mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-15 18:02:58 +08:00
chore: Windows MSIX
This commit is contained in:
18
.github/workflows/linux.yml
vendored
18
.github/workflows/linux.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 1
|
||||||
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
@@ -59,11 +59,23 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: sudo chmod -R 777 ~/.gradle
|
run: sudo chmod -R 777 ~/.gradle
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload targz artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: termora-linux-${{ runner.arch }}
|
name: termora-linux-targz-${{ runner.arch }}
|
||||||
path: |
|
path: |
|
||||||
build/distributions/*.tar.gz
|
build/distributions/*.tar.gz
|
||||||
|
|
||||||
|
- name: Upload AppImage artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: termora-linux-AppImage-${{ runner.arch }}
|
||||||
|
path: |
|
||||||
build/distributions/*.AppImage
|
build/distributions/*.AppImage
|
||||||
|
|
||||||
|
- name: Upload deb artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: termora-linux-deb-${{ runner.arch }}
|
||||||
|
path: |
|
||||||
build/distributions/*.deb
|
build/distributions/*.deb
|
||||||
|
|||||||
12
.github/workflows/osx.yml
vendored
12
.github/workflows/osx.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 1
|
||||||
|
|
||||||
- name: Install the Apple certificate
|
- name: Install the Apple certificate
|
||||||
if: "startsWith(github.event.head_commit.message, 'release: ') && github.repository == 'TermoraDev/termora' && env.BUILD_CERTIFICATE_BASE64 != ''"
|
if: "startsWith(github.event.head_commit.message, 'release: ') && github.repository == 'TermoraDev/termora' && env.BUILD_CERTIFICATE_BASE64 != ''"
|
||||||
@@ -93,10 +93,16 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: ./gradlew :jpackage && ./gradlew :dist
|
run: ./gradlew :jpackage && ./gradlew :dist
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload zip artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: termora-osx-${{ runner.arch }}
|
name: termora-osx-zip-${{ runner.arch }}
|
||||||
path: |
|
path: |
|
||||||
build/distributions/*.zip
|
build/distributions/*.zip
|
||||||
|
|
||||||
|
- name: Upload dmg artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: termora-osx-dmg-${{ runner.arch }}
|
||||||
|
path: |
|
||||||
build/distributions/*.dmg
|
build/distributions/*.dmg
|
||||||
|
|||||||
49
.github/workflows/windows.yml
vendored
49
.github/workflows/windows.yml
vendored
@@ -11,11 +11,14 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ windows-11-arm, windows-latest ]
|
os: [ windows-11-arm, windows-2022 ]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Setup MSbuild
|
||||||
|
uses: microsoft/setup-msbuild@v2
|
||||||
|
|
||||||
- name: Set architecture
|
- name: Set architecture
|
||||||
id: set-arch
|
id: set-arch
|
||||||
@@ -26,6 +29,24 @@ jobs:
|
|||||||
echo "ARCH=x64" >> $env:GITHUB_ENV
|
echo "ARCH=x64" >> $env:GITHUB_ENV
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- name: Find MakeAppx
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$installedRootsKey = "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
|
||||||
|
$kitsRoot = (Get-ItemProperty $installedRootsKey).KitsRoot10
|
||||||
|
$versions = Get-ChildItem -Path $installedRootsKey | Select-Object -ExpandProperty PSChildName
|
||||||
|
$maxVersion = $versions | ForEach-Object { [version]$_ } | Sort-Object -Descending | Select-Object -First 1
|
||||||
|
$arch = if ($env:ARCH -eq "aarch64") { "arm64" } else { "x64" }
|
||||||
|
$makeAppXPath = Join-Path -Path $kitsRoot -ChildPath "bin\$maxVersion\$arch\makeappx.exe"
|
||||||
|
Write-Output "MakeAppx.exe path: $makeAppXPath"
|
||||||
|
|
||||||
|
if (Test-Path $makeAppXPath) {
|
||||||
|
"MAKEAPPX_PATH=$makeAppXPath" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
} else {
|
||||||
|
Write-Output "MakeAppx.exe not found!"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
- name: Install zip
|
- name: Install zip
|
||||||
run: |
|
run: |
|
||||||
$system32 = [System.Environment]::GetEnvironmentVariable("WINDIR") + "\System32"
|
$system32 = [System.Environment]::GetEnvironmentVariable("WINDIR") + "\System32"
|
||||||
@@ -63,13 +84,33 @@ jobs:
|
|||||||
- name: Package
|
- name: Package
|
||||||
run: .\gradlew :jpackage && .\gradlew :dist
|
run: .\gradlew :jpackage && .\gradlew :dist
|
||||||
|
|
||||||
|
- name: MSIX
|
||||||
|
env:
|
||||||
|
TERMORA_TYPE: appx
|
||||||
|
run: |
|
||||||
|
.\gradlew --stop
|
||||||
|
.\gradlew :dist
|
||||||
|
|
||||||
- name: Stop Gradle
|
- name: Stop Gradle
|
||||||
run: .\gradlew.bat --stop
|
run: .\gradlew.bat --stop
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload zip artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: termora-windows-${{ runner.arch }}
|
name: termora-windows-zip-${{ runner.arch }}
|
||||||
path: |
|
path: |
|
||||||
build/distributions/*.zip
|
build/distributions/*.zip
|
||||||
|
|
||||||
|
- name: Upload exe artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: termora-windows-exe-${{ runner.arch }}
|
||||||
|
path: |
|
||||||
build/distributions/*.exe
|
build/distributions/*.exe
|
||||||
|
|
||||||
|
- name: Upload msix artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: termora-windows-msix-${{ runner.arch }}
|
||||||
|
path: |
|
||||||
|
build/distributions/*.msix
|
||||||
|
|||||||
303
build.gradle.kts
303
build.gradle.kts
@@ -1,3 +1,4 @@
|
|||||||
|
import org.apache.tools.ant.filters.ReplaceTokens
|
||||||
import org.gradle.internal.jvm.Jvm
|
import org.gradle.internal.jvm.Jvm
|
||||||
import org.gradle.kotlin.dsl.support.uppercaseFirstChar
|
import org.gradle.kotlin.dsl.support.uppercaseFirstChar
|
||||||
import org.gradle.nativeplatform.platform.internal.ArchitectureInternal
|
import org.gradle.nativeplatform.platform.internal.ArchitectureInternal
|
||||||
@@ -28,7 +29,9 @@ version = rootProject.projectDir.resolve("VERSION").readText().trim()
|
|||||||
val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem()
|
val os: OperatingSystem = DefaultNativePlatform.getCurrentOperatingSystem()
|
||||||
val arch: ArchitectureInternal = DefaultNativePlatform.getCurrentArchitecture()
|
val arch: ArchitectureInternal = DefaultNativePlatform.getCurrentArchitecture()
|
||||||
val appVersion = project.version.toString().split("-")[0]
|
val appVersion = project.version.toString().split("-")[0]
|
||||||
|
val makeAppx = if (os.isWindows) StringUtils.defaultString(System.getenv("MAKEAPPX_PATH")) else StringUtils.EMPTY
|
||||||
val isDeb = os.isLinux && System.getenv("TERMORA_TYPE") == "deb"
|
val isDeb = os.isLinux && System.getenv("TERMORA_TYPE") == "deb"
|
||||||
|
val isAppx = os.isWindows && makeAppx.isNotBlank() && System.getenv("TERMORA_TYPE") == "appx"
|
||||||
|
|
||||||
// macOS 签名信息
|
// macOS 签名信息
|
||||||
val macOSSignUsername = System.getenv("TERMORA_MAC_SIGN_USER_NAME") ?: StringUtils.EMPTY
|
val macOSSignUsername = System.getenv("TERMORA_MAC_SIGN_USER_NAME") ?: StringUtils.EMPTY
|
||||||
@@ -169,102 +172,145 @@ publishing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.processResources {
|
||||||
|
filesMatching("**/AppxManifest.xml") {
|
||||||
|
filter<ReplaceTokens>(
|
||||||
|
"tokens" to mapOf(
|
||||||
|
"version" to appVersion,
|
||||||
|
"architecture" to if (arch.isArm64) "arm64" else "x64",
|
||||||
|
"projectDir" to project.projectDir.absolutePath,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("CascadeIf")
|
||||||
tasks.register<Copy>("copy-dependencies") {
|
tasks.register<Copy>("copy-dependencies") {
|
||||||
val dir = layout.buildDirectory.dir("libs")
|
val dir = layout.buildDirectory.dir("libs")
|
||||||
from(configurations.runtimeClasspath).into(dir)
|
from(configurations.runtimeClasspath).into(dir)
|
||||||
val jna = libs.jna.asProvider().get()
|
val jna = libs.jna.asProvider().get()
|
||||||
val pty4j = libs.pty4j.get()
|
val pty4j = libs.pty4j.get()
|
||||||
val flatlaf = libs.flatlaf.get()
|
val flatlaf = libs.flatlaf.get()
|
||||||
val jSerialComm = libs.jSerialComm.get()
|
|
||||||
val restart4j = libs.restart4j.get()
|
val restart4j = libs.restart4j.get()
|
||||||
val sqlite = libs.sqlite.get()
|
val sqlite = libs.sqlite.get()
|
||||||
|
val archName = if (arch.isArm) "aarch64" else "x86_64"
|
||||||
|
val dylib = dir.get().dir("dylib").asFile
|
||||||
|
|
||||||
// 对 JNA 和 PTY4J 的本地库提取
|
doLast {
|
||||||
// 提取出来是为了单独签名,不然无法通过公证
|
for (file in dir.get().asFile.listFiles() ?: emptyArray()) {
|
||||||
if (os.isMacOsX) {
|
if ("${jna.name}-${jna.version}" == file.nameWithoutExtension) {
|
||||||
doLast {
|
val targetDir = File(dylib, jna.name)
|
||||||
val archName = if (arch.isArm) "aarch64" else "x86_64"
|
FileUtils.forceMkdir(targetDir)
|
||||||
val dylib = dir.get().dir("dylib").asFile
|
if (os.isWindows) {
|
||||||
for (file in dir.get().asFile.listFiles() ?: emptyArray()) {
|
// @formatter:off
|
||||||
if ("${jna.name}-${jna.version}" == file.nameWithoutExtension) {
|
exec { commandLine("unzip","-j","-o", file.absolutePath, "com/sun/jna/win32-${arch.name}/*", "-d", targetDir.absolutePath) }
|
||||||
val targetDir = File(dylib, jna.name)
|
// @formatter:on
|
||||||
FileUtils.forceMkdir(targetDir)
|
} else if (os.isLinux) {
|
||||||
|
// @formatter:off
|
||||||
|
exec { commandLine("unzip","-j","-o", file.absolutePath, "com/sun/jna/linux-${arch.name}/*", "-d", targetDir.absolutePath) }
|
||||||
|
// @formatter:on
|
||||||
|
} else if (os.isMacOsX) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
exec { commandLine("unzip","-j","-o", file.absolutePath, "com/sun/jna/darwin-${arch.name}/*", "-d", targetDir.absolutePath) }
|
exec { commandLine("unzip","-j","-o", file.absolutePath, "com/sun/jna/darwin-${arch.name}/*", "-d", targetDir.absolutePath) }
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
// 删除所有二进制类库
|
}
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/darwin-*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-*") }
|
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-*") }
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/sunos-*") }
|
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/linux-*") }
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/openbsd-*") }
|
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/darwin-*") }
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/linux-*") }
|
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/sunos-*") }
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/freebsd-*") }
|
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/openbsd-*") }
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/dragonflybsd-*") }
|
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/freebsd-*") }
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/aix-*") }
|
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/dragonflybsd-*") }
|
||||||
} else if ("${pty4j.name}-${pty4j.version}" == file.nameWithoutExtension) {
|
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/aix-*") }
|
||||||
val targetDir = FileUtils.getFile(dylib, pty4j.name, "darwin")
|
} else if ("${pty4j.name}-${pty4j.version}" == file.nameWithoutExtension) {
|
||||||
FileUtils.forceMkdir(targetDir)
|
val targetDir = FileUtils.getFile(dylib, pty4j.name, if (os.isWindows) "win32" else "linux")
|
||||||
|
FileUtils.forceMkdir(targetDir)
|
||||||
|
val myArchName = if (arch.isArm) "aarch64" else "x86-64"
|
||||||
|
if (os.isWindows) {
|
||||||
|
// @formatter:off
|
||||||
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "resources/*win/${myArchName}/*", "-d", targetDir.absolutePath) }
|
||||||
|
// @formatter:on
|
||||||
|
} else if (os.isLinux) {
|
||||||
|
// @formatter:off
|
||||||
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "resources/*linux/${myArchName}/*", "-d", targetDir.absolutePath) }
|
||||||
|
// @formatter:on
|
||||||
|
} else if (os.isMacOsX) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "resources/com/pty4j/native/darwin*", "-d", targetDir.absolutePath) }
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "resources/com/pty4j/native/darwin*", "-d", targetDir.absolutePath) }
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
// 删除所有二进制类库
|
}
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*") }
|
exec { commandLine("zip", "-d", file.absolutePath, "resources/*") }
|
||||||
} else if ("${jSerialComm.name}-${jSerialComm.version}" == file.nameWithoutExtension) {
|
} else if ("${restart4j.name}-${restart4j.version}" == file.nameWithoutExtension) {
|
||||||
val targetDir = FileUtils.getFile(dylib, jSerialComm.name, "OSX", archName)
|
val targetDir = FileUtils.getFile(dylib, restart4j.name)
|
||||||
FileUtils.forceMkdir(targetDir)
|
FileUtils.forceMkdir(targetDir)
|
||||||
|
if (os.isWindows) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "OSX/${archName}/*", "-d", targetDir.absolutePath) }
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "win32/${archName}/*", "-d", targetDir.absolutePath) }
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
// 删除所有二进制类库
|
} else if (os.isLinux) {
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "Android/*") }
|
// @formatter:off
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "FreeBSD/*") }
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "linux/${archName}/*", "-d", targetDir.absolutePath) }
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "Linux/*") }
|
// @formatter:on
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "OpenBSD/*") }
|
} else if (os.isMacOsX) {
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "OSX/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "Solaris/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "Windows/*") }
|
|
||||||
} else if ("${restart4j.name}-${restart4j.version}" == file.nameWithoutExtension) {
|
|
||||||
val targetDir = FileUtils.getFile(dylib, restart4j.name)
|
|
||||||
FileUtils.forceMkdir(targetDir)
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "darwin/${archName}/*", "-d", targetDir.absolutePath) }
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "darwin/${archName}/*", "-d", targetDir.absolutePath) }
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
// 删除所有二进制类库
|
}
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "win32/*") }
|
// 设置可执行权限
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "darwin/*") }
|
for (e in FileUtils.listFiles(
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "linux/*") }
|
targetDir,
|
||||||
// 设置可执行权限
|
FileFilterUtils.trueFileFilter(),
|
||||||
for (e in FileUtils.listFiles(
|
FileFilterUtils.falseFileFilter()
|
||||||
targetDir,
|
)) e.setExecutable(true)
|
||||||
FileFilterUtils.trueFileFilter(),
|
exec { commandLine("zip", "-d", file.absolutePath, "win32/*") }
|
||||||
FileFilterUtils.falseFileFilter()
|
exec { commandLine("zip", "-d", file.absolutePath, "darwin/*") }
|
||||||
)) {
|
exec { commandLine("zip", "-d", file.absolutePath, "linux/*") }
|
||||||
e.setExecutable(true)
|
} else if ("${sqlite.name}-${sqlite.version}" == file.nameWithoutExtension) {
|
||||||
}
|
val targetDir = FileUtils.getFile(dylib, sqlite.name)
|
||||||
} else if ("${sqlite.name}-${sqlite.version}" == file.nameWithoutExtension) {
|
FileUtils.forceMkdir(targetDir)
|
||||||
val targetDir = FileUtils.getFile(dylib, sqlite.name)
|
if (os.isWindows) {
|
||||||
FileUtils.forceMkdir(targetDir)
|
// @formatter:off
|
||||||
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "org/sqlite/native/Windows/${archName}/*", "-d", targetDir.absolutePath) }
|
||||||
|
// @formatter:on
|
||||||
|
} else if (os.isLinux) {
|
||||||
|
// @formatter:off
|
||||||
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "org/sqlite/native/Linux/${archName}/*", "-d", targetDir.absolutePath) }
|
||||||
|
// @formatter:on
|
||||||
|
} else if (os.isMacOsX) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "org/sqlite/native/Mac/${archName}/*", "-d", targetDir.absolutePath) }
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "org/sqlite/native/Mac/${archName}/*", "-d", targetDir.absolutePath) }
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
// 删除所有二进制类库
|
}
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/*") }
|
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/*") }
|
||||||
} else if ("${flatlaf.name}-${flatlaf.version}" == file.nameWithoutExtension) {
|
} else if ("${flatlaf.name}-${flatlaf.version}" == file.nameWithoutExtension) {
|
||||||
val targetDir = FileUtils.getFile(dylib, flatlaf.name)
|
val targetDir = FileUtils.getFile(dylib, flatlaf.name)
|
||||||
FileUtils.forceMkdir(targetDir)
|
FileUtils.forceMkdir(targetDir)
|
||||||
val isArm = arch.isArm
|
val isArm = arch.isArm
|
||||||
|
if (os.isWindows) {
|
||||||
|
// @formatter:off
|
||||||
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "com/formdev/flatlaf/natives/*windows*${if (isArm) "arm64" else "x86_64"}*", "-d", targetDir.absolutePath) }
|
||||||
|
// @formatter:on
|
||||||
|
} else if (os.isLinux) {
|
||||||
|
// @formatter:off
|
||||||
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "com/formdev/flatlaf/natives/*linux*${if (isArm) "arm64" else "x86_64"}*", "-d", targetDir.absolutePath) }
|
||||||
|
// @formatter:on
|
||||||
|
} else if (os.isMacOsX) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "com/formdev/flatlaf/natives/*macos*${if (isArm) "arm" else "x86"}*", "-d", targetDir.absolutePath) }
|
exec { commandLine("unzip", "-j" , "-o", file.absolutePath, "com/formdev/flatlaf/natives/*macos*${if (isArm) "arm" else "x86"}*", "-d", targetDir.absolutePath) }
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*") }
|
|
||||||
}
|
}
|
||||||
|
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*") }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 对二进制签名
|
// 对二进制签名
|
||||||
|
if (os.isMacOsX) {
|
||||||
Files.walk(dylib.toPath()).use { paths ->
|
Files.walk(dylib.toPath()).use { paths ->
|
||||||
for (path in paths) {
|
for (path in paths) {
|
||||||
if (Files.isRegularFile(path)) {
|
if (Files.isRegularFile(path)) {
|
||||||
@@ -273,116 +319,8 @@ tasks.register<Copy>("copy-dependencies") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (os.isLinux || os.isWindows) { // 缩减安装包
|
|
||||||
doLast {
|
|
||||||
for (file in dir.get().asFile.listFiles() ?: emptyArray()) {
|
|
||||||
if ("${jna.name}-${jna.version}" == file.nameWithoutExtension) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/darwin-*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/sunos-*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/openbsd-*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/freebsd-*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/dragonflybsd-*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/aix-*") }
|
|
||||||
if (os.isWindows) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/linux-*") }
|
|
||||||
if (arch.isArm) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-x86*") }
|
|
||||||
} else {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-aarch64/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-x86/*") }
|
|
||||||
}
|
|
||||||
} else if (os.isLinux) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/sun/jna/win32-*") }
|
|
||||||
}
|
|
||||||
} else if ("${pty4j.name}-${pty4j.version}" == file.nameWithoutExtension) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*darwin*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*freebsd*") }
|
|
||||||
if (os.isWindows) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*linux*") }
|
|
||||||
if (arch.isArm) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win/x86/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win/x86-64*") }
|
|
||||||
} else {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win/x86/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win/aarch64/*") }
|
|
||||||
}
|
|
||||||
} else if (os.isLinux) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "resources/*win*") }
|
|
||||||
}
|
|
||||||
} else if ("${jSerialComm.name}-${jSerialComm.version}" == file.nameWithoutExtension) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "Android/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "FreeBSD/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "OpenBSD/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "OSX/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "Solaris/*") }
|
|
||||||
if (os.isWindows) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "Linux/*") }
|
|
||||||
} else if (os.isLinux) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "Windows/*") }
|
|
||||||
}
|
|
||||||
} else if ("${restart4j.name}-${restart4j.version}" == file.nameWithoutExtension) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "darwin/*") }
|
|
||||||
if (os.isWindows) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "linux/*") }
|
|
||||||
if (arch.isArm) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "win32/x86_64/*") }
|
|
||||||
} else {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "win32/aarch64/*") }
|
|
||||||
}
|
|
||||||
} else if (os.isLinux) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "win32/*") }
|
|
||||||
if (arch.isArm) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "linux/x86_64/*") }
|
|
||||||
} else {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "linux/aarch64/*") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ("${sqlite.name}-${sqlite.version}" == file.nameWithoutExtension) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux-*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/FreeBSD/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Mac/*") }
|
|
||||||
if (os.isWindows) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/armv7/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/x86/*") }
|
|
||||||
if (arch.isArm) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/x86_64/*") }
|
|
||||||
} else {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/aarch64/*") }
|
|
||||||
}
|
|
||||||
} else if (os.isLinux) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Windows/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/arm*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/ppc64/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/riscv64/*") }
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/x86/*") }
|
|
||||||
if (arch.isArm) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/x86_64/*") }
|
|
||||||
} else {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "org/sqlite/native/Linux/aarch64/*") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ("${flatlaf.name}-${flatlaf.version}" == file.nameWithoutExtension) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*macos*") }
|
|
||||||
if (os.isWindows) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*linux*") }
|
|
||||||
if (arch.isArm) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*x86*") }
|
|
||||||
} else {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*x86.dll") }
|
|
||||||
}
|
|
||||||
} else if (os.isLinux) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*windows*") }
|
|
||||||
if (arch.isArm) {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*x86*") }
|
|
||||||
} else {
|
|
||||||
exec { commandLine("zip", "-d", file.absolutePath, "com/formdev/flatlaf/natives/*arm*") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register<Exec>("jlink") {
|
tasks.register<Exec>("jlink") {
|
||||||
@@ -568,6 +506,27 @@ fun packOnWindows(distributionDir: Directory, finalFilenameWithoutExtension: Str
|
|||||||
val cfg = FileUtils.getFile(dir, projectName, "app", "${projectName}.cfg")
|
val cfg = FileUtils.getFile(dir, projectName, "app", "${projectName}.cfg")
|
||||||
val configText = cfg.readText()
|
val configText = cfg.readText()
|
||||||
|
|
||||||
|
// appx
|
||||||
|
if (isAppx) {
|
||||||
|
cfg.writeText(StringBuilder(configText).appendLine("java-options=-Djpackage.app-layout=appx").toString())
|
||||||
|
val appxManifest = FileUtils.getFile(dir, projectName, "AppxManifest.xml")
|
||||||
|
layout.buildDirectory.file("resources/main/AppxManifest.xml").get().asFile
|
||||||
|
.renameTo(appxManifest)
|
||||||
|
val icons = setOf("termora.png", "termora_44x44.png", "termora_150x150.png")
|
||||||
|
for (file in projectDir.resolve("src/main/resources/icons/").listFiles()) {
|
||||||
|
if (icons.contains(file.name)) {
|
||||||
|
val p = appxManifest.parentFile.resolve("icons/${file.name}")
|
||||||
|
FileUtils.forceMkdirParent(p)
|
||||||
|
file.copyTo(p, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exec {
|
||||||
|
commandLine(makeAppx, "pack", "/d", projectName, "/p", "${finalFilenameWithoutExtension}.msix")
|
||||||
|
workingDir = dir
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// zip
|
// zip
|
||||||
cfg.writeText(StringBuilder(configText).appendLine("java-options=-Djpackage.app-layout=zip").toString())
|
cfg.writeText(StringBuilder(configText).appendLine("java-options=-Djpackage.app-layout=zip").toString())
|
||||||
exec {
|
exec {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ enum class AppLayout {
|
|||||||
*/
|
*/
|
||||||
Zip,
|
Zip,
|
||||||
Exe,
|
Exe,
|
||||||
|
Appx,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* macOS
|
* macOS
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ object Application {
|
|||||||
return AppLayout.Exe
|
return AppLayout.Exe
|
||||||
} else if ("zip" == layout) {
|
} else if ("zip" == layout) {
|
||||||
return AppLayout.Zip
|
return AppLayout.Zip
|
||||||
|
} else if ("appx" == layout) {
|
||||||
|
return AppLayout.Appx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,14 +16,8 @@ class ApplicationInitializr {
|
|||||||
|
|
||||||
fun run() {
|
fun run() {
|
||||||
|
|
||||||
// 由于 macOS 签名和公证问题,依赖二进制依赖会单独在一个文件夹
|
// 依赖二进制依赖会单独在一个文件夹
|
||||||
if (SystemUtils.IS_OS_MAC_OSX) {
|
setupNativeLibraries()
|
||||||
setupNativeLibraries()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemUtils.IS_OS_MAC_OSX) {
|
|
||||||
System.setProperty("apple.awt.application.name", Application.getName())
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置 tinylog
|
// 设置 tinylog
|
||||||
setupTinylog()
|
setupTinylog()
|
||||||
@@ -31,6 +25,11 @@ class ApplicationInitializr {
|
|||||||
// 检查是否单例
|
// 检查是否单例
|
||||||
checkSingleton()
|
checkSingleton()
|
||||||
|
|
||||||
|
|
||||||
|
if (SystemUtils.IS_OS_MAC_OSX) {
|
||||||
|
System.setProperty("apple.awt.application.name", Application.getName())
|
||||||
|
}
|
||||||
|
|
||||||
// 启动
|
// 启动
|
||||||
val runtime = measureTimeMillis { ApplicationRunner().run() }
|
val runtime = measureTimeMillis { ApplicationRunner().run() }
|
||||||
val log = LoggerFactory.getLogger(javaClass)
|
val log = LoggerFactory.getLogger(javaClass)
|
||||||
@@ -42,23 +41,29 @@ class ApplicationInitializr {
|
|||||||
|
|
||||||
|
|
||||||
private fun setupNativeLibraries() {
|
private fun setupNativeLibraries() {
|
||||||
if (!SystemUtils.IS_OS_MAC_OSX) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val appPath = Application.getAppPath()
|
val appPath = Application.getAppPath()
|
||||||
if (StringUtils.isBlank(appPath)) {
|
if (StringUtils.isBlank(appPath)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val contents = File(appPath).parentFile?.parentFile ?: return
|
var contents = File(appPath)
|
||||||
|
if (SystemUtils.IS_OS_MAC_OSX || SystemUtils.IS_OS_LINUX) {
|
||||||
|
contents = contents.parentFile?.parentFile ?: return
|
||||||
|
if (SystemUtils.IS_OS_LINUX) {
|
||||||
|
contents = File(contents, "lib")
|
||||||
|
}
|
||||||
|
} else if (SystemUtils.IS_OS_WINDOWS) {
|
||||||
|
contents = contents.parentFile ?: return
|
||||||
|
}
|
||||||
|
|
||||||
val dylib = FileUtils.getFile(contents, "app", "dylib")
|
val dylib = FileUtils.getFile(contents, "app", "dylib")
|
||||||
if (!dylib.exists()) {
|
if (dylib.exists().not()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val jna = FileUtils.getFile(dylib, "jna")
|
val jna = FileUtils.getFile(dylib, "jna")
|
||||||
if (jna.exists()) {
|
if (jna.exists()) {
|
||||||
|
System.setProperty("jna.nounpack", "true")
|
||||||
System.setProperty("jna.boot.library.path", jna.absolutePath)
|
System.setProperty("jna.boot.library.path", jna.absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +77,10 @@ class ApplicationInitializr {
|
|||||||
System.setProperty("jSerialComm.library.path", jSerialComm.absolutePath)
|
System.setProperty("jSerialComm.library.path", jSerialComm.absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
val restart4j = FileUtils.getFile(dylib, "restart4j", "restarter")
|
val restart4j = FileUtils.getFile(
|
||||||
|
dylib, "restart4j",
|
||||||
|
if (SystemUtils.IS_OS_WINDOWS) "restarter.exe" else "restarter"
|
||||||
|
)
|
||||||
if (restart4j.exists()) {
|
if (restart4j.exists()) {
|
||||||
System.setProperty("restarter.path", restart4j.absolutePath)
|
System.setProperty("restarter.path", restart4j.absolutePath)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import com.sun.jna.platform.win32.WinDef.*
|
|||||||
import com.sun.jna.platform.win32.WinError
|
import com.sun.jna.platform.win32.WinError
|
||||||
import com.sun.jna.platform.win32.WinUser.*
|
import com.sun.jna.platform.win32.WinUser.*
|
||||||
import com.sun.jna.platform.win32.Wtsapi32
|
import com.sun.jna.platform.win32.Wtsapi32
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import java.nio.channels.FileChannel
|
import java.nio.channels.FileChannel
|
||||||
import java.nio.channels.FileLock
|
import java.nio.channels.FileLock
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
@@ -95,7 +94,6 @@ class ApplicationSingleton private constructor() : Disposable {
|
|||||||
private class Win32HelperWindow private constructor() : Runnable {
|
private class Win32HelperWindow private constructor() : Runnable {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val log = LoggerFactory.getLogger(Win32HelperWindow::class.java)
|
|
||||||
private val WindowClass = "${Application.getName()}HelperWindowClass"
|
private val WindowClass = "${Application.getName()}HelperWindowClass"
|
||||||
private val WindowName =
|
private val WindowName =
|
||||||
"${Application.getName()} hidden helper window, used only to catch the windows events"
|
"${Application.getName()} hidden helper window, used only to catch the windows events"
|
||||||
@@ -166,24 +164,15 @@ class ApplicationSingleton private constructor() : Disposable {
|
|||||||
override fun callback(hwnd: HWND, uMsg: Int, wParam: WPARAM, lParam: LPARAM): LRESULT {
|
override fun callback(hwnd: HWND, uMsg: Int, wParam: WPARAM, lParam: LPARAM): LRESULT {
|
||||||
when (uMsg) {
|
when (uMsg) {
|
||||||
WM_CREATE -> {
|
WM_CREATE -> {
|
||||||
if (log.isDebugEnabled) {
|
|
||||||
log.debug("win32 helper window created")
|
|
||||||
}
|
|
||||||
return LRESULT()
|
return LRESULT()
|
||||||
}
|
}
|
||||||
|
|
||||||
TICK -> {
|
TICK -> {
|
||||||
if (log.isDebugEnabled) {
|
|
||||||
log.debug("win32 helper window tick")
|
|
||||||
}
|
|
||||||
onTick()
|
onTick()
|
||||||
return LRESULT()
|
return LRESULT()
|
||||||
}
|
}
|
||||||
|
|
||||||
WM_DESTROY -> {
|
WM_DESTROY -> {
|
||||||
if (log.isDebugEnabled) {
|
|
||||||
log.debug("win32 helper window destroyed")
|
|
||||||
}
|
|
||||||
User32.INSTANCE.PostQuitMessage(0)
|
User32.INSTANCE.PostQuitMessage(0)
|
||||||
return LRESULT()
|
return LRESULT()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ import org.apache.commons.io.FileUtils
|
|||||||
import org.apache.commons.lang3.StringUtils
|
import org.apache.commons.lang3.StringUtils
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.awt.Component
|
import java.awt.Component
|
||||||
|
import java.awt.Window
|
||||||
import java.awt.event.WindowEvent
|
import java.awt.event.WindowEvent
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import javax.swing.JDialog
|
||||||
import javax.swing.JOptionPane
|
import javax.swing.JOptionPane
|
||||||
import javax.swing.SwingUtilities
|
import javax.swing.SwingUtilities
|
||||||
import kotlin.jvm.optionals.getOrNull
|
import kotlin.jvm.optionals.getOrNull
|
||||||
@@ -121,11 +123,22 @@ class TermoraRestarter {
|
|||||||
|
|
||||||
val instance = TermoraFrameManager.getInstance()
|
val instance = TermoraFrameManager.getInstance()
|
||||||
for (window in instance.getWindows()) {
|
for (window in instance.getWindows()) {
|
||||||
|
disposeChildren(window)
|
||||||
window.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSED))
|
window.dispatchEvent(WindowEvent(window, WindowEvent.WINDOW_CLOSED))
|
||||||
}
|
}
|
||||||
Disposer.dispose(instance)
|
Disposer.dispose(instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun disposeChildren(window: Window) {
|
||||||
|
for (win in Window.getWindows()) {
|
||||||
|
if (win is JDialog) {
|
||||||
|
if (win.owner == window) {
|
||||||
|
disposeChildren(win)
|
||||||
|
}
|
||||||
|
win.dispatchEvent(WindowEvent(win, WindowEvent.WINDOW_CLOSED))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkIsSupported(): Boolean {
|
private fun checkIsSupported(): Boolean {
|
||||||
val appPath = Application.getAppPath()
|
val appPath = Application.getAppPath()
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
package app.termora.plugin.internal.update
|
package app.termora.plugin.internal.update
|
||||||
|
|
||||||
import app.termora.Application
|
import app.termora.*
|
||||||
import app.termora.Application.httpClient
|
import app.termora.Application.httpClient
|
||||||
import app.termora.ApplicationScope
|
|
||||||
import app.termora.Disposable
|
|
||||||
import app.termora.UpdaterManager
|
|
||||||
import com.formdev.flatlaf.util.SystemInfo
|
import com.formdev.flatlaf.util.SystemInfo
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
@@ -32,6 +29,7 @@ internal class Updater private constructor() : Disposable {
|
|||||||
private val updaterManager get() = UpdaterManager.getInstance()
|
private val updaterManager get() = UpdaterManager.getInstance()
|
||||||
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||||
private var isRemindMeNextTime = false
|
private var isRemindMeNextTime = false
|
||||||
|
private val disabledUpdater get() = Application.getLayout() == AppLayout.Appx
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 安装包位置
|
* 安装包位置
|
||||||
@@ -39,6 +37,14 @@ internal class Updater private constructor() : Disposable {
|
|||||||
private var pkg: LatestPkg? = null
|
private var pkg: LatestPkg? = null
|
||||||
|
|
||||||
fun scheduleUpdate() {
|
fun scheduleUpdate() {
|
||||||
|
|
||||||
|
if (disabledUpdater) {
|
||||||
|
if (coroutineScope.isActive) {
|
||||||
|
coroutineScope.cancel()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
coroutineScope.launch(Dispatchers.IO) {
|
||||||
// 启动 3 分钟后才是检查
|
// 启动 3 分钟后才是检查
|
||||||
if (Application.isUnknownVersion().not()) {
|
if (Application.isUnknownVersion().not()) {
|
||||||
@@ -66,6 +72,9 @@ internal class Updater private constructor() : Disposable {
|
|||||||
|
|
||||||
private fun checkUpdate() {
|
private fun checkUpdate() {
|
||||||
|
|
||||||
|
// Windows 应用商店
|
||||||
|
if (disabledUpdater) return
|
||||||
|
|
||||||
val latestVersion = updaterManager.fetchLatestVersion()
|
val latestVersion = updaterManager.fetchLatestVersion()
|
||||||
if (latestVersion.isSelf) {
|
if (latestVersion.isSelf) {
|
||||||
return
|
return
|
||||||
|
|||||||
40
src/main/resources/AppxManifest.xml
Normal file
40
src/main/resources/AppxManifest.xml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<Package
|
||||||
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||||
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||||
|
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||||
|
IgnorableNamespaces="uap rescap">
|
||||||
|
|
||||||
|
<Identity Name="TermoraDev.Termora"
|
||||||
|
Publisher="CN=C804E131-4368-4BF7-9E7F-95C681AD0AAC"
|
||||||
|
Version="@version@.0"
|
||||||
|
ProcessorArchitecture="@architecture@"/>
|
||||||
|
|
||||||
|
<Properties>
|
||||||
|
<DisplayName>Termora</DisplayName>
|
||||||
|
<PublisherDisplayName>TermoraDev</PublisherDisplayName>
|
||||||
|
<Logo>icons\termora.png</Logo>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Resources>
|
||||||
|
<Resource Language="en-US"/>
|
||||||
|
</Resources>
|
||||||
|
|
||||||
|
<Dependencies>
|
||||||
|
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.26100.0"/>
|
||||||
|
</Dependencies>
|
||||||
|
|
||||||
|
<Applications>
|
||||||
|
<Application Id="Termora" Executable="Termora.exe" EntryPoint="Windows.FullTrustApplication">
|
||||||
|
<uap:VisualElements
|
||||||
|
DisplayName="Termora"
|
||||||
|
Description="Termora is a cross-platform terminal emulator and SSH client, available on Windows, macOS, and Linux"
|
||||||
|
BackgroundColor="transparent"
|
||||||
|
Square150x150Logo="icons\termora_150x150.png"
|
||||||
|
Square44x44Logo="icons\termora_44x44.png"/>
|
||||||
|
</Application>
|
||||||
|
</Applications>
|
||||||
|
|
||||||
|
<Capabilities>
|
||||||
|
<rescap:Capability Name="runFullTrust"/>
|
||||||
|
</Capabilities>
|
||||||
|
</Package>
|
||||||
BIN
src/main/resources/icons/termora_150x150.png
Normal file
BIN
src/main/resources/icons/termora_150x150.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
BIN
src/main/resources/icons/termora_44x44.png
Normal file
BIN
src/main/resources/icons/termora_44x44.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Reference in New Issue
Block a user