diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index 7c0135a2..27531e8b 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -7,9 +7,10 @@ on:
branches: [main]
jobs:
- build:
- runs-on: windows-latest
-
+ build-windows:
+ runs-on: windows-2022
+ outputs:
+ version-number: ${{ steps.version.outputs.number}}
steps:
- uses: actions/checkout@v4
- name: Download config repo
@@ -66,9 +67,6 @@ jobs:
$version = $version -replace "\+.*", ""
Write-Output "number=$version" >> $env:GITHUB_OUTPUT
shell: pwsh
- - name: Publish Linux 64bit
- if: ${{ github.event_name != 'pull_request' }}
- run: dotnet publish --os linux --arch x64 -c Release --self-contained false src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
- name: Publish Multiplayer Server
if: ${{ github.event_name != 'pull_request' }}
run: dotnet publish -c Release --self-contained false src//TrackerCouncil.Smz3.Multiplayer.Server//TrackerCouncil.Smz3.Multiplayer.Server.csproj
@@ -76,11 +74,6 @@ jobs:
if: ${{ github.event_name != 'pull_request' }}
run: '"%programfiles(x86)%/Inno Setup 6/iscc.exe" "setup/randomizer.app.iss"'
shell: cmd
- - name: Building the Linux 64bit package
- if: ${{ github.event_name != 'pull_request' }}
- working-directory: setup
- run: "./LinuxBuildZipper.ps1"
- shell: pwsh
- name: Building the Multiplayer Server package
if: ${{ github.event_name != 'pull_request' }}
working-directory: setup
@@ -91,26 +84,105 @@ jobs:
if: ${{ github.event_name != 'pull_request' }}
with:
path: "setup/Output/*"
- name: SMZ3CasRandomizer_${{ steps.version.outputs.number }}
+ name: SMZ3CasRandomizerWindows
+
+ build-linux:
+ runs-on: ubuntu-22.04
+ needs: [build-windows]
+ permissions:
+ contents: write
+ steps:
+ - uses: actions/checkout@v4
+ - name: Download config repo
+ uses: actions/checkout@v4
+ if: ${{ github.event_name != 'pull_request' }}
+ with:
+ repository: TheTrackerCouncil/SMZ3CasConfigs
+ path: configs
+ ref: main
+ - name: Download sprite repo
+ uses: actions/checkout@v4
+ if: ${{ github.event_name != 'pull_request' }}
+ with:
+ repository: TheTrackerCouncil/SMZ3CasSprites
+ path: sprites
+ ref: main
+ - name: Download tracker sprite repo
+ uses: actions/checkout@v4
+ if: ${{ github.event_name != 'pull_request' }}
+ with:
+ repository: TheTrackerCouncil/TrackerSprites
+ path: trackersprites
+ ref: main
+ - name: Download git trees
+ if: ${{ github.event_name != 'pull_request' }}
+ shell: pwsh
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ $headers = @{
+ Authorization="Bearer $Env:GH_TOKEN"
+ }
+ Invoke-RestMethod -Uri https://api.github.com/repos/TheTrackerCouncil/SMZ3CasSprites/git/trees/main?recursive=1 -OutFile sprites/Sprites/sprites.json -Headers $headers
+ Invoke-RestMethod -Uri https://api.github.com/repos/TheTrackerCouncil/TrackerSprites/git/trees/main?recursive=1 -OutFile trackersprites/tracker-sprites.json -Headers $headers
+ Remove-Item -LiteralPath "trackersprites/.git" -Force -Recurse
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ if: ${{ github.event_name != 'pull_request' }}
+ with:
+ dotnet-version: 8.0.x
+ - name: Update VersionOverride in source file
+ if: ${{ github.event_name != 'pull_request' }}
+ run: |
+ pwd
+ VERSION="${{ needs.build-windows.outputs.version-number }}"
+ BASE_VERSION="${VERSION%%-*}"
+ FILE="src/TrackerCouncil.Smz3.UI/App.axaml.cs"
+ sed -i -E "s|^[[:space:]]*private static readonly string\?[[:space:]]+s_versionOverride[[:space:]]*=[[:space:]]*null;|private static readonly string? s_versionOverride = \"${VERSION}\";|" "$FILE"
+ sed -i "s/^AppVersionRelease *= *.*/AppVersionRelease = ${BASE_VERSION}/" setup/AppImage.pupnet.conf
+ echo "Updated VersionOverride to: ${VERSION}"
+ - name: Install PupNet
+ run: dotnet tool install -g KuiperZone.PupNet
+ if: ${{ github.event_name != 'pull_request' }}
+ - name: Download AppImageTool
+ if: ${{ github.event_name != 'pull_request' }}
+ run: |
+ wget -P "$HOME/.local/bin" "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
+ chmod +x "$HOME/.local/bin/appimagetool-x86_64.AppImage"
+ appimagetool-x86_64.AppImage --version
+ - name: Run PupNet
+ if: ${{ github.event_name != 'pull_request' }}
+ run: |
+ chmod +x setup/AppImageBundleFiles.sh
+ pupnet setup/AppImage.pupnet.conf --kind appimage -y
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ if: ${{ github.event_name != 'pull_request' }}
+ with:
+ path: "setup/Output/SMZ3CasRandomizer.x86_64*"
+ name: SMZ3CasRandomizerLinux
+
build-mac:
runs-on: macos-latest
- if: ${{ github.event_name != 'pull_request' }}
steps:
- uses: actions/checkout@v4
- name: Download config repo
uses: actions/checkout@v4
+ if: ${{ github.event_name != 'pull_request' }}
with:
repository: TheTrackerCouncil/SMZ3CasConfigs
path: configs
ref: main
- name: Download sprite repo
uses: actions/checkout@v4
+ if: ${{ github.event_name != 'pull_request' }}
with:
repository: TheTrackerCouncil/SMZ3CasSprites
path: sprites
ref: main
- name: Download tracker sprite repo
uses: actions/checkout@v4
+ if: ${{ github.event_name != 'pull_request' }}
with:
repository: TheTrackerCouncil/TrackerSprites
path: trackersprites
@@ -129,16 +201,21 @@ jobs:
Remove-Item -LiteralPath "trackersprites/.git" -Force -Recurse
- name: Setup .NET
uses: actions/setup-dotnet@v4
+ if: ${{ github.event_name != 'pull_request' }}
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
+ if: ${{ github.event_name != 'pull_request' }}
- name: Build
run: dotnet build --no-restore -p:PostBuildEvent= src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
+ if: ${{ github.event_name != 'pull_request' }}
- name: Publish
run: dotnet publish -r osx-arm64 --configuration Release -p:UseAppHost=true src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
+ if: ${{ github.event_name != 'pull_request' }}
- name: Get version number
id: version
+ if: ${{ github.event_name != 'pull_request' }}
run: |
$version = (Get-Item "src\TrackerCouncil.Smz3.UI\bin\Release\net8.0\osx-arm64\publish\SMZ3CasRandomizer.dll").VersionInfo.ProductVersion
$version = $version -replace "\+.*", ""
@@ -147,11 +224,56 @@ jobs:
Write-Output "number=$version" >> $env:GITHUB_OUTPUT
shell: pwsh
- name: Prepare packaging script
+ if: ${{ github.event_name != 'pull_request' }}
run: |
chmod +x ./setup/package-macos-app.sh
./setup/package-macos-app.sh "${{ steps.version.outputs.number }}"
- name: Upload artifact
+ if: ${{ github.event_name != 'pull_request' }}
uses: actions/upload-artifact@v4
with:
path: "setup/output/*"
- name: SMZ3CasRandomizerMacOS_${{ steps.version.outputs.number }}
+ name: SMZ3CasRandomizerMacOS
+
+ package:
+ runs-on: ubuntu-22.04
+
+ needs: [build-windows, build-linux, build-mac]
+
+ permissions:
+ contents: write
+
+ steps:
+ - uses: actions/download-artifact@v5
+ if: ${{ github.event_name != 'pull_request' }}
+ with:
+ name: SMZ3CasRandomizerWindows
+ path: out
+ - uses: actions/download-artifact@v5
+ if: ${{ github.event_name != 'pull_request' }}
+ with:
+ name: SMZ3CasRandomizerLinux
+ path: out
+ - uses: actions/download-artifact@v5
+ if: ${{ github.event_name != 'pull_request' }}
+ with:
+ name: SMZ3CasRandomizerMacOS
+ path: out
+ - name: Extract some files
+ if: ${{ github.event_name != 'pull_request' }}
+ run: |
+ ls -alR
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ if: ${{ github.event_name != 'pull_request' }}
+ with:
+ path: "out/*"
+ name: SMZ3CasRandomizer_${{ needs.build-windows.outputs.version-number }}
+ - name: Delete old artifacts
+ if: ${{ github.event_name != 'pull_request' }}
+ uses: geekyeggo/delete-artifact@v5
+ with:
+ name: |
+ SMZ3CasRandomizerWindows
+ SMZ3CasRandomizerLinux
+ SMZ3CasRandomizerMacOS
diff --git a/.gitignore b/.gitignore
index 5ce039ca..a7b21a13 100644
--- a/.gitignore
+++ b/.gitignore
@@ -345,7 +345,7 @@ healthchecksdb
/Randomizer.CLI/Properties/launchSettings.json
/WebRandomizer/randomizer.db
/asar/
-setup/Output/
+[Ss]etup/[Oo]utput/
patch-config*
**/.DS_Store
**/*.db
diff --git a/setup/AppImage.pupnet.conf b/setup/AppImage.pupnet.conf
new file mode 100644
index 00000000..18f3662c
--- /dev/null
+++ b/setup/AppImage.pupnet.conf
@@ -0,0 +1,200 @@
+################################################################################
+# PUPNET DEPLOY: 1.9.0
+################################################################################
+
+########################################
+# APP PREAMBLE
+########################################
+
+# Mandatory application base name. This MUST BE the base name of the main executable file. It should NOT
+# include any directory part or extension, i.e. do not append '.exe' or '.dll'. It should not contain
+# spaces or invalid filename characters.
+AppBaseName = SMZ3CasRandomizer
+
+# Mandatory application friendly name.
+AppFriendlyName = "SMZ3 Cas' Randomizer"
+
+# Mandatory application ID in reverse DNS form. The value should stay constant for lifetime of the software.
+AppId = org.trackercouncil.smz3
+
+# Mandatory application version and package release of form: 'VERSION[RELEASE]'. Use optional square
+# brackets to denote package release, i.e. '1.2.3[1]'. Release refers to a change to the deployment
+# package, rather the application. If release part is absent (i.e. '1.2.3'), the release value defaults
+# to '1'. Note that the version-release value given here may be overridden from the command line.
+AppVersionRelease = 1.0.0
+
+# Mandatory single line application summary text in default (English) language.
+AppShortSummary = "Casual standalone version of the SMZ3 randomizer"
+
+# Multi-line (surround with triple """ quotes) application description which provides longer explanation
+# than AppShortSummary in default language. Optional but it is recommended to specify this. Text
+# separated by an empty line will be treated as separate paragraphs. Avoid complex formatting, and do not
+# use HTML or markdown, other than list items beginning with "* ", "+ " or "- ". This content is
+# used by package builders where supported, including RPM and DEB, and is used to populate the
+# ${APPSTREAM_DESCRIPTION_XML} element used within AppStream metadata.
+AppDescription = """
+ UI application for selecting, randomizing, and shuffling MSUs for various rom hacks and randomizers.
+"""
+
+# Mandatory application license ID. This should be one of the recognized SPDX license
+# identifiers, such as: 'MIT', 'GPL-3.0-or-later' or 'Apache-2.0'. For a proprietary or
+# custom license, use 'LicenseRef-Proprietary' or 'LicenseRef-LICENSE'.
+AppLicenseId = MIT
+
+# Optional path to application copyright/license text file. If provided, it will be packaged with the
+# application and used with package builders where supported.
+AppLicenseFile = ../LICENSE
+
+# Optional path to application changelog file. IMPORTANT. If given, this file should contain version
+# information in a predefined format. Namely, it should contain one or more version headings of form:
+# '+ VERSION;DATE', under which are to be listed change items of form: '- Change description'. Formatted
+# information will be parsed and used to expand the ${APPSTREAM_CHANGELOG_XML} macro used
+# for AppStream metadata (superfluous text is ignored, so the file may also contain README information).
+# The given file will also be packaged with the application verbatim. See: https://github.com/kuiperzone/PupNet-Deploy.
+AppChangeFile =
+
+########################################
+# PUBLISHER
+########################################
+
+# Mandatory publisher, group or creator name.
+PublisherName = The Tracker Council
+
+# Publisher ID in reverse DNS form. Invariably, this would be the same as AppId, excluding the app leaf
+# name. The value populates the ${PUBLISHER_ID} macro used AppStream metainfo. If omitted, defaults to
+# the leading parts of AppId. It is highly recommended to specify the value explicitly.
+PublisherId = org.trackercouncil
+
+# Optional copyright statement.
+PublisherCopyright =
+
+# Optional publisher or application web-link name. Note that Windows Setup packages
+# require both PublisherLinkName and PublisherLinkUrl in order to include the link as
+# an item in program menu entries. Do not modify name, as may leave old entries in updated installations.
+PublisherLinkName = Home Page
+
+# Publisher or application web-link URL. Although optional, it should be considered mandatory if using
+# MetaFile
+PublisherLinkUrl = https://github.com/TheTrackerCouncil
+
+# Publisher or maintainer email contact. Although optional, some package builders (i.e. DEB) require it
+# and may warn or fail unless provided.
+PublisherEmail =
+
+########################################
+# DESKTOP INTEGRATION
+########################################
+
+# Boolean (true or false) which indicates whether the application is hidden on the desktop. It is used to
+# populate the 'NoDisplay' field of the .desktop file. The default is false. Setting to true will also
+# cause the main application start menu entry to be omitted for Windows Setup.
+DesktopNoDisplay = false
+
+# Boolean (true or false) which indicates whether the application runs in the terminal, rather than
+# providing a GUI. It is used to populate the 'Terminal' field of the .desktop file.
+DesktopTerminal = false
+
+# Optional path to a Linux desktop file. If empty (default), one will be generated automatically from
+# the information in this file. Supplying a custom file, however, allows for mime-types and
+# internationalisation. If supplied, the file MUST contain the line: 'Exec=${INSTALL_EXEC}'
+# in order to use the correct install location. Other macros may be used to help automate the content.
+# Note. PupNet Deploy can generate you a desktop file. Use --help and 'pupnet --help macro' for reference.
+# See: https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
+DesktopFile = Smz3CasRandomizer.desktop
+
+# Optional command name to start the application from the terminal. If, for example, AppBaseName is
+# 'Zone.Kuiper.HelloWorld', the value here may be set to a simpler and/or lower-case variant such as
+# 'helloworld'. It must not contain spaces or invalid filename characters. Do not add any extension such
+# as '.exe'. If empty, the application will not be in the path and cannot be started from the command line.
+# For Windows Setup packages, see also SetupCommandPrompt. StartCommand is not
+# supported for all packages kinds (i.e. Flatpak). Default is empty (none).
+StartCommand = SMZ3CasRandomizer
+
+# Optional category for the application. The value should be one of the recognized Freedesktop top-level
+# categories, such as: Audio, Development, Game, Office, Utility etc. Only a single value should be
+# provided here which will be used, where supported, to populate metadata. The default is empty.
+# See: https://specifications.freedesktop.org/menu-spec/latest/apa.html
+PrimeCategory = Game
+
+# Path to AppStream metadata file. It is optional, but recommended as it is used by software centers.
+# Note. The contents of the files may use macro variables. Use 'pupnet --help macro' for reference.
+# See: https://docs.appimage.org/packaging-guide/optional/appstream.html
+MetaFile = app.metainfo.xml
+
+# Optional icon file paths. The value may include multiple filenames separated with semicolon or given
+# in multi-line form. Valid types are SVG, PNG and ICO (ICO ignored on Linux). Note that the inclusion
+# of a scalable SVG is preferable on Linux, whereas PNGs must be one of the standard sizes and MUST
+# include the size in the filename in the form: name.32x32.png' or 'name.32.png'.
+IconFiles = """
+ Icons/icon.512.png
+ Icons/icon.256.png
+ Icons/icon.128.png
+ Icons/icon.64.png
+ Icons/icon.48.png
+ Icons/icon.32.png
+ Icons/icon.24.png
+ Icons/icon.16.png
+ Icons/icon.svg
+"""
+
+########################################
+# DOTNET PUBLISH
+########################################
+
+# Optional path relative to this file in which to find the dotnet project (.csproj) file, or the
+# directory containing it. If empty (default), a single project file is expected under the same
+# directory as this file. IMPORTANT. If set to 'NONE', dotnet publish is disabled
+# (i.e. not called). Instead, only DotnetPostPublish is called.
+DotnetProjectPath = ../src/TrackerCouncil.Smz3.UI
+
+# Optional arguments supplied to 'dotnet publish'. Do NOT include '-r' (runtime), or '-c' (configuration)
+# here as they will be added according to command line arguments. Typically you want as a minimum:
+# '-p:Version=${APP_VERSION} --self-contained true'. Additional useful arguments include:
+# '-p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishReadyToRun=true
+# -p:PublishTrimmed=true -p:TrimMode=link'. Note. This value may use macro variables. Use 'pupnet --help macro'
+# for reference. See: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish
+DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false
+
+DotnetPostPublish = AppImageBundleFiles.sh
+
+########################################
+# PACKAGE OUTPUT
+########################################
+
+# Optional package name (excludes version etc.). If empty, defaults to AppBaseName. However, it is
+# used not only to specify the base output filename, but to identify the application in DEB and RPM
+# packages. You may wish, therefore, to ensure that the value represents a unique name. Naming
+# requirements are strict and must contain only alpha-numeric and '-', '+' and '.' characters.
+PackageName = SMZ3CasRandomizer
+
+# Output directory, or subdirectory relative to this file. It will be created if it does not exist and
+# will contain the final deploy output files. If empty, it defaults to the location of this file.
+OutputDirectory = Output
+
+########################################
+# APPIMAGE OPTIONS
+########################################
+
+# Additional arguments for use with appimagetool, i.e. '--no-appstream' to disable pedantic metadata checking.
+# Use for signing with '--sign'. Default is empty.
+AppImageArgs =
+
+# Optional path to AppImage fuse runtime(s), but not to be confused with .NET runtime ID. If AppImageRuntimePath is
+# left empty (default), appimagetool will download the latest runtime automatically. Specifying a path here avoids
+# the need for an internet connection during build, and fixes the runtime version. If AppImageRuntimePath
+# points to a file, the value is supplied directly to appimagetool using '--runtime-file'. If it points to a
+# directory, the directory should contain expected runtimes, which will be selected for the target architecture,
+# namely one of: runtime-aarch64, runtime-armhf, runtime-i686 or runtime-x86_64. Runtimes can be downloaded:
+# https://github.com/AppImage/type2-runtime/releases
+AppImageRuntimePath =
+
+# Boolean (true or false) which sets whether to include the application version in the AppImage filename,
+# i.e. 'HelloWorld-1.2.3-x86_64.AppImage'. Default is false. It is ignored if the output filename is
+# specified at command line.
+AppImageVersionOutput = false
+
+
+FlatpakPlatformRuntime = 1.0.0
+FlatpakPlatformSdk = 1.0.0
+FlatpakPlatformVersion = 1.0.0
+SetupMinWindowsVersion = 1.0.0
\ No newline at end of file
diff --git a/setup/AppImageBundleFiles.sh b/setup/AppImageBundleFiles.sh
new file mode 100755
index 00000000..3db6346e
--- /dev/null
+++ b/setup/AppImageBundleFiles.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+echo "BUILD_ARCH: ${BUILD_ARCH}"
+echo "BUILD_TARGET: ${BUILD_TARGET}"
+echo "BUILD_SHARE: ${BUILD_SHARE}"
+echo "BUILD_APP_BIN: ${BUILD_APP_BIN}"
+
+mkdir ${BUILD_APP_BIN}/DefaultData
+mv sprites/Sprites ${BUILD_APP_BIN}/DefaultData/Sprites
+mv trackersprites ${BUILD_APP_BIN}/DefaultData/TrackerSprites
+mv configs/Profiles ${BUILD_APP_BIN}/DefaultData/Configs
+mv configs/Schemas ${BUILD_APP_BIN}/DefaultData/Schemas
+
+UNIQUE_ID=$(uuidgen)
+echo "$UNIQUE_ID" >> ${BUILD_APP_BIN}/DefaultData/id.txt
+
+ls -al ${BUILD_APP_BIN}/DefaultData
+
diff --git a/setup/Icons/icon.128.png b/setup/Icons/icon.128.png
new file mode 100644
index 00000000..0e00092c
Binary files /dev/null and b/setup/Icons/icon.128.png differ
diff --git a/setup/Icons/icon.16.png b/setup/Icons/icon.16.png
new file mode 100644
index 00000000..dc3aa62b
Binary files /dev/null and b/setup/Icons/icon.16.png differ
diff --git a/setup/Icons/icon.24.png b/setup/Icons/icon.24.png
new file mode 100644
index 00000000..7673c827
Binary files /dev/null and b/setup/Icons/icon.24.png differ
diff --git a/setup/Icons/icon.256.png b/setup/Icons/icon.256.png
new file mode 100644
index 00000000..65a7dfee
Binary files /dev/null and b/setup/Icons/icon.256.png differ
diff --git a/setup/Icons/icon.32.png b/setup/Icons/icon.32.png
new file mode 100644
index 00000000..43eef33e
Binary files /dev/null and b/setup/Icons/icon.32.png differ
diff --git a/setup/Icons/icon.48.png b/setup/Icons/icon.48.png
new file mode 100644
index 00000000..d996d473
Binary files /dev/null and b/setup/Icons/icon.48.png differ
diff --git a/setup/Icons/icon.512.png b/setup/Icons/icon.512.png
new file mode 100644
index 00000000..9597031b
Binary files /dev/null and b/setup/Icons/icon.512.png differ
diff --git a/setup/Icons/icon.64.png b/setup/Icons/icon.64.png
new file mode 100644
index 00000000..2ce6b7ac
Binary files /dev/null and b/setup/Icons/icon.64.png differ
diff --git a/setup/Icons/icon.svg b/setup/Icons/icon.svg
new file mode 100644
index 00000000..33e06e2e
--- /dev/null
+++ b/setup/Icons/icon.svg
@@ -0,0 +1,83 @@
+
+
diff --git a/setup/LinuxBuildZipper.ps1 b/setup/LinuxBuildZipper.ps1
deleted file mode 100644
index 72f04eb2..00000000
--- a/setup/LinuxBuildZipper.ps1
+++ /dev/null
@@ -1,60 +0,0 @@
-$parentFolder = Split-Path -parent $PSScriptRoot
-
-# Get publish folder
-$folder = "$parentFolder\src\TrackerCouncil.Smz3.UI\bin\Release\net8.0\linux-x64\publish"
-$winFolder = "$parentFolder\src\TrackerCouncil.Smz3.UI\bin\Release\net8.0\win-x86\publish"
-if (-not (Test-Path $folder))
-{
- $folder = "$parentFolder\src\TrackerCouncil.Smz3.UI\bin\Release\net8.0\publish\linux-x64"
- $winFolder = "$parentFolder\src\TrackerCouncil.Smz3.UI\bin\Release\net8.0\publish\win-x86"
-}
-
-# Get version number from TrackerCouncil.Smz3.UI
-$version = "0.0.0"
-if (Test-Path "$winFolder\TrackerCouncil.Smz3.UI.exe") {
- $version = (Get-Item "$winFolder\SMZ3CasRandomizer.exe").VersionInfo.ProductVersion
-}
-else {
- $version = (Get-Item "$folder\SMZ3CasRandomizer.dll").VersionInfo.ProductVersion
-}
-$version = $version -replace "\+.*", ""
-
-# Setup default data folder
-$dataFolder = "$folder\DefaultData"
-New-Item -Path "$dataFolder" -ItemType Directory -Force
-
-# Copy sprites to be bundled together
-if (Test-Path -LiteralPath "$dataFolder\Sprites") {
- Remove-Item -LiteralPath "$dataFolder\Sprites" -Recurse
-}
-Copy-Item "$parentFolder\sprites\Sprites\" -Destination "$dataFolder\Sprites" -Recurse
-
-# Copy tracker sprites to be bundled together
-if (Test-Path -LiteralPath "$dataFolder\TrackerSprites") {
- Remove-Item -LiteralPath "$dataFolder\TrackerSprites" -Recurse
-}
-Copy-Item "$parentFolder\trackersprites\" -Destination "$dataFolder\TrackerSprites" -Recurse
-
-# Copy configs to be bundled together
-if (Test-Path -LiteralPath "$dataFolder\Configs") {
- Remove-Item -LiteralPath "$dataFolder\Configs" -Recurse
-}
-Copy-Item "$parentFolder\configs\Profiles\" -Destination "$dataFolder\Configs" -Recurse
-
-# Copy schemas to be bundled together
-if (Test-Path -LiteralPath "$dataFolder\Schemas") {
- Remove-Item -LiteralPath "$dataFolder\Schemas" -Recurse
-}
-Copy-Item "$parentFolder\configs\Schemas\" -Destination "$dataFolder\Schemas" -Recurse
-
-# Create package
-$fullVersion = "SMZ3CasRandomizerLinux_$version"
-$outputFile = "$PSScriptRoot\Output\$fullVersion.tar.gz"
-if (Test-Path $outputFile) {
- Remove-Item $outputFile -Force
-}
-if (-not (Test-Path $outputFile)) {
- Set-Location $folder
- tar -cvzf $outputFile *
-}
-Set-Location $PSScriptRoot
\ No newline at end of file
diff --git a/setup/Smz3CasRandomizer.desktop b/setup/Smz3CasRandomizer.desktop
new file mode 100644
index 00000000..1a914f1f
--- /dev/null
+++ b/setup/Smz3CasRandomizer.desktop
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Type=Application
+Name=${APP_FRIENDLY_NAME}
+Icon=${APP_ID}
+StartupWMClass=${APP_BASE_NAME}
+Comment=${APP_SHORT_SUMMARY}
+Exec=${INSTALL_EXEC}
+NoDisplay=${DESKTOP_NODISPLAY}
+Terminal=${DESKTOP_TERMINAL}
+Categories=${PRIME_CATEGORY}
+X-AppImage-Name=${APP_ID};
+X-AppImage-Version=${APP_VERSION};
+X-AppImage-Arch=${PACKAGE_ARCH};
+MimeType=
+Keywords=metroid;zelda;smz3;randomizer;tracker
\ No newline at end of file
diff --git a/setup/app.metainfo.xml b/setup/app.metainfo.xml
new file mode 100644
index 00000000..700c619e
--- /dev/null
+++ b/setup/app.metainfo.xml
@@ -0,0 +1,42 @@
+
+
+ MIT
+
+ ${APP_ID}
+ ${APP_FRIENDLY_NAME}
+ ${APP_SHORT_SUMMARY}
+ ${PUBLISHER_LINK_URL}
+ ${APP_LICENSE_ID}
+
+
+
+ ${PUBLISHER_NAME}
+
+
+ ${APP_ID}.desktop
+
+
+ ${APPSTREAM_DESCRIPTION_XML}
+
+
+
+
+ ${PRIME_CATEGORY}
+
+
+
+ development
+ programming
+
+
+
+
+ ${APPSTREAM_CHANGELOG_XML}
+
+
+
\ No newline at end of file
diff --git a/src/TrackerCouncil.Smz3.Data/Options/GeneralOptions.cs b/src/TrackerCouncil.Smz3.Data/Options/GeneralOptions.cs
index bf95b7e2..da02bb75 100644
--- a/src/TrackerCouncil.Smz3.Data/Options/GeneralOptions.cs
+++ b/src/TrackerCouncil.Smz3.Data/Options/GeneralOptions.cs
@@ -88,6 +88,8 @@ public class GeneralOptions : INotifyPropertyChanged
public int UndoExpirationTime { get; set; } = 3;
public double UIScaleFactor { get; set; } = 1;
+ public bool SkipDesktopFile { get; set; }
+
public Dictionary LinkSpriteOptions { get; set; } = new();
public Dictionary SamusSpriteOptions { get; set; } = new();
public Dictionary ShipSpriteOptions { get; set; } = new();
diff --git a/src/TrackerCouncil.Smz3.Data/ViewModels/OptionsWindowRandomizerOptions.cs b/src/TrackerCouncil.Smz3.Data/ViewModels/OptionsWindowRandomizerOptions.cs
index 16ca2e4c..557e6d95 100644
--- a/src/TrackerCouncil.Smz3.Data/ViewModels/OptionsWindowRandomizerOptions.cs
+++ b/src/TrackerCouncil.Smz3.Data/ViewModels/OptionsWindowRandomizerOptions.cs
@@ -94,6 +94,9 @@ public bool DisplayMsuWarning
[DynamicFormFieldButton(buttonText: "Update Sprites", groupName: "Bottom right", alignment: DynamicFormAlignment.Right)]
public event EventHandler? UpdateSpritesButtonPressed;
+
+ [DynamicFormFieldButton(buttonText: "Create Desktop File", groupName: "Bottom right", alignment: DynamicFormAlignment.Right, platforms: DynamicFormPlatform.Linux)]
+ public event EventHandler? CreateDesktopFileButtonPressed;
#pragma warning restore CS0067 // Event is never used
public event PropertyChangedEventHandler? PropertyChanged;
diff --git a/src/TrackerCouncil.Smz3.UI/App.axaml.cs b/src/TrackerCouncil.Smz3.UI/App.axaml.cs
index 1266eaa4..23d9e20e 100644
--- a/src/TrackerCouncil.Smz3.UI/App.axaml.cs
+++ b/src/TrackerCouncil.Smz3.UI/App.axaml.cs
@@ -1,19 +1,37 @@
using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.Versioning;
using System.Threading.Tasks;
+using AppImageManager;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using AvaloniaControls.Controls;
using Microsoft.Extensions.DependencyInjection;
using SharpHook;
+using TrackerCouncil.Smz3.Shared;
using TrackerCouncil.Smz3.UI.Views;
namespace TrackerCouncil.Smz3.UI;
public partial class App : Application
{
+ public const string AppId = "org.trackercouncil.smz3";
+ public const string AppName = "SMZ3 Cas' Randomizer";
+
private IGlobalHook? _hook;
private Task? _hookRunner;
+ private static readonly string? s_versionOverride = null;
+
+ public static string Version
+ {
+ get
+ {
+ var version = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly()!.Location);
+ return s_versionOverride ?? (version.ProductVersion ?? "").Split("+")[0];
+ }
+ }
public override void Initialize()
{
@@ -52,4 +70,12 @@ private void NativeMenuItem_OnClick(object? sender, EventArgs e)
{
Program.MainHost?.Services.GetService()?.Show();
}
+
+ [SupportedOSPlatform("linux")]
+ internal static CreateDesktopFileResponse BuildLinuxDesktopFile()
+ {
+ return new DesktopFileBuilder(AppId, AppName)
+ .AddUninstallAction(Directories.AppDataFolder)
+ .Build();
+ }
}
diff --git a/src/TrackerCouncil.Smz3.UI/Program.cs b/src/TrackerCouncil.Smz3.UI/Program.cs
index a8a35a98..984c2c0c 100644
--- a/src/TrackerCouncil.Smz3.UI/Program.cs
+++ b/src/TrackerCouncil.Smz3.UI/Program.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.IO;
+// ReSharper disable once RedundantUsingDirective
using System.Linq;
using System.Reflection;
using System.Threading;
@@ -17,7 +17,6 @@
using MSURandomizerLibrary.Models;
using MSURandomizerLibrary.Services;
using Serilog;
-using TrackerCouncil.Smz3.Data;
using TrackerCouncil.Smz3.Shared;
namespace TrackerCouncil.Smz3.UI;
@@ -51,7 +50,7 @@ public static void Main(string[] args)
#endif
.CreateLogger();
- Log.Information("Starting SMZ3 Cas' Randomizer {Version}", FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion);
+ Log.Information("Starting SMZ3 Cas' Randomizer {Version}", App.Version);
Log.Information("Config Path: {Directory}", Directories.ConfigPath);
Log.Information("Sprite Path: {Directory}", Directories.SpritePath);
Log.Information("Tracker Sprite Path: {Directory}", Directories.TrackerSpritePath);
@@ -89,16 +88,16 @@ public static void Main(string[] args)
catch (Exception e)
{
Log.Error(e, "[CRASH] Uncaught {Name}: ", e.GetType().Name);
- ShowExceptionPopup(e).ContinueWith(t => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext());
+ ShowExceptionPopup(e).ContinueWith(_ => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext());
Dispatcher.UIThread.MainLoop(source.Token);
}
}
// Avalonia configuration, don't remove; also used by visual designer.
- public static AppBuilder BuildAvaloniaApp()
+ private static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure()
.UsePlatformDetect()
- .With(new Win32PlatformOptions() { RenderingMode = new List() { Win32RenderingMode.Software } })
+ .With(new Win32PlatformOptions() { RenderingMode = new List { Win32RenderingMode.Software } })
.With(new X11PlatformOptions() { UseDBusFilePicker = false })
.WithInterFont()
.LogToTrace()
@@ -143,6 +142,23 @@ private static void CopyDefaultFolder()
return;
}
+ if (OperatingSystem.IsLinux())
+ {
+ var appImageIdPath = Path.Combine(source, "id.txt");
+ var currentIdPath = Path.Combine(Directories.DefaultDataPath, "id.txt");
+
+ if (File.Exists(appImageIdPath) && File.Exists(currentIdPath))
+ {
+ var appImageId = File.ReadAllText(appImageIdPath);
+ var currentId = File.ReadAllText(currentIdPath);
+ if (appImageId == currentId)
+ {
+ Log.Information("DefaultData id matches: {Value}", appImageId);
+ return;
+ }
+ }
+ }
+
if (Directory.Exists(Directories.DefaultDataPath))
{
try
diff --git a/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs b/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs
index a6c345ff..527cf45d 100644
--- a/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs
+++ b/src/TrackerCouncil.Smz3.UI/Services/MainWindowService.cs
@@ -1,9 +1,8 @@
using System;
-using System.Diagnostics;
using System.IO;
using System.Linq;
-using System.Reflection;
using System.Threading.Tasks;
+using AppImageManager;
using Avalonia.Threading;
using AvaloniaControls.Controls;
using AvaloniaControls.ControlServices;
@@ -15,7 +14,6 @@
using PySpeechService.Client;
using PySpeechService.TextToSpeech;
using TrackerCouncil.Smz3.Chat.Integration;
-using TrackerCouncil.Smz3.Data;
using TrackerCouncil.Smz3.Data.Configuration;
using TrackerCouncil.Smz3.Data.Options;
using TrackerCouncil.Smz3.Data.Services;
@@ -44,6 +42,12 @@ public MainWindowViewModel InitializeModel(MainWindow window)
{
_options = optionsFactory.Create();
_model.OpenSetupWindow = !_options.GeneralOptions.HasOpenedSetupWindow;
+
+ if (!_model.OpenSetupWindow && OperatingSystem.IsLinux() && !_options.GeneralOptions.SkipDesktopFile)
+ {
+ _model.OpenDesktopFileWindow = !AppImage.DoesDesktopFileExist(App.AppId);
+ }
+
ITaskService.Run(CheckForUpdates);
ITaskService.Run(StartPySpeechService);
return _model;
@@ -63,6 +67,19 @@ public void IgnoreUpdate()
_model.DisplayNewVersionBanner = false;
}
+ public void HandleUserDesktopResponse(bool addDesktopFile)
+ {
+ if (addDesktopFile && OperatingSystem.IsLinux())
+ {
+ App.BuildLinuxDesktopFile();
+ }
+ else
+ {
+ _options.GeneralOptions.SkipDesktopFile = true;
+ _options.Save();
+ }
+ }
+
public async Task ValidateTwitchToken()
{
if (string.IsNullOrEmpty(_options.GeneralOptions.TwitchOAuthToken))
@@ -202,17 +219,22 @@ private async Task CheckForUpdates()
return;
}
- var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion;
-
try
{
var gitHubRelease = await gitHubReleaseCheckerService
- .GetGitHubReleaseToUpdateToAsync("TheTrackerCouncil", "SMZ3Randomizer", version ?? "", false);
+ .GetGitHubReleaseToUpdateToAsync("TheTrackerCouncil", "SMZ3Randomizer", App.Version, false);
if (!string.IsNullOrWhiteSpace(gitHubRelease?.Url) && gitHubRelease.Url != _options.GeneralOptions.IgnoredUpdateUrl)
{
_model.DisplayNewVersionBanner = true;
_model.NewVersionGitHubUrl = gitHubRelease.Url;
+
+ if (OperatingSystem.IsLinux())
+ {
+ _model.NewVersionDownloadUrl = gitHubRelease.Asset
+ .FirstOrDefault(x => x.Url.ToLower().EndsWith(".appimage"))?.Url;
+ _model.DisplayDownloadLink = !string.IsNullOrEmpty(_model.NewVersionDownloadUrl);
+ }
}
}
catch (Exception ex)
diff --git a/src/TrackerCouncil.Smz3.UI/Services/MultiplayerConnectWindowService.cs b/src/TrackerCouncil.Smz3.UI/Services/MultiplayerConnectWindowService.cs
index 86ab4ed8..687ad6da 100644
--- a/src/TrackerCouncil.Smz3.UI/Services/MultiplayerConnectWindowService.cs
+++ b/src/TrackerCouncil.Smz3.UI/Services/MultiplayerConnectWindowService.cs
@@ -82,13 +82,13 @@ private void MultiplayerClientServiceOnConnected()
_options.MultiplayerUrl = _model.Url;
_options.Save();
_ = multiplayerClientService.CreateGame(_model.DisplayName, _model.PhoneticName,
- _model.MultiplayerGameType, GetVersion(), _model.AsyncGame, _model.SendItemsOnComplete,
+ _model.MultiplayerGameType, App.Version, _model.AsyncGame, _model.SendItemsOnComplete,
_model.DeathLink);
}
else
{
logger.LogInformation("Connected to Server successfully. Joining game.");
- _ = multiplayerClientService.JoinGame(_model.GameGuid, _model.DisplayName, _model.PhoneticName, GetVersion());
+ _ = multiplayerClientService.JoinGame(_model.GameGuid, _model.DisplayName, _model.PhoneticName, App.Version);
}
}
@@ -114,17 +114,6 @@ private void DisplayError(string error)
}
}
- private string GetVersion()
- {
- var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion ?? "";
- if (version.Contains('+'))
- {
- version = version[..version.IndexOf('+')];
- }
-
- return version;
- }
-
public void Dispose()
{
multiplayerClientService.Connected -= MultiplayerClientServiceOnConnected;
diff --git a/src/TrackerCouncil.Smz3.UI/Services/OptionsWindowService.cs b/src/TrackerCouncil.Smz3.UI/Services/OptionsWindowService.cs
index d5388a06..e58c0369 100644
--- a/src/TrackerCouncil.Smz3.UI/Services/OptionsWindowService.cs
+++ b/src/TrackerCouncil.Smz3.UI/Services/OptionsWindowService.cs
@@ -63,6 +63,12 @@ public OptionsWindowViewModel GetViewModel()
_ = UpdateSpritesAsync();
};
+ _model.RandomizerOptions.CreateDesktopFileButtonPressed += (_, _) =>
+ {
+ if (!OperatingSystem.IsLinux()) return;
+ App.BuildLinuxDesktopFile();
+ };
+
_model.TrackerOptions.TestTextToSpeechPressed += (_, _) =>
{
communicator.UpdateVolume(_model.TrackerOptions.TextToSpeechVolume);
diff --git a/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj b/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
index 45e9dc2b..d16a2f7a 100644
--- a/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
+++ b/src/TrackerCouncil.Smz3.UI/TrackerCouncil.Smz3.UI.csproj
@@ -1,45 +1,51 @@
-
- WinExe
- net8.0
- enable
- true
- app.manifest
- true
- 9.9.10
- SMZ3CasRandomizer
- Assets\smz3.ico
- $(MSBuildProjectName.Replace(" ", "_"))
-
+
+ WinExe
+ net8.0
+ enable
+ true
+ app.manifest
+ true
+ 9.9.10
+ SMZ3CasRandomizer
+ Assets\smz3.ico
+ $(MSBuildProjectName.Replace(" ", "_"))
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/TrackerCouncil.Smz3.UI/ViewModels/MainWindowViewModel.cs b/src/TrackerCouncil.Smz3.UI/ViewModels/MainWindowViewModel.cs
index 7fed220c..f147f8f7 100644
--- a/src/TrackerCouncil.Smz3.UI/ViewModels/MainWindowViewModel.cs
+++ b/src/TrackerCouncil.Smz3.UI/ViewModels/MainWindowViewModel.cs
@@ -10,8 +10,12 @@ public MainWindowViewModel()
}
[Reactive] public bool DisplayNewVersionBanner { get; set; }
+ [Reactive] public bool DisplayDownloadLink { get; set; }
public string NewVersionGitHubUrl { get; set; } = "";
+ public string? NewVersionDownloadUrl { get; set; }
public bool OpenSetupWindow { get; set; }
+
+ public bool OpenDesktopFileWindow { get; set; }
}
diff --git a/src/TrackerCouncil.Smz3.UI/ViewModels/SetupWindowViewModel.cs b/src/TrackerCouncil.Smz3.UI/ViewModels/SetupWindowViewModel.cs
index d15306e9..bde40a3c 100644
--- a/src/TrackerCouncil.Smz3.UI/ViewModels/SetupWindowViewModel.cs
+++ b/src/TrackerCouncil.Smz3.UI/ViewModels/SetupWindowViewModel.cs
@@ -1,3 +1,4 @@
+using System;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Media;
using AvaloniaControls.Models;
@@ -77,6 +78,7 @@ public class SetupWindowViewModel : ViewModelBase
public bool TrackerBcuDisabled { get; set; } = true;
public bool DisplayPage4 => StepNumber == 4;
+ public bool DisplayLinuxDesktopButton => OperatingSystem.IsLinux();
}
diff --git a/src/TrackerCouncil.Smz3.UI/Views/AboutWindow.axaml.cs b/src/TrackerCouncil.Smz3.UI/Views/AboutWindow.axaml.cs
index 769a816c..31dfadb5 100644
--- a/src/TrackerCouncil.Smz3.UI/Views/AboutWindow.axaml.cs
+++ b/src/TrackerCouncil.Smz3.UI/Views/AboutWindow.axaml.cs
@@ -10,16 +10,9 @@ public partial class AboutWindow : ScalableWindow
{
public AboutWindow()
{
- var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion ?? "";
-
- if (version.Contains('+'))
- {
- version = version[..version.IndexOf('+')];
- }
-
InitializeComponent();
- TextBlockVersion.Text = $"Version {version}";
+ TextBlockVersion.Text = $"Version {App.Version}";
}
private void SMZ3Button_OnClick(object? sender, RoutedEventArgs e)
diff --git a/src/TrackerCouncil.Smz3.UI/Views/MainWindow.axaml b/src/TrackerCouncil.Smz3.UI/Views/MainWindow.axaml
index e43bf3fe..d4b13e21 100644
--- a/src/TrackerCouncil.Smz3.UI/Views/MainWindow.axaml
+++ b/src/TrackerCouncil.Smz3.UI/Views/MainWindow.axaml
@@ -18,7 +18,7 @@
-
+
@@ -26,21 +26,34 @@
-
-
- A new version of SMZ3 is now available!
- Click here to go to the download page.
-
+
+
+ A new version of SMZ3 is now available!
-
+
-
- Ignore this Version
- Don't Check for Updates
-
+
+
+
+
+
+
+ Download Update
+
+
+
+
+
+ View On GitHub
+
+
+ Ignore this Version
+ Don't Check for Updates
+
+
diff --git a/src/TrackerCouncil.Smz3.UI/Views/MainWindow.axaml.cs b/src/TrackerCouncil.Smz3.UI/Views/MainWindow.axaml.cs
index 79e0fbcf..b4a9cdd5 100644
--- a/src/TrackerCouncil.Smz3.UI/Views/MainWindow.axaml.cs
+++ b/src/TrackerCouncil.Smz3.UI/Views/MainWindow.axaml.cs
@@ -1,7 +1,10 @@
using System;
using System.IO;
using System.Threading.Tasks;
+using AppImageManager;
+using Avalonia.Controls;
using Avalonia.Interactivity;
+using Avalonia.Threading;
using AvaloniaControls;
using AvaloniaControls.Controls;
using AvaloniaControls.Services;
@@ -34,17 +37,17 @@ public MainWindow(MainWindowService service, IServiceProvider? serviceProvider,
InitializeComponent();
DataContext = _model = _service.InitializeModel(this);
- _service.SpriteDownloadStart += (sender, args) =>
+ _service.SpriteDownloadStart += (_, _) =>
{
_spriteDownloadWindow = new SpriteDownloadWindow();
- _spriteDownloadWindow.Closed += (o, eventArgs) =>
+ _spriteDownloadWindow.Closed += (_, _) =>
{
_spriteDownloadWindow = null;
};
_spriteDownloadWindow.ShowDialog(this);
};
- _service.SpriteDownloadEnd += (sender, args) => _spriteDownloadWindow?.Close();
+ _service.SpriteDownloadEnd += (_, _) => _spriteDownloadWindow?.Close();
}
public void Reload()
@@ -77,7 +80,7 @@ private void DisableUpdatesLink_OnClick(object? sender, RoutedEventArgs e)
_service?.DisableUpdates();
}
- private async void Control_OnLoaded(object? sender, RoutedEventArgs e)
+ private void Control_OnLoaded(object? sender, RoutedEventArgs e)
{
if (_service == null)
{
@@ -88,6 +91,15 @@ private async void Control_OnLoaded(object? sender, RoutedEventArgs e)
_ = ITaskService.Run(_service.DownloadConfigsAsync);
_ = ITaskService.Run(_service.DownloadSpritesAsync);
+ if (_model.OpenSetupWindow || _model.OpenDesktopFileWindow)
+ {
+ _ = Dispatcher.UIThread.InvokeAsync(OpenStartingWindows);
+ }
+ }
+
+ private async Task OpenStartingWindows()
+ {
+ await Task.Delay(TimeSpan.FromSeconds(0.5));
if (_model.OpenSetupWindow && _serviceProvider != null)
{
var result = await _serviceProvider.GetRequiredService()
@@ -101,6 +113,14 @@ private async void Control_OnLoaded(object? sender, RoutedEventArgs e)
_ = SoloRomListPanel.OpenGenerationWindow();
}
}
+ else if (_model.OpenDesktopFileWindow)
+ {
+ _model.OpenDesktopFileWindow = false;
+ var response = await MessageWindow.ShowYesNoDialog(
+ "Would you like to add SMZ3 to your menu by creating a desktop file?",
+ "SMZ3 Cas' Randomizer", this);
+ _service!.HandleUserDesktopResponse(response);
+ }
}
private void OptionsMenuItem_OnClick(object? sender, RoutedEventArgs e)
@@ -112,4 +132,41 @@ private void AboutButton_OnClick(object? sender, RoutedEventArgs e)
{
_serviceProvider?.GetRequiredService().ShowDialog(this);
}
+
+ private async void DownloadReleaseButton_OnClick(object? sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(_model.NewVersionDownloadUrl))
+ {
+ return;
+ }
+
+ if (OperatingSystem.IsLinux())
+ {
+ var downloadResult = await AppImage.DownloadAsync(new DownloadAppImageRequest
+ {
+ Url = _model.NewVersionDownloadUrl
+ });
+
+ if (downloadResult.Success)
+ {
+ Close();
+ }
+ else if (downloadResult.DownloadedSuccessfully)
+ {
+ await MessageWindow.ShowErrorDialog("AppImage was downloaded, but it could not be launched.");
+ }
+ else
+ {
+ await MessageWindow.ShowErrorDialog("Failed downloading AppImage");
+ }
+ }
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine(exception);
+ throw;
+ }
+ }
}
diff --git a/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml b/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml
index ea00dc31..40e9bc03 100644
--- a/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml
+++ b/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml
@@ -202,6 +202,12 @@
+
+ You can create a .desktop file to add SMZ3 as an application in your desktop environment's menu.
+
+
+
+
You can open the full settings window to change other settings such as enabling Twitch integration,
modifying the tracker UI background, and modifying other tracking behavior.
diff --git a/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml.cs b/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml.cs
index ef0c7176..dc3fc937 100644
--- a/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml.cs
+++ b/src/TrackerCouncil.Smz3.UI/Views/SetupWindow.axaml.cs
@@ -1,3 +1,4 @@
+using System;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
@@ -155,5 +156,11 @@ private void Window_OnClosing(object? sender, WindowClosingEventArgs e)
{
_service?.OnClose();
}
+
+ private void CreateDesktopFileButton_OnClick(object? sender, RoutedEventArgs e)
+ {
+ if (!OperatingSystem.IsLinux()) return;
+ App.BuildLinuxDesktopFile();
+ }
}