Merge branch 'master' of https://github.com/tw93/pake
This commit is contained in:
@@ -93,7 +93,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
注意:Windows 下不能安装到 `C:\Program File`,会直接闪退,建议安装到其他非管理员权限目录,比如 `D:\Program Files (x86)` 。
|
||||
|
||||
## 命令行打包
|
||||
|
||||
|
||||
@@ -93,8 +93,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Note: it cannot be installed to `C:\Program File` under Windows, and it will crash directly. It is recommended to install to other non-administrator directories, such as `D:\Program Files (x86)`.
|
||||
|
||||
## Command line packing
|
||||
|
||||
<kbd>
|
||||
|
||||
2
bin/README.md
vendored
2
bin/README.md
vendored
@@ -4,7 +4,7 @@
|
||||
npm install -g pake-cli
|
||||
```
|
||||
|
||||
如果安装失败提示没有权限,请参考该贴解决:[链接](https://gist.github.com/Giancarlos/d087f8a9e6516716da98ad0c0f5a8f58),注意:**尽量别用 sudo 权限**。
|
||||
如果安装失败提示没有权限,请参考该贴解决:[链接](https://gist.github.com/Giancarlos/d087f8a9e6516716da98ad0c0f5a8f58),**或者使用 `sudo` 权限**。
|
||||
|
||||
## 用法
|
||||
|
||||
|
||||
4
bin/README_EN.md
vendored
4
bin/README_EN.md
vendored
@@ -4,7 +4,7 @@
|
||||
npm install -g pake-cli
|
||||
```
|
||||
|
||||
If the installation fails and you are prompted that you do not have permission, please see this [website](https://gist.github.com/Giancarlos/d087f8a9e6516716da98ad0c0f5a8f58) , attention! **try not to use sudo permissions**.
|
||||
If the installation fails and you are prompted that you do not have permission, please see this [website](https://gist.github.com/Giancarlos/d087f8a9e6516716da98ad0c0f5a8f58) , **or use `sudo` permissions**.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -34,7 +34,7 @@ The application name, if not specified when entering, will prompt you to enter,
|
||||
|
||||
#### [icon]
|
||||
|
||||
应用 icon,支持本地/远程文件,默认为 Pake 自带图标。
|
||||
The application icon, support local and remote files. The default is brand icon of Pake.
|
||||
|
||||
- MacOS must be `.icns`
|
||||
- Windows must be `.ico`
|
||||
|
||||
1
bin/builders/BuilderFactory.ts
vendored
1
bin/builders/BuilderFactory.ts
vendored
@@ -6,7 +6,6 @@ import LinuxBuilder from './LinuxBuilder.js';
|
||||
|
||||
export default class BuilderFactory {
|
||||
static create(): IBuilder {
|
||||
console.log("now platform is ", process.platform);
|
||||
if (IS_MAC) {
|
||||
return new MacBuilder();
|
||||
}
|
||||
|
||||
15
bin/builders/LinuxBuilder.ts
vendored
15
bin/builders/LinuxBuilder.ts
vendored
@@ -46,21 +46,6 @@ export default class LinuxBuilder implements IBuilder {
|
||||
const { name } = options;
|
||||
|
||||
await mergeTauriConfig(url, options, tauriConf);
|
||||
// write desktop
|
||||
const assertSrc = `src-tauri/assets/${name}.desktop`;
|
||||
const assertPath = path.join(npmDirectory, assertSrc);
|
||||
const desktopStr = `
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Categories=Office
|
||||
Exec=${name}
|
||||
Icon=${name}
|
||||
Name=${name}
|
||||
StartupNotify=true
|
||||
Terminal=false
|
||||
Type=Application
|
||||
`
|
||||
await fs.writeFile(assertPath, desktopStr);
|
||||
const _ = await shellExec(`cd ${npmDirectory} && npm install && npm run build`);
|
||||
let arch = "";
|
||||
if (process.arch === "x64") {
|
||||
|
||||
48
bin/builders/common.ts
vendored
48
bin/builders/common.ts
vendored
@@ -3,6 +3,7 @@ import prompts from 'prompts';
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
import { npmDirectory } from '@/utils/dir.js';
|
||||
import logger from '@/options/logger.js';
|
||||
|
||||
export async function promptText(message: string, initial?: string) {
|
||||
const response = await prompts({
|
||||
@@ -40,20 +41,41 @@ export async function mergeTauriConfig(
|
||||
Object.assign(tauriConf.tauri.windows[0], { url, ...tauriConfWindowOptions });
|
||||
tauriConf.package.productName = name;
|
||||
tauriConf.tauri.bundle.identifier = identifier;
|
||||
tauriConf.tauri.bundle.icon = [options.icon];
|
||||
if (process.platform === "win32") {
|
||||
const ico_path = path.join(npmDirectory, `src-tauri/png/${name.toLowerCase()}_32.ico`);
|
||||
tauriConf.tauri.bundle.resources = [`png/${name.toLowerCase()}_32.ico`];
|
||||
await fs.copyFile(options.icon, ico_path);
|
||||
}
|
||||
if (process.platform === "linux") {
|
||||
const installSrc = `/usr/share/applications/${name}.desktop`;
|
||||
const assertSrc = `src-tauri/assets/${name}.desktop`;
|
||||
const assertPath = path.join(npmDirectory, assertSrc);
|
||||
tauriConf.tauri.bundle.deb.files = {
|
||||
[installSrc]: assertPath
|
||||
const exists = await fs.stat(options.icon)
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
if (exists) {
|
||||
let updateIconPath = true;
|
||||
let customIconExt = path.extname(options.icon).toLowerCase();
|
||||
if (process.platform === "win32") {
|
||||
if (customIconExt === ".ico") {
|
||||
const ico_path = path.join(npmDirectory, `src-tauri/png/${name.toLowerCase()}_32.ico`);
|
||||
tauriConf.tauri.bundle.resources = [`png/${name.toLowerCase()}_32.ico`];
|
||||
await fs.copyFile(options.icon, ico_path);
|
||||
} else {
|
||||
updateIconPath = false;
|
||||
logger.warn(`icon file in Windows must be 256 * 256 pix with .ico type, but you give ${customIconExt}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === "linux") {
|
||||
delete tauriConf.tauri.bundle.deb.files;
|
||||
if (customIconExt != ".png") {
|
||||
updateIconPath = false;
|
||||
logger.warn(`icon file in Linux must be 512 * 512 pix with .png type, but you give ${customIconExt}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === "darwin" && customIconExt !== ".icns") {
|
||||
updateIconPath = false;
|
||||
logger.warn(`icon file in MacOS must be .icns type, but you give ${customIconExt}`);
|
||||
}
|
||||
if (updateIconPath) {
|
||||
tauriConf.tauri.bundle.icon = [options.icon];
|
||||
} else {
|
||||
logger.warn(`icon file will not change with default.`);
|
||||
}
|
||||
} else {
|
||||
logger.warn("the custom icon path may not exists. we will use default icon to replace it");
|
||||
}
|
||||
|
||||
|
||||
|
||||
17
bin/options/icon.ts
vendored
17
bin/options/icon.ts
vendored
@@ -4,8 +4,9 @@ import { PakeAppOptions } from '../types.js';
|
||||
import { dir } from 'tmp-promise';
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
import { fileURLToPath } from 'url';
|
||||
import logger from './logger.js';
|
||||
import { npmDirectory } from '@/utils/dir.js';
|
||||
import { IS_LINUX, IS_WIN } from '@/utils/platform.js';
|
||||
|
||||
export async function handleIcon(options: PakeAppOptions, url: string) {
|
||||
if (options.icon) {
|
||||
@@ -16,14 +17,20 @@ export async function handleIcon(options: PakeAppOptions, url: string) {
|
||||
}
|
||||
}
|
||||
if (!options.icon) {
|
||||
return inferIcon(options.name, url);
|
||||
return getDefaultIcon();
|
||||
}
|
||||
}
|
||||
|
||||
export async function inferIcon(name: string, url: string) {
|
||||
export async function getDefaultIcon() {
|
||||
logger.info('You have not provided an app icon, use the default icon.(use --icon option to assign an icon)')
|
||||
const npmDirectory = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
return path.join(npmDirectory, 'pake-default.icns');
|
||||
let iconPath = 'src-tauri/icons/icon.icns';
|
||||
if (IS_WIN) {
|
||||
iconPath = 'src-tauri/png/icon_256.ico';
|
||||
} else if (IS_LINUX) {
|
||||
iconPath = 'src-tauri/png/icon_512.png';
|
||||
}
|
||||
|
||||
return path.join(npmDirectory, iconPath);
|
||||
}
|
||||
|
||||
// export async function getIconFromPageUrl(url: string) {
|
||||
|
||||
130
dist/cli.js
vendored
130
dist/cli.js
vendored
@@ -6,11 +6,11 @@ import isurl from 'is-url';
|
||||
import prompts from 'prompts';
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
import chalk from 'chalk';
|
||||
import crypto from 'crypto';
|
||||
import axios from 'axios';
|
||||
import { fileTypeFromBuffer } from 'file-type';
|
||||
import { dir } from 'tmp-promise';
|
||||
import chalk from 'chalk';
|
||||
import ora from 'ora';
|
||||
import shelljs from 'shelljs';
|
||||
import updateNotifier from 'update-notifier';
|
||||
@@ -1593,6 +1593,24 @@ function validateUrlInput(url) {
|
||||
|
||||
const npmDirectory = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
|
||||
const logger = {
|
||||
info(...msg) {
|
||||
log.info(...msg.map((m) => chalk.blue.bold(m)));
|
||||
},
|
||||
debug(...msg) {
|
||||
log.debug(...msg);
|
||||
},
|
||||
error(...msg) {
|
||||
log.error(...msg.map((m) => chalk.red.bold(m)));
|
||||
},
|
||||
warn(...msg) {
|
||||
log.info(...msg.map((m) => chalk.yellow.bold(m)));
|
||||
},
|
||||
success(...msg) {
|
||||
log.info(...msg.map((m) => chalk.green.bold(m)));
|
||||
}
|
||||
};
|
||||
|
||||
function promptText(message, initial) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const response = yield prompts({
|
||||
@@ -1617,19 +1635,43 @@ function mergeTauriConfig(url, options, tauriConf) {
|
||||
Object.assign(tauriConf.tauri.windows[0], Object.assign({ url }, tauriConfWindowOptions));
|
||||
tauriConf.package.productName = name;
|
||||
tauriConf.tauri.bundle.identifier = identifier;
|
||||
tauriConf.tauri.bundle.icon = [options.icon];
|
||||
if (process.platform === "win32") {
|
||||
const ico_path = path.join(npmDirectory, `src-tauri/png/${name.toLowerCase()}_32.ico`);
|
||||
tauriConf.tauri.bundle.resources = [`png/${name.toLowerCase()}_32.ico`];
|
||||
yield fs.copyFile(options.icon, ico_path);
|
||||
const exists = yield fs.stat(options.icon)
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
if (exists) {
|
||||
let updateIconPath = true;
|
||||
let customIconExt = path.extname(options.icon).toLowerCase();
|
||||
if (process.platform === "win32") {
|
||||
if (customIconExt === ".ico") {
|
||||
const ico_path = path.join(npmDirectory, `src-tauri/png/${name.toLowerCase()}_32.ico`);
|
||||
tauriConf.tauri.bundle.resources = [`png/${name.toLowerCase()}_32.ico`];
|
||||
yield fs.copyFile(options.icon, ico_path);
|
||||
}
|
||||
else {
|
||||
updateIconPath = false;
|
||||
logger.warn(`icon file in Windows must be 256 * 256 pix with .ico type, but you give ${customIconExt}`);
|
||||
}
|
||||
}
|
||||
if (process.platform === "linux") {
|
||||
delete tauriConf.tauri.bundle.deb.files;
|
||||
if (customIconExt != ".png") {
|
||||
updateIconPath = false;
|
||||
logger.warn(`icon file in Linux must be 512 * 512 pix with .png type, but you give ${customIconExt}`);
|
||||
}
|
||||
}
|
||||
if (process.platform === "darwin" && customIconExt !== ".icns") {
|
||||
updateIconPath = false;
|
||||
logger.warn(`icon file in MacOS must be .icns type, but you give ${customIconExt}`);
|
||||
}
|
||||
if (updateIconPath) {
|
||||
tauriConf.tauri.bundle.icon = [options.icon];
|
||||
}
|
||||
else {
|
||||
logger.warn(`icon file will not change with default.`);
|
||||
}
|
||||
}
|
||||
if (process.platform === "linux") {
|
||||
const installSrc = `/usr/share/applications/${name}.desktop`;
|
||||
const assertSrc = `src-tauri/assets/${name}.desktop`;
|
||||
const assertPath = path.join(npmDirectory, assertSrc);
|
||||
tauriConf.tauri.bundle.deb.files = {
|
||||
[installSrc]: assertPath
|
||||
};
|
||||
else {
|
||||
logger.warn("the custom icon path may not exists. we will use default icon to replace it");
|
||||
}
|
||||
let configPath = "";
|
||||
switch (process.platform) {
|
||||
@@ -1660,23 +1702,9 @@ function getIdentifier(name, url) {
|
||||
return `pake-${postFixHash}`;
|
||||
}
|
||||
|
||||
const logger = {
|
||||
info(...msg) {
|
||||
log.info(...msg.map((m) => chalk.blue.bold(m)));
|
||||
},
|
||||
debug(...msg) {
|
||||
log.debug(...msg);
|
||||
},
|
||||
error(...msg) {
|
||||
log.error(...msg.map((m) => chalk.red.bold(m)));
|
||||
},
|
||||
warn(...msg) {
|
||||
log.info(...msg.map((m) => chalk.yellow.bold(m)));
|
||||
},
|
||||
success(...msg) {
|
||||
log.info(...msg.map((m) => chalk.green.bold(m)));
|
||||
}
|
||||
};
|
||||
const IS_MAC = process.platform === 'darwin';
|
||||
const IS_WIN = process.platform === 'win32';
|
||||
const IS_LINUX = process.platform === 'linux';
|
||||
|
||||
function handleIcon(options, url) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
@@ -1689,15 +1717,21 @@ function handleIcon(options, url) {
|
||||
}
|
||||
}
|
||||
if (!options.icon) {
|
||||
return inferIcon(options.name);
|
||||
return getDefaultIcon();
|
||||
}
|
||||
});
|
||||
}
|
||||
function inferIcon(name, url) {
|
||||
function getDefaultIcon() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
logger.info('You have not provided an app icon, use the default icon.(use --icon option to assign an icon)');
|
||||
const npmDirectory = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
return path.join(npmDirectory, 'pake-default.icns');
|
||||
let iconPath = 'src-tauri/icons/icon.icns';
|
||||
if (IS_WIN) {
|
||||
iconPath = 'src-tauri/png/icon_256.ico';
|
||||
}
|
||||
else if (IS_LINUX) {
|
||||
iconPath = 'src-tauri/png/icon_512.png';
|
||||
}
|
||||
return path.join(npmDirectory, iconPath);
|
||||
});
|
||||
}
|
||||
// export async function getIconFromPageUrl(url: string) {
|
||||
@@ -1773,10 +1807,6 @@ function handleOptions(options, url) {
|
||||
});
|
||||
}
|
||||
|
||||
const IS_MAC = process.platform === 'darwin';
|
||||
const IS_WIN = process.platform === 'win32';
|
||||
const IS_LINUX = process.platform === 'linux';
|
||||
|
||||
function shellExec(command) {
|
||||
return new Promise((resolve, reject) => {
|
||||
shelljs.exec(command, { async: true, silent: false }, (code) => {
|
||||
@@ -1870,7 +1900,8 @@ var tauri$2 = {
|
||||
wix: {
|
||||
language: [
|
||||
"en-US"
|
||||
]
|
||||
],
|
||||
template: "assets/main.wxs"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2092,21 +2123,6 @@ class LinuxBuilder {
|
||||
logger.debug('PakeAppOptions', options);
|
||||
const { name } = options;
|
||||
yield mergeTauriConfig(url, options, tauriConf);
|
||||
// write desktop
|
||||
const assertSrc = `src-tauri/assets/${name}.desktop`;
|
||||
const assertPath = path.join(npmDirectory, assertSrc);
|
||||
const desktopStr = `
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Categories=Office
|
||||
Exec=${name}
|
||||
Icon=${name}
|
||||
Name=${name}
|
||||
StartupNotify=true
|
||||
Terminal=false
|
||||
Type=Application
|
||||
`;
|
||||
yield fs.writeFile(assertPath, desktopStr);
|
||||
yield shellExec(`cd ${npmDirectory} && npm install && npm run build`);
|
||||
let arch = "";
|
||||
if (process.arch === "x64") {
|
||||
@@ -2137,7 +2153,6 @@ Type=Application
|
||||
|
||||
class BuilderFactory {
|
||||
static create() {
|
||||
console.log("now platform is ", process.platform);
|
||||
if (IS_MAC) {
|
||||
return new MacBuilder();
|
||||
}
|
||||
@@ -2152,7 +2167,7 @@ class BuilderFactory {
|
||||
}
|
||||
|
||||
var name = "pake-cli";
|
||||
var version = "0.1.1";
|
||||
var version = "0.1.2";
|
||||
var description = "🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App 🤱🏻 A simple way to make any web page a desktop application using Rust.";
|
||||
var bin = {
|
||||
pake: "./cli.js"
|
||||
@@ -2168,8 +2183,7 @@ var author = {
|
||||
var files = [
|
||||
"dist",
|
||||
"src-tauri",
|
||||
"cli.js",
|
||||
"pake-default.icns"
|
||||
"cli.js"
|
||||
];
|
||||
var scripts = {
|
||||
start: "npm run dev",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pake-cli",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"description": "🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App 🤱🏻 A simple way to make any web page a desktop application using Rust.",
|
||||
"bin": {
|
||||
"pake": "./cli.js"
|
||||
@@ -16,8 +16,7 @@
|
||||
"files": [
|
||||
"dist",
|
||||
"src-tauri",
|
||||
"cli.js",
|
||||
"pake-default.icns"
|
||||
"cli.js"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "npm run dev",
|
||||
|
||||
10
src-tauri/Cargo.lock
generated
10
src-tauri/Cargo.lock
generated
@@ -42,6 +42,7 @@ checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"home",
|
||||
"image",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -1105,6 +1106,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "html5ever"
|
||||
version = "0.25.2"
|
||||
|
||||
@@ -19,6 +19,7 @@ serde_json = "1.0.88"
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
tauri = { version = "1.2.1", features = [] }
|
||||
image = "0.24.5"
|
||||
home = "0.5"
|
||||
tauri-utils = "1.2.1"
|
||||
webbrowser = "0.8.2"
|
||||
wry = "0.23.1"
|
||||
|
||||
310
src-tauri/assets/main.wxs
Normal file
310
src-tauri/assets/main.wxs
Normal file
@@ -0,0 +1,310 @@
|
||||
<?if $(sys.BUILDARCH)="x86"?>
|
||||
<?define Win64 = "no" ?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
|
||||
<?elseif $(sys.BUILDARCH)="x64"?>
|
||||
<?define Win64 = "yes" ?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
|
||||
<?else?>
|
||||
<?error Unsupported value of sys.BUILDARCH=$(sys.BUILDARCH)?>
|
||||
<?endif?>
|
||||
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product
|
||||
Id="*"
|
||||
Name="{{{product_name}}}"
|
||||
UpgradeCode="{{{upgrade_code}}}"
|
||||
Language="!(loc.TauriLanguage)"
|
||||
Manufacturer="{{{manufacturer}}}"
|
||||
Version="{{{version}}}">
|
||||
|
||||
<Package Id="*"
|
||||
Keywords="Installer"
|
||||
InstallerVersion="450"
|
||||
Languages="0"
|
||||
Compressed="yes"
|
||||
InstallScope="perMachine"
|
||||
SummaryCodepage="!(loc.TauriCodepage)"/>
|
||||
|
||||
<!-- https://docs.microsoft.com/en-us/windows/win32/msi/reinstallmode -->
|
||||
<!-- reinstall all files; rewrite all registry entries; reinstall all shortcuts -->
|
||||
<Property Id="REINSTALLMODE" Value="amus" />
|
||||
|
||||
{{#if allow_downgrades}}
|
||||
<MajorUpgrade Schedule="afterInstallInitialize" AllowDowngrades="yes" />
|
||||
{{else}}
|
||||
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="!(loc.DowngradeErrorMessage)" AllowSameVersionUpgrades="yes" />
|
||||
{{/if}}
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<RemoveShortcuts>Installed AND NOT UPGRADINGPRODUCTCODE</RemoveShortcuts>
|
||||
</InstallExecuteSequence>
|
||||
|
||||
<Media Id="1" Cabinet="app.cab" EmbedCab="yes" />
|
||||
|
||||
{{#if banner_path}}
|
||||
<WixVariable Id="WixUIBannerBmp" Value="{{{banner_path}}}" />
|
||||
{{/if}}
|
||||
{{#if dialog_image_path}}
|
||||
<WixVariable Id="WixUIDialogBmp" Value="{{{dialog_image_path}}}" />
|
||||
{{/if}}
|
||||
{{#if license}}
|
||||
<WixVariable Id="WixUILicenseRtf" Value="{{{license}}}" />
|
||||
{{/if}}
|
||||
|
||||
<Icon Id="ProductIcon" SourceFile="{{{icon_path}}}"/>
|
||||
<Property Id="ARPPRODUCTICON" Value="ProductIcon" />
|
||||
<Property Id="ARPNOREPAIR" Value="yes" Secure="yes" /> <!-- Remove repair -->
|
||||
<SetProperty Id="ARPNOMODIFY" Value="1" After="InstallValidate" Sequence="execute"/>
|
||||
|
||||
<!-- initialize with previous InstallDir -->
|
||||
<Property Id="INSTALLDIR">
|
||||
<RegistrySearch Id="PrevInstallDirReg" Root="HKCU" Key="Software\\{{{manufacturer}}}\\{{{product_name}}}" Name="InstallDir" Type="raw"/>
|
||||
</Property>
|
||||
|
||||
<!-- launch app checkbox -->
|
||||
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="!(loc.LaunchApp)" />
|
||||
<Property Id="WixShellExecTarget" Value="[!Path]" />
|
||||
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
|
||||
|
||||
<UI>
|
||||
<!-- launch app checkbox -->
|
||||
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
|
||||
|
||||
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
|
||||
|
||||
{{#unless license}}
|
||||
<!-- Skip license dialog -->
|
||||
<Publish Dialog="WelcomeDlg"
|
||||
Control="Next"
|
||||
Event="NewDialog"
|
||||
Value="InstallDirDlg"
|
||||
Order="2">1</Publish>
|
||||
<Publish Dialog="InstallDirDlg"
|
||||
Control="Back"
|
||||
Event="NewDialog"
|
||||
Value="WelcomeDlg"
|
||||
Order="2">1</Publish>
|
||||
{{/unless}}
|
||||
</UI>
|
||||
|
||||
<UIRef Id="WixUI_InstallDir" />
|
||||
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="DesktopFolder" Name="Desktop">
|
||||
<Component Id="ApplicationShortcutDesktop" Guid="*">
|
||||
<Shortcut Id="ApplicationDesktopShortcut" Name="{{{product_name}}}" Description="Runs {{{product_name}}}" Target="[!Path]" WorkingDirectory="INSTALLDIR" />
|
||||
<RemoveFolder Id="DesktopFolder" On="uninstall" />
|
||||
<RegistryValue Root="HKCU" Key="Software\\{{{manufacturer}}}\\{{{product_name}}}" Name="Desktop Shortcut" Type="integer" Value="1" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
<Directory Id="$(var.PlatformProgramFilesFolder)" Name="PFiles">
|
||||
<Directory Id="INSTALLDIR" Name="{{{product_name}}}"/>
|
||||
</Directory>
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="{{{product_name}}}"/>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<DirectoryRef Id="INSTALLDIR">
|
||||
<Component Id="RegistryEntries" Guid="*">
|
||||
<RegistryKey Root="HKCU" Key="Software\\{{{manufacturer}}}\\{{{product_name}}}">
|
||||
<RegistryValue Name="InstallDir" Type="string" Value="[INSTALLDIR]" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
<Component Id="Path" Guid="{{{path_component_guid}}}" Win64="$(var.Win64)">
|
||||
<File Id="Path" Source="{{{app_exe_source}}}" KeyPath="yes" Checksum="yes"/>
|
||||
</Component>
|
||||
{{#each binaries as |bin| ~}}
|
||||
<Component Id="{{ bin.id }}" Guid="{{bin.guid}}" Win64="$(var.Win64)">
|
||||
<File Id="Bin_{{ bin.id }}" Source="{{bin.path}}" KeyPath="yes"/>
|
||||
</Component>
|
||||
{{/each~}}
|
||||
{{#if enable_elevated_update_task}}
|
||||
<Component Id="UpdateTask" Guid="C492327D-9720-4CD5-8DB8-F09082AF44BE" Win64="$(var.Win64)">
|
||||
<File Id="UpdateTask" Source="update.xml" KeyPath="yes" Checksum="yes"/>
|
||||
</Component>
|
||||
<Component Id="UpdateTaskInstaller" Guid="011F25ED-9BE3-50A7-9E9B-3519ED2B9932" Win64="$(var.Win64)">
|
||||
<File Id="UpdateTaskInstaller" Source="install-task.ps1" KeyPath="yes" Checksum="yes"/>
|
||||
</Component>
|
||||
<Component Id="UpdateTaskUninstaller" Guid="D4F6CC3F-32DC-5FD0-95E8-782FFD7BBCE1" Win64="$(var.Win64)">
|
||||
<File Id="UpdateTaskUninstaller" Source="uninstall-task.ps1" KeyPath="yes" Checksum="yes"/>
|
||||
</Component>
|
||||
{{/if}}
|
||||
{{{resources}}}
|
||||
<Component Id="CMP_UninstallShortcut" Guid="*">
|
||||
|
||||
<Shortcut Id="UninstallShortcut"
|
||||
Name="Uninstall {{{product_name}}}"
|
||||
Description="Uninstalls {{{product_name}}}"
|
||||
Target="[System64Folder]msiexec.exe"
|
||||
Arguments="/x [ProductCode]" />
|
||||
|
||||
<RemoveFolder Id="INSTALLDIR"
|
||||
On="uninstall" />
|
||||
|
||||
<RegistryValue Root="HKCU"
|
||||
Key="Software\\{{{manufacturer}}}\\{{{product_name}}}"
|
||||
Name="Uninstaller Shortcut"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||
<Component Id="ApplicationShortcut" Guid="*">
|
||||
<Shortcut Id="ApplicationStartMenuShortcut"
|
||||
Name="{{{product_name}}}"
|
||||
Description="Runs {{{product_name}}}"
|
||||
Target="[!Path]"
|
||||
Icon="ProductIcon"
|
||||
WorkingDirectory="INSTALLDIR">
|
||||
<ShortcutProperty Key="System.AppUserModel.ID" Value="{{{bundle_id}}}"/>
|
||||
</Shortcut>
|
||||
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
|
||||
<RegistryValue Root="HKCU" Key="Software\\{{{manufacturer}}}\\{{{product_name}}}" Name="Start Menu Shortcut" Type="integer" Value="1" KeyPath="yes"/>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
{{#each merge_modules as |msm| ~}}
|
||||
<DirectoryRef Id="TARGETDIR">
|
||||
<Merge Id="{{ msm.name }}" SourceFile="{{ msm.path }}" DiskId="1" Language="!(loc.TauriLanguage)" />
|
||||
</DirectoryRef>
|
||||
|
||||
<Feature Id="{{ msm.name }}" Title="{{ msm.name }}" AllowAdvertise="no" Display="hidden" Level="1">
|
||||
<MergeRef Id="{{ msm.name }}"/>
|
||||
</Feature>
|
||||
{{/each~}}
|
||||
|
||||
<Feature
|
||||
Id="MainProgram"
|
||||
Title="Application"
|
||||
Description="!(loc.InstallAppFeature)"
|
||||
Level="1"
|
||||
ConfigurableDirectory="INSTALLDIR"
|
||||
AllowAdvertise="no"
|
||||
Display="expand"
|
||||
Absent="disallow">
|
||||
|
||||
<ComponentRef Id="RegistryEntries"/>
|
||||
|
||||
{{#each resource_file_ids as |resource_file_id| ~}}
|
||||
<ComponentRef Id="{{ resource_file_id }}"/>
|
||||
{{/each~}}
|
||||
|
||||
{{#if enable_elevated_update_task}}
|
||||
<ComponentRef Id="UpdateTask" />
|
||||
<ComponentRef Id="UpdateTaskInstaller" />
|
||||
<ComponentRef Id="UpdateTaskUninstaller" />
|
||||
{{/if}}
|
||||
|
||||
<Feature Id="ShortcutsFeature"
|
||||
Title="Shortcuts"
|
||||
Level="1">
|
||||
<ComponentRef Id="Path"/>
|
||||
<ComponentRef Id="CMP_UninstallShortcut" />
|
||||
<ComponentRef Id="ApplicationShortcut" />
|
||||
<ComponentRef Id="ApplicationShortcutDesktop" />
|
||||
</Feature>
|
||||
|
||||
<Feature
|
||||
Id="Environment"
|
||||
Title="PATH Environment Variable"
|
||||
Description="!(loc.PathEnvVarFeature)"
|
||||
Level="1"
|
||||
Absent="allow">
|
||||
<ComponentRef Id="Path"/>
|
||||
{{#each binaries as |bin| ~}}
|
||||
<ComponentRef Id="{{ bin.id }}"/>
|
||||
{{/each~}}
|
||||
</Feature>
|
||||
</Feature>
|
||||
|
||||
<Feature Id="External" AllowAdvertise="no" Absent="disallow">
|
||||
{{#each component_group_refs as |id| ~}}
|
||||
<ComponentGroupRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
{{#each component_refs as |id| ~}}
|
||||
<ComponentRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
{{#each feature_group_refs as |id| ~}}
|
||||
<FeatureGroupRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
{{#each feature_refs as |id| ~}}
|
||||
<FeatureRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
{{#each merge_refs as |id| ~}}
|
||||
<MergeRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
</Feature>
|
||||
|
||||
{{#if install_webview}}
|
||||
<!-- WebView2 -->
|
||||
<Property Id="WVRTINSTALLED">
|
||||
<RegistrySearch Id="WVRTInstalledSystem" Root="HKLM" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw" Win64="no" />
|
||||
<RegistrySearch Id="WVRTInstalledUser" Root="HKCU" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw"/>
|
||||
</Property>
|
||||
|
||||
{{#if download_bootstrapper}}
|
||||
<CustomAction Id='DownloadAndInvokeBootstrapper' Directory="INSTALLDIR" Execute="deferred" ExeCommand='powershell.exe -NoProfile -windowstyle hidden try [\{] [\[]Net.ServicePointManager[\]]::SecurityProtocol = [\[]Net.SecurityProtocolType[\]]::Tls12 [\}] catch [\{][\}]; Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -OutFile "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" ; Start-Process -FilePath "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" -ArgumentList ({{{webview_installer_args}}} '/install') -Wait' Return='check'/>
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='DownloadAndInvokeBootstrapper' Before='InstallFinalize'>
|
||||
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
{{/if}}
|
||||
|
||||
<!-- Embedded webview bootstrapper mode -->
|
||||
{{#if webview2_bootstrapper_path}}
|
||||
<Binary Id="MicrosoftEdgeWebview2Setup.exe" SourceFile="{{{webview2_bootstrapper_path}}}"/>
|
||||
<CustomAction Id='InvokeBootstrapper' BinaryKey='MicrosoftEdgeWebview2Setup.exe' Execute="deferred" ExeCommand='{{{webview_installer_args}}} /install' Return='check' />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='InvokeBootstrapper' Before='InstallFinalize'>
|
||||
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
{{/if}}
|
||||
|
||||
<!-- Embedded offline installer -->
|
||||
{{#if webview2_installer_path}}
|
||||
<Binary Id="MicrosoftEdgeWebView2RuntimeInstaller.exe" SourceFile="{{{webview2_installer_path}}}"/>
|
||||
<CustomAction Id='InvokeStandalone' BinaryKey='MicrosoftEdgeWebView2RuntimeInstaller.exe' Execute="deferred" ExeCommand='{{{webview_installer_args}}} /install' Return='check' />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='InvokeStandalone' Before='InstallFinalize'>
|
||||
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
{{/if}}
|
||||
|
||||
{{/if}}
|
||||
|
||||
{{#if enable_elevated_update_task}}
|
||||
<!-- Install an elevated update task within Windows Task Scheduler -->
|
||||
<CustomAction
|
||||
Id="CreateUpdateTask"
|
||||
Return="check"
|
||||
Directory="INSTALLDIR"
|
||||
Execute="commit"
|
||||
Impersonate="yes"
|
||||
ExeCommand="powershell.exe -WindowStyle hidden .\install-task.ps1" />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='CreateUpdateTask' Before='InstallFinalize'>
|
||||
NOT(REMOVE)
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
<!-- Remove elevated update task during uninstall -->
|
||||
<CustomAction
|
||||
Id="DeleteUpdateTask"
|
||||
Return="check"
|
||||
Directory="INSTALLDIR"
|
||||
ExeCommand="powershell.exe -WindowStyle hidden .\uninstall-task.ps1" />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="DeleteUpdateTask" Before='InstallFinalize'>
|
||||
(REMOVE = "ALL") AND NOT UPGRADINGPRODUCTCODE
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
{{/if}}
|
||||
|
||||
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize"/>
|
||||
</Product>
|
||||
</Wix>
|
||||
@@ -23,7 +23,7 @@ use wry::application::{
|
||||
#[cfg(target_os = "windows")]
|
||||
use wry::application::window::Icon;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
use wry::webview::WebContext;
|
||||
|
||||
fn main() -> wry::Result<()> {
|
||||
@@ -147,35 +147,21 @@ fn main() -> wry::Result<()> {
|
||||
.with_back_forward_navigation_gestures(true)
|
||||
.build()?;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let webview = WebViewBuilder::new(window)?
|
||||
// .with_user_agent(user_agent_string)
|
||||
// .with_accept_first_mouse(true)
|
||||
.with_url(&url.to_string())?
|
||||
.with_devtools(cfg!(feature = "devtools"))
|
||||
.with_initialization_script(include_str!("pake.js"))
|
||||
.with_ipc_handler(handler)
|
||||
.build()?;
|
||||
|
||||
// 自定义cookie文件夹,仅用于Linux
|
||||
// Custom Cookie folder, only for Linux
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
let webview = {
|
||||
let user = std::env::var_os("USER");
|
||||
let config_path = match user {
|
||||
Some(v) => format!(
|
||||
"/home/{}/.config/{}",
|
||||
v.into_string().unwrap(),
|
||||
package_name,
|
||||
),
|
||||
None => panic!("can't found any user"),
|
||||
let home_dir = match home::home_dir() {
|
||||
Some(path1) => path1,
|
||||
None => panic!("Error, can't found you home dir!!"),
|
||||
};
|
||||
let data_path = std::path::PathBuf::from(&config_path);
|
||||
if !std::path::Path::new(&data_path).exists() {
|
||||
std::fs::create_dir(&data_path)
|
||||
.unwrap_or_else(|_| panic!("can't create dir {}", &config_path));
|
||||
#[cfg(target_os = "windows")]
|
||||
let data_dir = home_dir.join("AppData").join("Roaming").join(package_name);
|
||||
#[cfg(target_os = "linux")]
|
||||
let data_dir = home_dir.join(".config").join(package_name);
|
||||
if !data_dir.exists() {
|
||||
std::fs::create_dir(&data_dir)
|
||||
.unwrap_or_else(|_| panic!("can't create dir {}", data_dir.display()));
|
||||
}
|
||||
let mut web_content = WebContext::new(Some(data_path));
|
||||
let mut web_content = WebContext::new(Some(data_dir));
|
||||
WebViewBuilder::new(window)?
|
||||
// .with_user_agent(user_agent_string)
|
||||
.with_url(&url.to_string())?
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": "",
|
||||
"wix": {
|
||||
"language": ["en-US"]
|
||||
"language": ["en-US"],
|
||||
"template": "assets/main.wxs"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user