diff --git a/Directory.Build.props b/Directory.Build.props index eea2b713a0..ca3e5406f6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -24,7 +24,7 @@ INSTALLATION_METHOD_ARCHIVE: App should have been installed via archive. INSTALLATION_METHOD_INNO_SETUP: Installed via InnoSetup (Windows) - INSTALLATION_METHOD_FLATPAK: Installed via Flatpak (Linux) + INSTALLATION_METHOD_PACKAGE_MANAGER: Installed with a package manager. INSTALLATION_METHOD_APPIMAGE: Running via AppImage (Linux) ________________ diff --git a/docs/Contributing.md b/docs/Contributing.md new file mode 100644 index 0000000000..92b86034fb --- /dev/null +++ b/docs/Contributing.md @@ -0,0 +1,28 @@ +## Code Contributions + +### Prerequisites + +- The latest version of the [.NET SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0). +- An IDE: + - [JetBrains Rider](https://www.jetbrains.com/rider/) and the [Avalonia Rider Extension](https://plugins.jetbrains.com/plugin/14839-avaloniarider), + - [Visual Studio](https://visualstudio.microsoft.com/downloads/) and the [Avalonia Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaVS). + +There are also some [Item Templates](https://github.com/AvaloniaUI/avalonia-dotnet-templates) for Avalonia that can be very useful to have, +helping you make things like new 'Windows' and 'Controls' easier. + +### Writing code + +Make sure to follow our [Development Guidelines](./development-guidelines/UICodingGuidelines.md). + +## Translations + +Translations are currently handled via the IDE. See [this issue](https://github.com/Nexus-Mods/NexusMods.App/issues/598) for more details. + +## For Package Maintainers + +If you want to create a package for your distribution, here are some helpful tips to get started: + +- If possible, use `nexusmods-app` for the package name. +- We ship a build of `7zz` and use that executable unless you set `NEXUSMODS_APP_USE_SYSTEM_EXTRACTOR=1` when publishing. See [this issue](https://github.com/Nexus-Mods/NexusMods.App/issues/1306#issuecomment-2095755699) for details. +- Set `INSTALLATION_METHOD_PACKAGE_MANAGER` when publishing. We have an integrated updater that will notify users about new versions. If you set this flag, we'll tell the user to update with their package manager. +- Let us know if you have questions or if you published a new package by joining our [Discord](https://discord.gg/ReWTxb93jS). diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md deleted file mode 100644 index 1cb7c23828..0000000000 --- a/docs/GettingStarted.md +++ /dev/null @@ -1,33 +0,0 @@ -!!! info "Describes how to compile and run the Nexu Mods App." - -The Nexus Mods App is programmed in C# with latest .NET Runtime. Setup should be easy. - - -## Prerequisites - -- Download the Latest [.NET SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0). -- Download an IDE, recommended options below: - - [Visual Studio](https://visualstudio.microsoft.com/downloads/) - - [JetBrains Rider](https://www.jetbrains.com/rider/) - -Our development team uses Rider; however, Visual Studio is a great free offering on Windows. -Other code editors, like [VS Code](https://code.visualstudio.com/), may work for you with [extensions](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit); -however, they may be a bit more complicated to use. - -That's all. Open the project (`.sln`), build, and you're done. - -## Tools for UI Development - -Visual Studio and JetBrains Rider both have avalonia extensions that allow previewing ui designs (`.axaml` files). - -- [Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaVS) -- [Rider Extension](https://plugins.jetbrains.com/plugin/14839-avaloniarider) - -You can install via the web or from inside the IDE extension managers themselves. - -There are also some [Item Templates](https://github.com/AvaloniaUI/avalonia-dotnet-templates) for Avalonia that can be very useful to have, -helping you make things like new 'Windows' and 'Controls' easier. - -## Code Guidelines - -Have a look inside [Development Guidelines](./development-guidelines/DependencyInjection.md) 😉. diff --git a/docs/ModWithConfidence.md b/docs/ModWithConfidence.md new file mode 100644 index 0000000000..4c161c1355 --- /dev/null +++ b/docs/ModWithConfidence.md @@ -0,0 +1,78 @@ +One of the biggest complaints from users over the years about modding is that they can't mod with confidence. + +- Will a new mod wreck my installation? +- Will I need to delete my game to revert a mod installation? +- The game updated, my mods updated, and now everything's broken. + +Every step of the ***classic modding approach*** is fraught with pitfalls and destructive changes. + +The Nexus Mods App intends to solve these problems. In addition to being a great mod installer, manager and builder, +this project aims to always provide an *undo* feature for users. Not just on a metadata level (like most mod managers +offer today) but on a per-file basis as well. + +Go ahead and update that mod; if you don't like it, you can always go back to the game as it was before you made the update. + +Concept: [Immutable Mod Lists][immutable-mod-lists] + +### Simple Data + +Most *Mod Managers* have serious drawbacks and edge cases in how they manage files (data). + +They start with a goal of keeping the game folder clean, through the use of techniques such as Symbolic Links, +Hard Links and VFS Systems. + +!!! warning "Unfortunately, most modding frameworks aren't designed with these systems in mind." + +As a result, concepts foreign to end users (VFS, Symlinks) are forced upon them, and the [incidental complexity][incidental-complexity] +of these systems often leak through the mod manager abstractions in unexpected ways. + +#### For Example + +Symlinks & Hardlinks: + +* How do you know if your game works correctly with Symlinks? +* For Hardlinks, your mod files *must be on the same drive* as your game. +* Links can have strange side-effects when files are modified, depending if the file was direct modified or deleted-created-modified. + +Virtual FileSystems: + +* You have to run xEdit through [Mod Organizer 2][mod-organizer-2] for it to see your mod list (Bethesda Games) +* Files end up in a different place from where the end user expects them. + +#### Nexus Mods App Approach + +!!! nexus "The Nexus Mods App aims to merge the mental simplicity of manual modding with the hygiene of existing mod installers and a promise that "you can always go back to what last worked"" + +The 'Data Model' of the Nexus Mods App can be thought of as an extension of lessons learned from the development of +Nexus Collections and Wabbajack. + +When you make a mod list, we don't directly manipulate files. Instead, we manipulate the 'instructions' used to deploy +the mods to the folder, and clicking 'Apply' simply moves the files directly to the folder. + +We do this in a way that allows the user to revert changes at any time. Files aren't 'linked' or 'staged' in any way; +no functions are hooked, and the [cognitive overhead][cognitive-overhead] of the modding process is greatly reduced. + +Instead, users can focus on creating a perfect modding setup that works for them. + +Further Reading: [Comparison of File Management Systems][comparison-fms] + +[al12]: https://github.com/Al12rs +[clojure]: https://clojure.org/ +[cognitive-overhead]: https://techcrunch.com/2013/04/20/cognitive-overhead/ +[comparison-fms]: misc/ComparisonOfFileManagementSystems.md +[erri120]: https://github.com/erri120 +[flaws]: misc/DrawbacksOfNexusApproach.md +[gamefinder]: https://github.com/erri120/GameFinder +[halgari]: https://github.com/halgari +[immutable-mod-lists]: concepts/0000-immutable-modlists.md +[incidental-complexity]: https://dev.to/alexbunardzic/software-complexity-essential-accidental-and-incidental-3i4d +[mod-organizer-2]: https://www.modorganizer.org/ +[mutagen]: https://mutagen-modding.github.io/Mutagen/ +[nagev]: https://github.com/IDCs +[nexus-premium]: https://next.nexusmods.com/premium +[reloaded-ii]: https://reloaded-project.github.io/Reloaded-II/ +[sewer56]: https://github.com/Sewer56 +[simon]: https://github.com/insomnious +[tannin]: https://github.com/TanninOne +[vortex]: https://www.nexusmods.com/about/vortex/ +[wabbajack]: https://www.wabbajack.org/ diff --git a/docs/index.md b/docs/index.md index 9cb268a6ec..2e572b0fb7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,9 +1,3 @@ -!!! note "The Nexus Mods App is a Work in Progress" - - This documentation currently only contains information for programmers, contributors, and curious people alike. - ----------- -

The Nexus Mods App

@@ -12,128 +6,70 @@
The future of modding with Nexus Mods.

- - CI Tests - Discord + + GitHub Release +
-Nexus Mods App is a mod installer, creator and manager for all your popular games. - -Easy to use, it runs on your standard Windows PC and Linux alike. Don't waste time troubleshooting; play your games, -fill those knees with arrows, and most importantly, ***Have Fun***! - -!!! info "The Nexus Mods App is about creating that Modding experience that *'Just Works'* for old and new games alike!" - -### Mod with Confidence - -One of the biggest complaints from users over the years about modding is that they can't mod with confidence. - -- Will a new mod wreck my installation? -- Will I need to delete my game to revert a mod installation? -- The game updated, my mods updated, and now everything's broken. - -Every step of the ***classic modding approach*** is fraught with pitfalls and destructive changes. +If you want to know how the App works, see [Mod With Confidence](./ModWithConfidence.md). -The Nexus Mods App intends to solve these problems. In addition to being a great mod installer, manager and builder, -this project aims to always provide an *undo* feature for users. Not just on a metadata level (like most mod managers -offer today) but on a per-file basis as well. +## Installation -Go ahead and update that mod; if you don't like it, you can always go back to the game as it was before you made the update. +### Windows -Concept: [Immutable Mod Lists][immutable-mod-lists] +**Requirements**: Windows 10 or newer and a x64 CPU, we don't support Windows on ARM. -### Simple Data +Download and run the [Windows Installer] from the [latest release] on GitHub. -Most *Mod Managers* have serious drawbacks and edge cases in how they manage files (data). +### Linux -They start with a goal of keeping the game folder clean, through the use of techniques such as Symbolic Links, -Hard Links and VFS Systems. +The App requires the following programs to be available at runtime: -!!! warning "Unfortunately, most modding frameworks aren't designed with these systems in mind." +- `xdg-open` to open URLs in your browser. +- `update-desktop-database` to update the MIME cache after creating a desktop entry file for the NXM link handler. -As a result, concepts foreign to end users (VFS, Symlinks) are forced upon them, and the [incidental complexity][incidental-complexity] -of these systems often leak through the mod manager abstractions in unexpected ways. +#### AppImage -#### For Example +You can download the AppImage file `NexusMods.App.x86_64.AppImage` from the [latest release] on GitHub. Make sure you have the following dependencies installed before running the AppImage: -Symlinks & Hardlinks: +- [FUSE 2](https://github.com/AppImage/AppImageKit/wiki/FUSE) is required to run any AppImage. +- `glibc` 2.2.5 or newer +- `glibc++` 3.4 or newer -* How do you know if your game works correctly with Symlinks? -* For Hardlinks, your mod files *must be on the same drive* as your game. -* Links can have strange side-effects when files are modified, depending if the file was direct modified or deleted-created-modified. +#### System Package Manager -Virtual FileSystems: +This page will be updated with [Repology](https://repology.org/) once packages start appearing. If you're want to create a package for a platform, see [Contributing](./Contributing.md#for-package-maintainers) for more details. -* You have to run xEdit through [Mod Organizer 2][mod-organizer-2] for it to see your mod list (Bethesda Games) -* Files end up in a different place from where the end user expects them. +### macOS -#### Nexus Mods App Approach +We currently don't publish releases for macOS. -!!! nexus "The Nexus Mods App aims to merge the mental simplicity of manual modding with the hygiene of existing mod installers and a promise that "you can always go back to what last worked"" +## The Team -The 'Data Model' of the Nexus Mods App can be thought of as an extension of lessons learned from the development of -Nexus Collections and Wabbajack. +### Nexus Mods App Team -When you make a mod list, we don't directly manipulate files. Instead, we manipulate the 'instructions' used to deploy -the mods to the folder, and clicking 'Apply' simply moves the files directly to the folder. +- [halgari](https://github.com/halgari): Team lead of the Nexus Mods App, creator of [Wabbajack](https://www.wabbajack.org) and former developer of [Clojure](https://clojure.org/). +- [Al12rs](https://github.com/Al12rs): Lead developer of [Mod Organizer 2](https://www.modorganizer.org/). +- [erri120](https://github.com/erri120): Developer of [Wabbajack](https://www.wabbajack.org) and creator of [GameFinder](https://github.com/erri120/GameFinder). +- [Sewer56](https://github.com/Sewer56): Creator of [Reloaded-II](https://reloaded-project.github.io/Reloaded-II/). -We do this in a way that allows the user to revert changes at any time. Files aren't 'linked' or 'staged' in any way; -no functions are hooked, and the [cognitive overhead][cognitive-overhead] of the modding process is greatly reduced. +### Vortex Team -Instead, users can focus on creating a perfect modding setup that works for them. +- [Simon](https://github.com/insomnious): Lead developer of [Vortex](https://www.nexusmods.com/about/vortex/). +- [Nagev](https://github.com/IDCs): Developer of [Vortex](https://www.nexusmods.com/about/vortex/). -Further Reading: [Comparison of File Management Systems][comparison-fms] +### Others -#### Drawback +See [Contributors](https://github.com/Nexus-Mods/NexusMods.App/graphs/contributors) for a full list of contributors. -!!! note "No approach is without drawbacks, so it's [only right for us to acknowledge ours][flaws]." - -## The Development Team - -!!! nexus "The Nexus Mods App is developed by a very diverse, talented group of people." - -- Tim ([Halgari][halgari]): Team lead and author of [Wabbajack][wabbajack], 20 years building large computer systems, and most notably a big fan of [Clojure][clojure]. - -- [Sewer56][sewer56]: Best known for [Reloaded-II][reloaded-ii]. Built several modding frameworks and brings with him a lot of experience with micro-optimization, reverse engineering, and low-level knowledge; including the more arcane parts of .NET. - -- [erri120][erri120]: Worked with Tim for some time on [Wabbajack][wabbajack], has been heavily involved with [Mutagen][mutagen] (patching library for Bethesda games) and wrote the [Gamefinder][gamefinder] library used in the App. - -- [AL12][al12]: Best known for being lead developer of [Mod Organizer 2][mod-organizer-2]. Wealth of experience in various modding frameworks is appreciated. - -We also collaborate with the [Vortex][vortex] people: - -- Simon ([Simon][simon]): Been a Unity developer for some time and has quickly picked up the ins and outs of Vortex. He’s leads development on [Vortex][vortex]. +Former maintainers: -- [Nagev][nagev]: Played a pivotal role in developing several impressive extensions and frameworks for the application. +- [TanninOne](https://github.com/TanninOne): Creator of [Vortex](https://www.nexusmods.com/about/vortex/) and [Mod Organizer 1](https://github.com/TanninOne/modorganizer). -Former maintainers: +--- -- [Tannin][tannin]: Created [Vortex][vortex], and was the lead developer throughout most of its lifetime. - -!!! tip "Development of the Nexus Mods App is funded through your subscriptions of [nexus-premium][nexus-premium]" - -If you enjoy using the App, consider subscribing, thanks! - -[al12]: https://github.com/Al12rs -[clojure]: https://clojure.org/ -[cognitive-overhead]: https://techcrunch.com/2013/04/20/cognitive-overhead/ -[comparison-fms]: misc/ComparisonOfFileManagementSystems.md -[erri120]: https://github.com/erri120 -[flaws]: misc/DrawbacksOfNexusApproach.md -[gamefinder]: https://github.com/erri120/GameFinder -[halgari]: https://github.com/halgari -[immutable-mod-lists]: concepts/0000-immutable-modlists.md -[incidental-complexity]: https://dev.to/alexbunardzic/software-complexity-essential-accidental-and-incidental-3i4d -[mod-organizer-2]: https://www.modorganizer.org/ -[mutagen]: https://mutagen-modding.github.io/Mutagen/ -[nagev]: https://github.com/IDCs -[nexus-premium]: https://next.nexusmods.com/premium -[reloaded-ii]: https://reloaded-project.github.io/Reloaded-II/ -[sewer56]: https://github.com/Sewer56 -[simon]: https://github.com/insomnious -[tannin]: https://github.com/TanninOne -[vortex]: https://www.nexusmods.com/about/vortex/ -[wabbajack]: https://www.wabbajack.org/ +[Windows Installer]: https://github.com/Nexus-Mods/NexusMods.App/releases/latest/download/NexusMods.App.x64.exe +[latest release]: https://github.com/Nexus-Mods/NexusMods.App/releases/latest diff --git a/mkdocs.yml b/mkdocs.yml index 29af3642fd..e365f45281 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -48,7 +48,8 @@ plugins: nav: - Home: index.md - - Getting Started: GettingStarted.md + - Mod With Confidence: ModWithConfidence.md + - Contributing: Contributing.md - Development Guidelines: - Dependency Injection: development-guidelines/DependencyInjection.md - Interacting with the File System: development-guidelines/UsingIFileSystem.md diff --git a/src/NexusMods.App.BuildInfo/CompileConstants.cs b/src/NexusMods.App.BuildInfo/CompileConstants.cs index 135d0a48b5..4bcd185115 100644 --- a/src/NexusMods.App.BuildInfo/CompileConstants.cs +++ b/src/NexusMods.App.BuildInfo/CompileConstants.cs @@ -16,8 +16,8 @@ public static class CompileConstants InstallationMethod.Archive; #elif INSTALLATION_METHOD_APPIMAGE InstallationMethod.AppImage; -#elif INSTALLATION_METHOD_FLATPAK - InstallationMethod.Flatpak; +#elif INSTALLATION_METHOD_PACKAGE_MANAGER + InstallationMethod.PackageManager; #elif INSTALLATION_METHOD_INNO_SETUP InstallationMethod.InnoSetup; #else @@ -41,27 +41,27 @@ public static class CompileConstants public enum InstallationMethod { /// - /// Manual. + /// Manual installation, or from source. This is the default value. /// Manually = 0, /// - /// Via the archive. + /// The App was packaged into an archive. /// Archive, /// - /// Via the AppImage. + /// The App was packaged into an AppImage. /// AppImage, /// - /// Via the Flatpak. + /// The App was installed using a package manager. /// - Flatpak, + PackageManager, /// - /// Via the Inno Setup. + /// The App was installed using the InnoSetup. /// - InnoSetup + InnoSetup, } diff --git a/src/NexusMods.App.UI/Overlays/Updater/UpdaterViewModel.cs b/src/NexusMods.App.UI/Overlays/Updater/UpdaterViewModel.cs index 59af7af985..d7ff5dcc0b 100644 --- a/src/NexusMods.App.UI/Overlays/Updater/UpdaterViewModel.cs +++ b/src/NexusMods.App.UI/Overlays/Updater/UpdaterViewModel.cs @@ -1,5 +1,4 @@ -using System.Diagnostics; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Text.Json; using System.Text.Json.Serialization; using System.Windows.Input; @@ -100,12 +99,13 @@ public async Task ShouldShow() _logger.LogInformation("New version available: {Version}", latestRelease.Version); var asset = FindAsset(latestRelease); + if (asset is null) return false; _logger.LogInformation("Asset found: {Asset}", asset.Name); UpdateUrl = asset.BrowserDownloadUrl; NewVersion = latestRelease.Version; - if (Method is InstallationMethod.AppImage or InstallationMethod.Flatpak) + if (Method is InstallationMethod.AppImage or InstallationMethod.PackageManager) { ShowSystemUpdateMessage = true; } @@ -120,24 +120,22 @@ public async Task ShouldShow() } - private Asset FindAsset(Release latestRelease) + private Asset? FindAsset(Release latestRelease) { switch (Method) { - case InstallationMethod.Flatpak: - throw new UnreachableException("Flatpak is not supported yet"); case InstallationMethod.InnoSetup: - return latestRelease.Assets.First(r => r.Name.EndsWith(".exe")); + return latestRelease.Assets.FirstOrDefault(r => r.Name.EndsWith(".exe")); case InstallationMethod.Archive when RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && RuntimeInformation.OSArchitecture == Architecture.X64: - return latestRelease.Assets.First(r => r.Name.EndsWith(".win-x64.zip")); + return latestRelease.Assets.FirstOrDefault(r => r.Name.EndsWith(".win-x64.zip")); case InstallationMethod.Archive when RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && RuntimeInformation.OSArchitecture == Architecture.X64: - return latestRelease.Assets.First(r => r.Name.EndsWith(".linux-x64.zip")); + return latestRelease.Assets.FirstOrDefault(r => r.Name.EndsWith(".linux-x64.zip")); case InstallationMethod.AppImage: - return latestRelease.Assets.First(r => r.Name.EndsWith(".AppImage")); + return latestRelease.Assets.FirstOrDefault(r => r.Name.EndsWith(".AppImage")); default: - throw new UnreachableException("Unsupported installation method"); + return null; } } diff --git a/tests/NexusMods.UI.Tests/Overlays/UpdaterViewTests.cs b/tests/NexusMods.UI.Tests/Overlays/UpdaterViewTests.cs index 2ee6e217de..a54c17fb53 100644 --- a/tests/NexusMods.UI.Tests/Overlays/UpdaterViewTests.cs +++ b/tests/NexusMods.UI.Tests/Overlays/UpdaterViewTests.cs @@ -1,6 +1,5 @@ using Avalonia.Controls; using FluentAssertions; -using NexusMods.App.BuildInfo; using NexusMods.App.UI.Overlays; using NexusMods.App.UI.Overlays.Updater; @@ -28,21 +27,6 @@ await EventuallyOnUi(() => }); } - [Fact] - public async Task UsingFlatpakDisablesUpdateButtonAndShowsMessage() - { - ViewModel.Method = InstallationMethod.Flatpak; - - var useSystemUpdater = await Host.GetViewControl("UseSystemUpdater"); - var updateButton = await Host.GetViewControl