├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md └── workflows │ ├── deployment-develop.yml │ └── deployment-master.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── gamevault.sln └── gamevault ├── App.xaml ├── App.xaml.cs ├── AssemblyInfo.cs ├── Converter ├── ContainsCurrentUserConverter.cs ├── DownloadLimitConverter.cs ├── EnumDescriptionConverter.cs ├── GameSettingsTabVisibilityConverter.cs ├── GameSizeConverter.cs ├── GameStateColorConverter.cs ├── GameStateDescriptionConverter.cs ├── GameTimeConverter.cs ├── GameViewSettingsPermissionRoleToVisibilityConverter.cs ├── GreaterThanConverter.cs ├── InverseBoolConverter.cs ├── InverseEmptyStringConverter.cs ├── InverseNullConverter.cs ├── InverseVisibilityConverter.cs ├── IsGameDownloadedConverter.cs ├── IsGameMappedConverter.cs ├── LibraryPermissionRoleToVisibilityConverter.cs ├── LicenseConverter.cs ├── PermissionRoleConverter.cs ├── PermissionRoleToVisibilityConverter.cs ├── ShowMappedTitleConverter.cs ├── StringToArrayConverter.cs ├── StringToColorConverter.cs ├── UTCtoLocalTimeConverter.cs └── UrlImageConverter.cs ├── Helper ├── AnalyticsHelper.cs ├── CommandHelper.cs ├── CrashReportHelper.cs ├── DownloadSpeedCalculator.cs ├── GameTimeTracker.cs ├── InputTimer.cs ├── Integrations │ ├── AutostartHelper.cs │ ├── DesktopHelper.cs │ ├── DiscordHelper.cs │ ├── SaveGameHelper.cs │ ├── SevenZipHelper.cs │ ├── SteamHelper.cs │ ├── StoreHelper.cs │ └── ToastMessageHelper.cs ├── LoginManager.cs ├── Media │ ├── BitmapHelper.cs │ ├── CacheHelper.cs │ ├── GifHelper.cs │ └── MimeTypeHelper.cs ├── ProcessHelper.cs ├── ScrollViewerHelper.cs ├── StringCompressor.cs ├── TaskQueue.cs ├── VisualHelper.cs └── Web │ ├── HttpClientDownloadWithProgress.cs │ ├── WebExceptionHelper.cs │ ├── WebHelper.cs │ └── WpfEmbeddedBrowser.cs ├── Lib ├── 7z │ ├── 7z.dll │ ├── 7z.exe │ └── LICENSE ├── Preferences.dll └── savegame │ ├── LICENSE │ └── ludusavi.exe ├── Models ├── AppInfo.cs ├── CommandOptions.cs ├── Game.cs ├── ImageCache.cs ├── Mapping │ ├── MapGameDto.cs │ ├── MetadataProviderDto.cs │ ├── UpdateGameDto.cs │ └── UpdateUserDto.cs ├── Media.cs ├── Metadata │ ├── DeveloperMetadata.cs │ ├── GameMetadata.cs │ ├── GenreMetadata.cs │ ├── PublisherMetadata.cs │ ├── TagMetadata.cs │ └── UpdateGameUserMetadataDto.cs ├── MinimalGame.cs ├── PaginatedGame.cs ├── PhalcodeProduct.cs ├── Pill.cs ├── Progress.cs ├── ServerInfo.cs └── User.cs ├── PipeServiceHandler.cs ├── Program.cs ├── Properties └── launchSettings.json ├── Resources ├── Assets │ ├── Base.xaml │ ├── Colors.xaml │ ├── Icons.xaml │ ├── MarkdownStyles.xaml │ ├── Styles.xaml │ └── Themes │ │ ├── ThemeChristmasDark.xaml │ │ ├── ThemeClassicDark.xaml │ │ ├── ThemeDefaultDark.xaml │ │ ├── ThemeDefaultLight.xaml │ │ ├── ThemeHalloweenDark.xaml │ │ ├── ThemePhalcodeDark.xaml │ │ └── ThemePhalcodeLight.xaml └── Images │ ├── ContextMenuIcon_Community.png │ ├── ContextMenuIcon_Downloads.png │ ├── ContextMenuIcon_Exit.png │ ├── ContextMenuIcon_Library.png │ ├── ContextMenuIcon_Settings.png │ ├── com_NoUserAvatar.png │ ├── gameView_NoBackground.jpg │ ├── glyph_premium.png │ ├── icon.ico │ ├── install_NoGameFound.png │ ├── library_NoGameCover.png │ └── library_NoGameFound.png ├── Scripts └── GenerateClient.ps1 ├── UserControls ├── AdminConsoleUserControl.xaml ├── AdminConsoleUserControl.xaml.cs ├── CommunityUserControl.xaml ├── CommunityUserControl.xaml.cs ├── DownloadsUserControl.xaml ├── DownloadsUserControl.xaml.cs ├── GameDownloadUserControl.xaml ├── GameDownloadUserControl.xaml.cs ├── GameSettingsUserControl.xaml ├── GameSettingsUserControl.xaml.cs ├── GameViewUserControl.xaml ├── GameViewUserControl.xaml.cs ├── GeneralControls │ ├── CacheImage.xaml │ ├── CacheImage.xaml.cs │ ├── DateRangeSelector.xaml │ ├── DateRangeSelector.xaml.cs │ ├── IconButton.cs │ ├── MediaSlider.xaml │ ├── MediaSlider.xaml.cs │ ├── NewsPopup.xaml │ ├── NewsPopup.xaml.cs │ ├── PillSelector.xaml │ ├── PillSelector.xaml.cs │ └── TransitioningContentControlEx.cs ├── InstallUserControl.xaml ├── InstallUserControl.xaml.cs ├── LibraryUserControl.xaml ├── LibraryUserControl.xaml.cs ├── SettingsComponents │ ├── BackupRestoreUserControl.xaml │ ├── BackupRestoreUserControl.xaml.cs │ ├── LoginUserControl.xaml │ ├── LoginUserControl.xaml.cs │ ├── RegisterUserControl.xaml │ ├── RegisterUserControl.xaml.cs │ ├── RootPathUserControl.xaml │ ├── RootPathUserControl.xaml.cs │ ├── ServerUrlUserControl.xaml │ └── ServerUrlUserControl.xaml.cs ├── SettingsUserControl.xaml ├── SettingsUserControl.xaml.cs ├── UserSettingsUserControl.xaml ├── UserSettingsUserControl.xaml.cs ├── Wizard.xaml └── Wizard.xaml.cs ├── ViewModels ├── AdminConsoleViewModel.cs ├── CommunityViewModel.cs ├── DownloadsViewModel.cs ├── GameDownloadViewModel.cs ├── GameSettingsViewModel.cs ├── GameViewViewModel.cs ├── InstallViewModel.cs ├── LibraryViewModel.cs ├── MainWindowViewModel.cs ├── SettingsViewModel.cs ├── UserSettingsViewModel.cs └── ViewModelBase.cs ├── Windows ├── ExceptionWindow.xaml ├── ExceptionWindow.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── UpdateWindow.xaml └── UpdateWindow.xaml.cs ├── app.manifest └── gamevault.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | github: phalcode 3 | ko_fi: phalcode 4 | liberapay: phalcode 5 | custom: "https://paypal.me/phalcode" 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🪲 Report a Bug 3 | about: Does something not work correctly? 4 | labels: ["💻 client", "🪲 bug"] 5 | projects: "Phalcode/4" 6 | --- 7 | 8 | **Describe the bug** 9 | A clear and concise description of what the bug is. 10 | 11 | **To Reproduce** 12 | Steps to reproduce the behavior: 13 | 1. Go to '...' 14 | 2. Click on '....' 15 | 3. Scroll down to '....' 16 | 4. See error 17 | 18 | **Expected behavior** 19 | A clear and concise description of what you expected to happen. 20 | 21 | **Screenshots** 22 | If applicable, add screenshots to help explain your problem. 23 | 24 | **Desktop (please complete the following information):** 25 | - OS: [e.g. iOS] 26 | - Browser [e.g. chrome, safari] 27 | - Version [e.g. 22] 28 | 29 | **Smartphone (please complete the following information):** 30 | - Device: [e.g. iPhone6] 31 | - OS: [e.g. iOS8.1] 32 | - Browser [e.g. stock browser, safari] 33 | - Version [e.g. 22] 34 | 35 | **Additional context** 36 | Add any other context about the problem here. 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🔧 Request a Feature 3 | about: Do you have a Feature Request? 4 | labels: ["💻 client", "🔧 feature"] 5 | projects: "Phalcode/4" 6 | --- 7 | 8 | **Is your feature request related to a problem? Please describe.** 9 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 10 | 11 | **Describe the solution you'd like** 12 | A clear and concise description of what you want to happen. 13 | 14 | **Describe alternatives you've considered** 15 | A clear and concise description of any alternative solutions or features you've considered. 16 | 17 | **Additional context** 18 | Add any other context or screenshots about the feature request here. 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ❓ Question 3 | about: Do you have a Question? 4 | labels: ["💻 client","❓ question"] 5 | projects: "Phalcode/4" 6 | --- 7 | 8 | **Your Question** 9 | 10 | Ask your question or seek clarification here. 11 | 12 | **Additional Context** 13 | 14 | Add any additional context or information that may be helpful. 15 | -------------------------------------------------------------------------------- /.github/workflows/deployment-develop.yml: -------------------------------------------------------------------------------- 1 | name: Deployment Pipeline for develop branch 2 | on: 3 | push: 4 | branches: 5 | - develop 6 | jobs: 7 | deploy: 8 | permissions: write-all 9 | runs-on: windows-latest 10 | outputs: 11 | version: ${{ steps.release.outputs.version }} 12 | 13 | steps: 14 | - name: Checkout repository 15 | id: checkout 16 | uses: actions/checkout@v2 17 | 18 | - name: Set up .NET 19 | id: setup 20 | uses: actions/setup-dotnet@v3.2.0 21 | with: 22 | dotnet-version: '8.x' 23 | 24 | - name: Build .NET solution 25 | id: build 26 | run: | 27 | dotnet build gamevault.sln --configuration Release 28 | 7z a GameVault.zip gamevault/bin 29 | 30 | - name: Upload binaries to release 31 | uses: svenstaro/upload-release-action@v2 32 | with: 33 | repo_token: ${{ secrets.GITHUB_TOKEN }} 34 | file: GameVault.zip 35 | asset_name: GameVault.zip 36 | tag: unstable 37 | overwrite: true 38 | prerelease: true 39 | -------------------------------------------------------------------------------- /.github/workflows/deployment-master.yml: -------------------------------------------------------------------------------- 1 | name: Deployment Pipeline for master branch 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | deploy: 8 | permissions: write-all 9 | runs-on: windows-latest 10 | outputs: 11 | version: ${{ steps.release.outputs.version }} 12 | 13 | steps: 14 | - name: Checkout repository 15 | id: checkout 16 | uses: actions/checkout@v2 17 | 18 | - name: Set up .NET 19 | id: setup 20 | uses: actions/setup-dotnet@v3.2.0 21 | with: 22 | dotnet-version: '8.x' 23 | 24 | - name: Build .NET solution 25 | id: build 26 | run: | 27 | dotnet build gamevault.sln --configuration Release 28 | 7z a GameVault.zip gamevault/bin 29 | 30 | - name: Create Github Tag & Release 31 | id: release 32 | uses: CupOfTea696/gh-action-auto-release@v1.0.2 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | with: 36 | tag: "$semver.0" 37 | 38 | - name: Upload Release Artifact 39 | id: upload 40 | uses: actions/upload-release-asset@v1 41 | with: 42 | asset_path: GameVault.zip 43 | asset_name: GameVault.zip 44 | asset_content_type: application/zip 45 | upload_url: ${{steps.release.outputs.upload_url}} 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | 49 | notify_discord: 50 | needs: deploy 51 | runs-on: ubuntu-latest 52 | steps: 53 | - name: Send Discord Notification 54 | id: discord 55 | uses: Ilshidur/action-discord@master 56 | env: 57 | DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_BOT_WEBHOOK }} 58 | with: 59 | args: '<@&1128857090090340382> New Release: ${{ github.event.repository.full_name }} v${{ needs.deploy.outputs.version }}.0 has been deployed. Here are the changes: https://github.com/${{ github.event.repository.full_name }}/releases/tag/${{ needs.deploy.outputs.version }}.0' 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![logo](https://gamevau.lt/img/logo-text-and-image-sbs.png)](https://gamevau.lt) 2 | 3 | # GameVault Application 4 | 5 | ## Introduction 6 | 7 | **What is GameVault?** 8 | GameVault is an innovative gaming platform providing a self-hosted, source-available alternative to popular gaming platforms. It lets you and your friends enjoy DRM-free games stored on your file server in an organized way. Think of it as a self-hosted Steam. The project you are looking at right now is the client application. 9 | 10 | **Learn More & Get Started** 11 | [You can learn more about the project and find useful guides and information on the official Website.](https://gamevau.lt) 12 | 13 | ## Support 🤝 14 | 15 | We're working hard in our free time to provide you, your friends, and families with the best self-hosted gaming experience. 16 | It would mean a lot to us if you could support us developers by [getting GameVault+](https://gamevau.lt/gamevault-plus). 17 | 18 | Alternatively, you can support us by donating us some spare dollars on any of these platforms: 19 | 20 | - [Ko-Fi](https://ko-fi.com/phalcode) 21 | - [Liberapay](https://liberapay.com/Phalcode) 22 | - [GitHub Sponsors](https://github.com/sponsors/Phalcode) 23 | - [PayPal](https://paypal.me/phalcode) 24 | 25 | **TIP FOR DONATORS:** 26 | If you connect your Discord account to Ko-Fi, you'll automatically receive the "@Supporters" role and permanently stand out in our Discord members list. If you donate through a different platform and want to obtain the role, simply send us a message with your receipt as proof that you're truly a Supporter. 🌟 27 | 28 | ## License 📜 29 | 30 | **[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)** 31 | 32 | This work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/). 33 | 34 | This project is not and never was open-source. [Click here to learn why.](https://gamevau.lt/blog/2023/07/13/) 35 | 36 | ## Legal Disclaimer ⚖️ 37 | 38 | GameVault manages DRM-free games and is solely a tool to address this need. We are not responsible for the content or files users store or share. 39 | 40 | When we say DRM-free games, we only mean games obtained legally. While GameVault can theoretically be used with illegally obtained games, we do not endorse or support piracy. 41 | 42 | Users must be aware of and comply with copyright laws in their respective jurisdictions. We encourage responsible and legal use of GameVault. Unlawful use is strictly improper and unauthorized. 43 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | The following Application Versions are supported by Phalcode and get regular security updates. 6 | 7 | | Version | Regular Updates | Supported | 8 | | ------- | --------------- |---------- | 9 | | ``Latest Minor Version`` | :white_check_mark: | :white_check_mark: | 10 | | ``Early Access Version`` | :white_check_mark: | :white_check_mark: | 11 | | ``Older Versions`` | :x: | :x: | 12 | 13 | ## Reporting a Vulnerability 14 | Please report any vulnerabilities to Phalcode [via Email](mailto:contact@phalco.de). 15 | -------------------------------------------------------------------------------- /gamevault/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /gamevault/AssemblyInfo.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/AssemblyInfo.cs -------------------------------------------------------------------------------- /gamevault/Converter/ContainsCurrentUserConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Helper; 2 | using gamevault.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Data; 10 | 11 | namespace gamevault.Converter 12 | { 13 | internal class ContainsCurrentUserConverter : IValueConverter 14 | { 15 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | try 18 | { 19 | if (value.GetType() == typeof(List)) 20 | { 21 | return ((List)value).Any(u => u.ID == LoginManager.Instance.GetCurrentUser().ID); 22 | } 23 | } 24 | catch { } 25 | return false; 26 | } 27 | 28 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 29 | { 30 | return false; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gamevault/Converter/DownloadLimitConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace gamevault.Converter 10 | { 11 | internal class DownloadLimitConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | try 16 | { 17 | double size = double.Parse(value.ToString()); 18 | if (size == 0) 19 | { 20 | return "Unlimited"; 21 | } 22 | 23 | if (size >= 1000000) 24 | { 25 | size /= 1000000; 26 | size = Math.Round(size, 2); 27 | return $"{size} GB/s"; 28 | } 29 | else if (size >= 1000) 30 | { 31 | size /= 1000; 32 | size = Math.Round(size, 2); 33 | return $"{size} MB/s"; 34 | } 35 | else 36 | { 37 | size = Math.Round(size, 2); 38 | return $"{size} KB/s"; 39 | } 40 | } 41 | catch 42 | { 43 | return "Calc error"; 44 | } 45 | } 46 | 47 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 48 | { 49 | return ""; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /gamevault/Converter/EnumDescriptionConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Globalization; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Data; 10 | 11 | namespace gamevault.Converter 12 | { 13 | internal class EnumDescriptionConverter : IValueConverter 14 | { 15 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | if (value is GameType && (GameType)value != GameType.UNDETECTABLE) 18 | { 19 | string result = ((DescriptionAttribute[])typeof(GameType).GetField(((GameType)value).ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false))[0].Description.ToString(); 20 | return result; 21 | } 22 | else if (value is State) 23 | { 24 | string result = ((DescriptionAttribute[])typeof(State).GetField(((State)value).ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false))[0].Description.ToString(); 25 | return result; 26 | } 27 | return string.Empty; 28 | } 29 | 30 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 31 | { 32 | return string.Empty; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /gamevault/Converter/GameSettingsTabVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Helper; 2 | using gamevault.Models; 3 | using gamevault.ViewModels; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Globalization; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows; 11 | using System.Windows.Data; 12 | 13 | namespace gamevault.Converter 14 | { 15 | internal class GameSettingsTabVisibilityConverter : IValueConverter 16 | { 17 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | if (((Game)value) == null) 20 | return Visibility.Collapsed; 21 | if (parameter.ToString() == "local") 22 | { 23 | if (InstallViewModel.Instance.InstalledGames.Where(g => g.Key.ID == ((Game)value).ID).Count() > 0) 24 | { 25 | return Visibility.Visible; 26 | } 27 | } 28 | else if (parameter.ToString() == "server") 29 | { 30 | if (LoginManager.Instance.IsLoggedIn() && (LoginManager.Instance.GetCurrentUser() != null && LoginManager.Instance.GetCurrentUser().Role >= PERMISSION_ROLE.EDITOR)) 31 | { 32 | return Visibility.Visible; 33 | } 34 | } 35 | return Visibility.Collapsed; 36 | } 37 | 38 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 39 | { 40 | return false; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /gamevault/Converter/GameSizeConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | using System.Windows.Media.Imaging; 6 | 7 | namespace gamevault.Converter 8 | { 9 | internal class GameSizeConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | try 14 | { 15 | if (value == null) 16 | { 17 | throw new ArgumentException("Invalid input value"); 18 | } 19 | 20 | double size = double.Parse(value.ToString()); 21 | 22 | // DEFAULTS TO IEC (1024) used for storage capacity etc. 23 | int baseValue = 1024; 24 | if (parameter != null && parameter is int) 25 | { 26 | // Other Standard could be SI (1000) used for download speeds etc. 27 | baseValue = (int)parameter; 28 | } 29 | 30 | string[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; 31 | 32 | int suffixIndex = 0; 33 | while (size >= baseValue && suffixIndex < sizeSuffixes.Length - 1) 34 | { 35 | size /= baseValue; 36 | suffixIndex++; 37 | } 38 | 39 | size = Math.Round(size, 2); 40 | return $"{size} {sizeSuffixes[suffixIndex]}"; 41 | } 42 | catch (Exception ex) 43 | { 44 | return "ERR"; 45 | } 46 | } 47 | 48 | 49 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 50 | { 51 | return ""; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /gamevault/Converter/GameStateColorConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Globalization; 4 | using System.Windows.Data; 5 | using System.Windows.Media; 6 | 7 | namespace gamevault.Converter 8 | { 9 | class GameStateColorConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | try 14 | { 15 | State state = (State)Enum.Parse(typeof(State), value.ToString()); 16 | switch(state) 17 | { 18 | case State.UNPLAYED: 19 | return Brushes.DarkGray; 20 | case State.INFINITE: 21 | return Brushes.Yellow; 22 | case State.PLAYING: 23 | return Brushes.Green; 24 | case State.COMPLETED: 25 | return Brushes.Violet; 26 | case State.ABORTED_TEMPORARY: 27 | return Brushes.Orange; 28 | case State.ABORTED_PERMANENT: 29 | return Brushes.Red; 30 | default: 31 | return null; 32 | } 33 | 34 | } 35 | catch (Exception ex) 36 | { 37 | return null; 38 | } 39 | } 40 | 41 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 42 | { 43 | return null; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /gamevault/Converter/GameStateDescriptionConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.ComponentModel; 4 | using System.Globalization; 5 | using System.Windows.Data; 6 | 7 | namespace gamevault.Converter 8 | { 9 | internal class GameStateDescriptionConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | State enumValue = (State)Enum.Parse(typeof(State), value as string); 14 | string result = ((DescriptionAttribute[])typeof(State).GetField(((State)enumValue).ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false))[0].Description.ToString(); 15 | return result; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | return string.Empty; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gamevault/Converter/GameTimeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace gamevault.Converter 10 | { 11 | internal class GameTimeConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | try 16 | { 17 | if (value != null) 18 | { 19 | int minutes = (int)value; 20 | if (minutes < 60) 21 | { 22 | return $"{minutes} min"; 23 | } 24 | double hours = (double)minutes / 60; 25 | hours = Math.Round(hours, 1); 26 | return $"{hours} h"; 27 | } 28 | return "?"; 29 | } 30 | catch (Exception ex) 31 | { 32 | return "?"; 33 | } 34 | } 35 | 36 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 37 | { 38 | return ""; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /gamevault/Converter/GameViewSettingsPermissionRoleToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Helper; 2 | using gamevault.Models; 3 | using System; 4 | using System.Globalization; 5 | using System.Windows; 6 | using System.Windows.Data; 7 | 8 | namespace gamevault.Converter 9 | { 10 | internal class GameViewSettingsPermissionRoleToVisibilityConverter : IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 13 | { 14 | bool isInstalled = (bool)value; 15 | if (isInstalled || ((LoginManager.Instance.GetCurrentUser() != null && LoginManager.Instance.GetCurrentUser().Role >= PERMISSION_ROLE.EDITOR))) 16 | { 17 | return Visibility.Visible; 18 | } 19 | return Visibility.Collapsed; 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 23 | { 24 | return false; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /gamevault/Converter/GreaterThanConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace gamevault.Converter 10 | { 11 | internal class GreaterThanConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | return ((int)value > int.Parse((string)parameter)); 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | return null; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gamevault/Converter/InverseBoolConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows.Data; 9 | using System.Windows.Media.Imaging; 10 | 11 | namespace gamevault.Converter 12 | { 13 | internal class InverseBoolConverter : IValueConverter 14 | { 15 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | return !((bool)value); 18 | } 19 | 20 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 21 | { 22 | return null; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /gamevault/Converter/InverseEmptyStringConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace gamevault.Converter 10 | { 11 | internal class InverseEmptyStringConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | return (value == null || value.ToString() == string.Empty); 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | return null; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gamevault/Converter/InverseNullConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace gamevault.Converter 10 | { 11 | internal class InverseNullConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | return (value == null); 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | return null; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gamevault/Converter/InverseVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | 10 | namespace gamevault.Converter 11 | { 12 | internal class InverseVisibilityConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | Visibility visibility = (Visibility)value; 17 | if(visibility == Visibility.Visible) 18 | { 19 | return Visibility.Hidden; 20 | } 21 | else 22 | { 23 | return Visibility.Visible; 24 | } 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 28 | { 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gamevault/Converter/IsGameDownloadedConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using gamevault.ViewModels; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.Globalization; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Data; 11 | 12 | namespace gamevault.Converter 13 | { 14 | internal class IsGameDownloadedConverter : IValueConverter 15 | { 16 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | //Debug.WriteLine("IsDownloaded"); 19 | if (value == null) 20 | return false; 21 | return DownloadsViewModel.Instance.DownloadedGames.Where(gameUC => gameUC.GetGameId() == (int)value).Count() > 0; 22 | } 23 | 24 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 25 | { 26 | return false; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /gamevault/Converter/IsGameMappedConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using gamevault.Models.Mapping; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Data; 10 | 11 | namespace gamevault.Converter 12 | { 13 | internal class IsGameMappedConverter : IMultiValueConverter 14 | { 15 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | try 18 | { 19 | if (values[1].GetType() == typeof(GameMetadata)) 20 | { 21 | return ((List)values[0]).Any(entry => entry.ProviderSlug == ((GameMetadata)values[1]).ProviderSlug); 22 | } 23 | else if(values[1].GetType() == typeof(MetadataProviderDto)) 24 | { 25 | return ((List)values[0]).Any(entry => entry.ProviderSlug == ((MetadataProviderDto)values[1]).Slug); 26 | } 27 | else 28 | { 29 | return false; 30 | } 31 | } 32 | catch { return false; } 33 | } 34 | 35 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 36 | { 37 | return null; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /gamevault/Converter/LibraryPermissionRoleToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Helper; 2 | using gamevault.Models; 3 | using System; 4 | using System.Diagnostics; 5 | using System.Globalization; 6 | using System.Windows; 7 | using System.Windows.Data; 8 | 9 | namespace gamevault.Converter 10 | { 11 | internal class LibraryPermissionRoleToVisibilityConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | //Debug.WriteLine("PermRoleVis"); 16 | if ((LoginManager.Instance.GetCurrentUser() != null && LoginManager.Instance.GetCurrentUser().Role >= PERMISSION_ROLE.EDITOR)) 17 | { 18 | return Visibility.Visible; 19 | } 20 | return Visibility.Hidden; 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | return false; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /gamevault/Converter/LicenseConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.ViewModels; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows.Data; 9 | 10 | namespace gamevault.Converter 11 | { 12 | public class LicenseConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return SettingsViewModel.Instance.License.IsActive(); 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | return null; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /gamevault/Converter/PermissionRoleConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using gamevault.UserControls; 3 | using gamevault.ViewModels; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Globalization; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Data; 11 | 12 | namespace gamevault.Converter 13 | { 14 | internal class PermissionRoleConverter : IValueConverter 15 | { 16 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | if ((User)value != null && ((User)value).Role == PERMISSION_ROLE.ADMIN) 19 | { 20 | return true; 21 | } 22 | return false; 23 | } 24 | 25 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 26 | { 27 | return false; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /gamevault/Converter/PermissionRoleToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Helper; 2 | using gamevault.Models; 3 | using MahApps.Metro.Controls; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Globalization; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows; 11 | using System.Windows.Data; 12 | 13 | namespace gamevault.Converter 14 | { 15 | internal class PermissionRoleToVisibilityConverter : IValueConverter 16 | { 17 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | if ((int)value == 0 || (LoginManager.Instance.GetCurrentUser() != null && LoginManager.Instance.GetCurrentUser().Role == PERMISSION_ROLE.ADMIN)) 20 | { 21 | return Visibility.Visible; 22 | } 23 | return Visibility.Hidden; 24 | } 25 | 26 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 27 | { 28 | return false; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /gamevault/Converter/ShowMappedTitleConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows.Data; 9 | 10 | namespace gamevault.Converter 11 | { 12 | public class ShowMappedTitleConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | 17 | bool showMappedTitle = Preferences.Get(AppConfigKey.ShowMappedTitle, AppFilePath.UserFile) == "1"; 18 | if (showMappedTitle && value is Game game && !string.IsNullOrWhiteSpace(game?.Metadata?.Title)) 19 | { 20 | return true; 21 | } 22 | return false; 23 | 24 | } 25 | 26 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /gamevault/Converter/StringToArrayConverter.cs: -------------------------------------------------------------------------------- 1 | using ImageMagick; 2 | using System; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Windows.Data; 6 | 7 | namespace gamevault.Converter 8 | { 9 | internal class StringToArrayConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | try 14 | { 15 | if (value == null) 16 | return new string[] { }; 17 | 18 | if (value.GetType().IsArray)//If its array, then the viewmodel was set insted of the UI 19 | { 20 | var joined = string.Join(",", (string[])value); 21 | return joined; 22 | } 23 | else 24 | { 25 | return value.ToString().Split(new[] { parameter.ToString() }, StringSplitOptions.RemoveEmptyEntries) 26 | .Select(s => s.Trim()) 27 | .ToArray(); 28 | } 29 | } 30 | catch { return new string[] { }; } 31 | } 32 | 33 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 34 | { 35 | try 36 | { 37 | return value.ToString().Split(new[] { parameter.ToString() }, StringSplitOptions.None) 38 | .Select(s => s.Trim()) 39 | .ToArray(); 40 | } 41 | catch { return null; } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /gamevault/Converter/StringToColorConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | using System.Windows.Media; 5 | 6 | namespace gamevault.Converter 7 | { 8 | internal class StringToColorConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (value is string stringValue) 13 | { 14 | int hashCode = stringValue.GetHashCode(); 15 | Color generatedColor = GenerateColor(hashCode); 16 | SolidColorBrush brush = new SolidColorBrush(generatedColor); 17 | brush.Freeze(); 18 | return brush; 19 | } 20 | return Brushes.Black; 21 | } 22 | private Color GenerateColor(int numericValue) 23 | { 24 | byte red = (byte)((numericValue >> 16) & 0xFF); 25 | byte green = (byte)((numericValue >> 8) & 0xFF); 26 | byte blue = (byte)(numericValue & 0xFF); 27 | 28 | // Ensure the color is saturated by setting the maximum component to 255 29 | byte maxComponent = Math.Max(red, Math.Max(green, blue)); 30 | if (maxComponent > 0) 31 | { 32 | float scale = 200f / maxComponent; 33 | red = (byte)(red * scale); 34 | green = (byte)(green * scale); 35 | blue = (byte)(blue * scale); 36 | } 37 | 38 | return Color.FromRgb(red, green, blue); 39 | } 40 | 41 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 42 | { 43 | return Colors.White; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /gamevault/Converter/UTCtoLocalTimeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace gamevault.Converter 10 | { 11 | internal class UTCtoLocalTimeConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | if (value != null) 16 | { 17 | return ((DateTime)value).ToLocalTime(); 18 | } 19 | return null; 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 23 | { 24 | if (value != null) 25 | { 26 | return ((DateTime)value).ToUniversalTime().ToString(); 27 | } 28 | return null; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /gamevault/Converter/UrlImageConverter.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows.Data; 9 | using System.Windows.Media.Imaging; 10 | 11 | namespace gamevault.Converter 12 | { 13 | internal class UrlImageConverter : IValueConverter 14 | { 15 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | try 18 | { 19 | return new BitmapImage(new Uri((string)value)) { CacheOption = BitmapCacheOption.OnLoad }; 20 | } 21 | catch (Exception ex) 22 | { 23 | return null; 24 | } 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 28 | { 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gamevault/Helper/CommandHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Input; 7 | 8 | namespace gamevault.Helper 9 | { 10 | internal class CommandHelper : ICommand 11 | { 12 | public event EventHandler Executed; 13 | 14 | public bool CanExecute(object parameter) 15 | { 16 | return true; 17 | } 18 | 19 | public void Execute(object parameter) 20 | { 21 | if (Executed != null) 22 | Executed(this, parameter); 23 | } 24 | 25 | public event EventHandler CanExecuteChanged; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /gamevault/Helper/CrashReportHelper.cs: -------------------------------------------------------------------------------- 1 | using gamevault.ViewModels; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Management; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.Helper 10 | { 11 | public struct CrashReport 12 | { 13 | public string source { get; set; } 14 | public string message { get; set; } 15 | public string stackTrace { get; set; } 16 | public string systemInfo { get; set; } 17 | } 18 | 19 | internal class CrashReportHelper 20 | { 21 | public static void SendCrashReport(string errrorMessage, string stackTrace, string unhandledExceptionType) 22 | { 23 | try 24 | { 25 | string sysInfo = $"Version: {SettingsViewModel.Instance.Version} | Is Windows Package: {(App.IsWindowsPackage == true ? "True" : "False")}"; 26 | try 27 | { 28 | sysInfo += "\n" + GetSysInfo(); 29 | } 30 | catch { } 31 | CrashReport crashReport = new CrashReport { source = "GameVault Client", message = $"({unhandledExceptionType}): {errrorMessage}", stackTrace = stackTrace, systemInfo = sysInfo }; 32 | string parameter = System.Text.Json.JsonSerializer.Serialize(crashReport); 33 | using (System.Net.WebClient wc = new System.Net.WebClient()) 34 | { 35 | wc.Headers[System.Net.HttpRequestHeader.ContentType] = "application/json"; 36 | string url = Encoding.UTF8.GetString(Convert.FromBase64String("aHR0cHM6Ly9waGFsY29kZS1zdXBwb3J0LWJhY2tlbmQucGxhdGZvcm0ucGhhbGNvLmRlL2NyYXNo")); 37 | string HtmlResult = wc.UploadString(url, parameter); 38 | } 39 | } 40 | catch (Exception ex) 41 | { 42 | } 43 | } 44 | public static string GetSysInfo() 45 | { 46 | var OS = new ManagementObjectSearcher("select * from Win32_OperatingSystem").Get().Cast().First(); 47 | string os = $"OS: {OS["Caption"]} - {OS["OSArchitecture"]} - Version.{OS["Version"]}"; os = os.Replace("NT 5.1.2600", "XP"); os = os.Replace("NT 5.2.3790", "Server 2003"); 48 | string ram = $"RAM: {OS["TotalVisibleMemorySize"]} KB"; 49 | var CPU = new ManagementObjectSearcher("select * from Win32_Processor").Get().Cast().First(); 50 | string cpu = $"CPU: {CPU["Name"]} - {CPU["MaxClockSpeed"]} MHz - {CPU["NumberOfCores"]} Core"; 51 | return $"{os}; {ram}; {cpu};"; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /gamevault/Helper/DownloadSpeedCalculator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace gamevault.Helper 8 | { 9 | public class ExponentialMovingAverage 10 | { 11 | private double alpha; 12 | private double average; 13 | 14 | public ExponentialMovingAverage(double alpha) 15 | { 16 | this.alpha = alpha; 17 | average = 0; 18 | } 19 | 20 | public void Add(double value) 21 | { 22 | if (average == 0) 23 | average = value; 24 | else 25 | average = alpha * value + (1 - alpha) * average; 26 | } 27 | 28 | public double Calculate() 29 | { 30 | return average; 31 | } 32 | } 33 | public class DownloadSpeedCalculator 34 | { 35 | private ExponentialMovingAverage speedAverage; 36 | private long lastDownloadedBytes; 37 | private DateTime lastUpdateTime; 38 | 39 | public DownloadSpeedCalculator(double smoothingFactor = 0.3) 40 | { 41 | speedAverage = new ExponentialMovingAverage(smoothingFactor); 42 | lastDownloadedBytes = 0; 43 | lastUpdateTime = DateTime.Now; 44 | } 45 | 46 | public void UpdateSpeed(long currentDownloadedBytes) 47 | { 48 | DateTime currentTime = DateTime.Now; 49 | TimeSpan elapsedTime = currentTime - lastUpdateTime; 50 | 51 | if (elapsedTime.TotalSeconds > 0) 52 | { 53 | double downloadSpeed = (currentDownloadedBytes - lastDownloadedBytes) / elapsedTime.TotalSeconds; 54 | speedAverage.Add(downloadSpeed); 55 | lastDownloadedBytes = currentDownloadedBytes; 56 | lastUpdateTime = currentTime; 57 | } 58 | } 59 | 60 | public double GetCurrentSpeed() 61 | { 62 | return speedAverage.Calculate(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /gamevault/Helper/InputTimer.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Threading; 2 | 3 | namespace gamevault.Helper 4 | { 5 | public class InputTimer : DispatcherTimer 6 | { 7 | public string Data; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /gamevault/Helper/Integrations/AutostartHelper.cs: -------------------------------------------------------------------------------- 1 | using gamevault.ViewModels; 2 | using Microsoft.Win32; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Windows.ApplicationModel; 10 | 11 | namespace gamevault.Helper 12 | { 13 | internal class AutostartHelper 14 | { 15 | internal static void RegistryCreateAutostartKey() 16 | { 17 | RegistryKey? rk = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); 18 | string exePath = $"{Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)}\\gamevault.exe"; 19 | rk.SetValue("GameVault", exePath); 20 | } 21 | internal static void RegistryDeleteAutostartKey() 22 | { 23 | RegistryKey? rk = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); 24 | if (rk.GetValue("GameVault") != null) 25 | { 26 | rk.DeleteValue("GameVault"); 27 | } 28 | } 29 | internal static bool RegistryAutoStartKeyExists() 30 | { 31 | RegistryKey? rk = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); 32 | return rk.GetValue("GameVault") != null; 33 | } 34 | internal async static Task IsWindowsPackageAutostartEnabled() 35 | { 36 | StartupTask startupTask = await StartupTask.GetAsync("AutostartGameVault"); 37 | return startupTask.State == StartupTaskState.Enabled; 38 | } 39 | internal async static Task HandleWindowsPackageAutostart() 40 | { 41 | StartupTask startupTask = await StartupTask.GetAsync("AutostartGameVault"); 42 | switch (startupTask.State) 43 | { 44 | case StartupTaskState.Disabled: 45 | StartupTaskState newState = await startupTask.RequestEnableAsync(); 46 | if (newState != StartupTaskState.Enabled) 47 | { 48 | MainWindowViewModel.Instance.AppBarText = "Unable to activate autostart."; 49 | } 50 | break; 51 | case StartupTaskState.DisabledByUser: 52 | MainWindowViewModel.Instance.AppBarText = "Autostart was disabled manually. Please access task manager to reactivate it."; 53 | break; 54 | case StartupTaskState.DisabledByPolicy: 55 | MainWindowViewModel.Instance.AppBarText = "Autostart is either disabled due to policy or not supported on your device."; 56 | break; 57 | case StartupTaskState.Enabled: 58 | startupTask.Disable(); 59 | break; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /gamevault/Helper/Integrations/DesktopHelper.cs: -------------------------------------------------------------------------------- 1 | using gamevault.ViewModels; 2 | using MahApps.Metro.Controls.Dialogs; 3 | using MahApps.Metro.Controls; 4 | using System; 5 | using System.IO; 6 | using System.Threading.Tasks; 7 | using gamevault.Models; 8 | 9 | namespace gamevault.Helper 10 | { 11 | public static class DesktopHelper 12 | { 13 | public static async Task CreateShortcut(Game game, string iconPath, bool ask) 14 | { 15 | try 16 | { 17 | string desktopDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 18 | string shortcutPath = desktopDir + @"\\" + game.Title + ".url"; 19 | if (File.Exists(shortcutPath)) 20 | { 21 | MainWindowViewModel.Instance.AppBarText = "Desktop shortcut already exists"; 22 | return; 23 | } 24 | if (ask) 25 | { 26 | MessageDialogResult result = await ((MetroWindow)App.Current.MainWindow).ShowMessageAsync($"Do you want to create a desktop shortcut for {game.Title}?", "", 27 | MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings() { AffirmativeButtonText = "Yes", NegativeButtonText = "No", AnimateHide = false }); 28 | 29 | if (result != MessageDialogResult.Affirmative) 30 | return; 31 | } 32 | using (StreamWriter writer = new StreamWriter(shortcutPath)) 33 | { 34 | writer.Write("[InternetShortcut]\r\n"); 35 | writer.Write($"URL=gamevault://start?gameid={game.ID}" + "\r\n"); 36 | writer.Write("IconIndex=0\r\n"); 37 | writer.Write("IconFile=" + iconPath.Replace('\\', '/') + "\r\n"); 38 | //writer.WriteLine($"WorkingDirectory={Path.GetDirectoryName(SavedExecutable).Replace('\\', '/')}"); 39 | writer.Flush(); 40 | } 41 | 42 | } 43 | catch { } 44 | } 45 | public static void RemoveShotcut(Game game) 46 | { 47 | try 48 | { 49 | string desktopDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 50 | string shortcutPath = desktopDir + @"\\" + game.Title + ".url"; 51 | if (File.Exists(shortcutPath)) 52 | { 53 | File.Delete(shortcutPath); 54 | } 55 | } 56 | catch { } 57 | } 58 | public static bool ShortcutExists(Game game) 59 | { 60 | string desktopDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 61 | string shortcutPath = desktopDir + @"\\" + game.Title + ".url"; 62 | return File.Exists(shortcutPath); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /gamevault/Helper/Integrations/DiscordHelper.cs: -------------------------------------------------------------------------------- 1 | using DiscordRPC; 2 | using DiscordRPC.Logging; 3 | using gamevault.Models; 4 | using gamevault.ViewModels; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace gamevault.Helper 13 | { 14 | internal class DiscordHelper 15 | { 16 | #region Singleton 17 | private static DiscordHelper instance = null; 18 | private static readonly object padlock = new object(); 19 | 20 | public static DiscordHelper Instance 21 | { 22 | get 23 | { 24 | lock (padlock) 25 | { 26 | if (instance == null) 27 | { 28 | instance = new DiscordHelper(); 29 | } 30 | return instance; 31 | } 32 | } 33 | } 34 | #endregion 35 | private DiscordRpcClient client; 36 | private int currentGameId = -1; 37 | internal DiscordHelper() 38 | { 39 | try 40 | { 41 | client = new DiscordRpcClient(Encoding.UTF8.GetString(Convert.FromBase64String("MTMxMzIyNTUxNjUwOTMwMjgxNQ=="))); 42 | } 43 | catch { } 44 | } 45 | internal void SyncGameWithDiscordPresence(List trackedGameIds, Dictionary installedGames) 46 | { 47 | try 48 | { 49 | if (!SettingsViewModel.Instance.SyncDiscordPresence || !SettingsViewModel.Instance.License.IsActive()) 50 | return; 51 | 52 | if (!client.IsInitialized) 53 | { 54 | client.Initialize(); 55 | } 56 | if (currentGameId != -1 && !trackedGameIds.Contains(currentGameId)) 57 | { 58 | client.ClearPresence(); 59 | currentGameId = -1; 60 | } 61 | if (trackedGameIds.Count <= 0) 62 | return; 63 | 64 | KeyValuePair firstGame = installedGames.First(g => g.Key == trackedGameIds.First()); 65 | string gameTitle = Path.GetFileName(firstGame.Value.TrimEnd(Path.DirectorySeparatorChar)); 66 | gameTitle = gameTitle.Replace($"({firstGame.Key})", ""); 67 | client.SetPresence(new RichPresence() 68 | { 69 | Details = gameTitle, 70 | Buttons = new Button[] { new Button() { Label = "What's GameVault?", Url = "https://gamevau.lt/" } } 71 | }); 72 | currentGameId = firstGame.Key; 73 | } 74 | catch { } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /gamevault/Helper/Integrations/StoreHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows; 6 | using Windows.Foundation; 7 | using Windows.Services.Store; 8 | 9 | namespace gamevault.Helper 10 | { 11 | internal class StoreHelper 12 | { 13 | private StoreContext context = null; 14 | private IReadOnlyList updates = null; 15 | internal StoreHelper() 16 | { 17 | if (context == null) 18 | { 19 | context = StoreContext.GetDefault(); 20 | } 21 | } 22 | public async Task UpdatesAvailable() 23 | { 24 | updates = await context.GetAppAndOptionalStorePackageUpdatesAsync(); 25 | if (updates.Count != 0) 26 | { 27 | return true; 28 | } 29 | return false; 30 | } 31 | public async Task DownloadAndInstallAllUpdatesAsync(Window window) 32 | { 33 | var wih = new System.Windows.Interop.WindowInteropHelper(window); 34 | var handlePtr = wih.Handle; 35 | //var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window); 36 | WinRT.Interop.InitializeWithWindow.Initialize(context, handlePtr); 37 | IAsyncOperationWithProgress installOperation = this.context.RequestDownloadAndInstallStorePackageUpdatesAsync(updates); 38 | StorePackageUpdateResult result = await installOperation.AsTask(); 39 | switch (result.OverallState) 40 | { 41 | case StorePackageUpdateState.Completed: 42 | break; 43 | case StorePackageUpdateState.Canceled: 44 | UpdateCanceledException(); 45 | break; 46 | default: 47 | var failedUpdates = result.StorePackageUpdateStatuses.Where(status => status.PackageUpdateState != StorePackageUpdateState.Completed); 48 | 49 | if (failedUpdates.Count() != 0) 50 | { 51 | PackageException(); 52 | } 53 | break; 54 | } 55 | } 56 | public void NoInternetException() 57 | { 58 | MessageBox.Show("Cannot connect to microsoft services", "Connection failed", MessageBoxButton.OK, MessageBoxImage.Warning); 59 | } 60 | private void PackageException() 61 | { 62 | MessageBox.Show("Updates were not installed as intended.", "Update failed", MessageBoxButton.OK, MessageBoxImage.Warning); 63 | } 64 | private void UpdateCanceledException() 65 | { 66 | MessageBox.Show("Updates were not installed as intended.", "Update canceled", MessageBoxButton.OK, MessageBoxImage.Warning); 67 | //MessageBox.Show("GameVault can not start because the Updates were not installed.", "Updates not installed", MessageBoxButton.OK, MessageBoxImage.Information); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /gamevault/Helper/Integrations/ToastMessageHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Toolkit.Uwp.Notifications; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.Helper 10 | { 11 | public class ToastMessageHelper 12 | { 13 | public static void CreateToastMessage(string title, string message, string imageUri = "") 14 | { 15 | try 16 | { 17 | var builder = new ToastContentBuilder().AddText(title).AddText(message); 18 | if (imageUri != "" && File.Exists(imageUri)) 19 | { 20 | builder.AddInlineImage(new Uri(imageUri)); 21 | } 22 | builder.Show(); 23 | } 24 | catch { } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /gamevault/Helper/Media/BitmapHelper.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Drawing; 4 | using System.Drawing.Imaging; 5 | using System.IO; 6 | using System.Net.Http; 7 | using System.Threading.Tasks; 8 | using System.Windows.Media.Imaging; 9 | 10 | namespace gamevault.Helper 11 | { 12 | internal class BitmapHelper 13 | { 14 | public static BitmapImage GetBitmapImage(string uri) 15 | { 16 | var image = new BitmapImage(); 17 | image.BeginInit(); 18 | image.CacheOption = BitmapCacheOption.OnLoad; 19 | image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; 20 | image.UriSource = new Uri(uri); 21 | image.EndInit(); 22 | return image; 23 | } 24 | public static async Task GetBitmapImageAsync(string uri) 25 | { 26 | BitmapImage bitmap = null; 27 | 28 | var httpclient = new HttpClient(); 29 | 30 | using (var response = await httpclient.GetAsync(uri)) 31 | { 32 | if (response.IsSuccessStatusCode) 33 | { 34 | using (var stream = new MemoryStream()) 35 | { 36 | await response.Content.CopyToAsync(stream); 37 | stream.Seek(0, SeekOrigin.Begin); 38 | 39 | bitmap = new BitmapImage(); 40 | bitmap.BeginInit(); 41 | bitmap.CacheOption = BitmapCacheOption.OnLoad; 42 | bitmap.StreamSource = stream; 43 | bitmap.EndInit(); 44 | bitmap.Freeze(); 45 | } 46 | } 47 | } 48 | 49 | return bitmap; 50 | } 51 | public static async Task GetBitmapImageAsync(MemoryStream stream) 52 | { 53 | BitmapImage bitmap = null; 54 | stream.Position = 0; 55 | bitmap = new BitmapImage(); 56 | bitmap.BeginInit(); 57 | bitmap.CacheOption = BitmapCacheOption.OnLoad; 58 | bitmap.StreamSource = stream; 59 | bitmap.EndInit(); 60 | bitmap.Freeze(); 61 | return bitmap; 62 | } 63 | public static async Task UrlToMemoryStream(string url) 64 | { 65 | MemoryStream stream = new MemoryStream(); 66 | using (HttpClient client = new HttpClient()) 67 | { 68 | using (HttpResponseMessage response = await client.GetAsync(url)) 69 | { 70 | if (response.IsSuccessStatusCode) 71 | { 72 | await response.Content.CopyToAsync(stream); 73 | stream.Position = 0; 74 | } 75 | } 76 | } 77 | return stream; 78 | } 79 | public static MemoryStream UriToMemoryStream(string url) 80 | { 81 | MemoryStream ms = new MemoryStream(); 82 | using (FileStream file = new FileStream(url, FileMode.Open, FileAccess.Read)) 83 | file.CopyTo(ms); 84 | 85 | ms.Position = 0; 86 | return ms; 87 | } 88 | public static MemoryStream BitmapSourceToMemoryStream(BitmapSource src) 89 | { 90 | System.Drawing.Bitmap bitmap; 91 | MemoryStream pasteStream = new MemoryStream(); 92 | using (MemoryStream outStream = new MemoryStream()) 93 | { 94 | BitmapEncoder enc = new JpegBitmapEncoder(); 95 | enc.Frames.Add(BitmapFrame.Create(src)); 96 | enc.Save(outStream); 97 | bitmap = new System.Drawing.Bitmap(outStream); 98 | bitmap.Save(pasteStream, ImageFormat.Jpeg); 99 | } 100 | pasteStream.Seek(0, SeekOrigin.Begin); 101 | return pasteStream; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /gamevault/Helper/ProcessHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.Helper 10 | { 11 | internal class ProcessHelper 12 | { 13 | internal static Process StartApp(string fileName, string parameter = "", bool asAdmin = false) 14 | { 15 | ProcessStartInfo app = new ProcessStartInfo(); 16 | if (parameter != "") 17 | { 18 | app.Arguments = parameter; 19 | } 20 | app.FileName = fileName; 21 | app.WorkingDirectory = Path.GetDirectoryName(fileName); 22 | app.UseShellExecute = true; 23 | if (asAdmin) 24 | { 25 | app.Verb = "runas"; 26 | } 27 | return Process.Start(app); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /gamevault/Helper/ScrollViewerHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Controls.Primitives; 10 | using System.Windows.Input; 11 | 12 | namespace gamevault.Helper 13 | { 14 | public static class ScrollViewerHelper 15 | { 16 | public static readonly DependencyProperty ScrollBarHeightProperty = DependencyProperty.RegisterAttached("ScrollBarHeight", typeof(int), typeof(ScrollViewerHelper), new FrameworkPropertyMetadata(-1, OnScrollBarHeightPropertyChanged)); 17 | public static readonly DependencyProperty EnableHorizontalScrollProperty = DependencyProperty.RegisterAttached("EnableHorizontalScroll", typeof(bool), typeof(ScrollViewerHelper), new FrameworkPropertyMetadata(false, OnEnableHorizontalScrollChanged)); 18 | 19 | [AttachedPropertyBrowsableForType(typeof(ScrollViewer))] 20 | public static int GetScrollBarHeight(DependencyObject obj) 21 | { 22 | return (int)obj.GetValue(ScrollBarHeightProperty); 23 | } 24 | [AttachedPropertyBrowsableForType(typeof(ScrollViewer))] 25 | public static void SetScrollBarHeight(DependencyObject obj, int value) 26 | { 27 | obj.SetValue(ScrollBarHeightProperty, value); 28 | } 29 | [AttachedPropertyBrowsableForType(typeof(ScrollViewer))] 30 | public static bool GetEnableHorizontalScroll(DependencyObject obj) 31 | { 32 | return (bool)obj.GetValue(EnableHorizontalScrollProperty); 33 | } 34 | [AttachedPropertyBrowsableForType(typeof(ScrollViewer))] 35 | public static void SetEnableHorizontalScroll(DependencyObject obj, bool value) 36 | { 37 | obj.SetValue(EnableHorizontalScrollProperty, value); 38 | } 39 | public static void OnScrollBarHeightPropertyChanged(object sender, DependencyPropertyChangedEventArgs e) 40 | { 41 | int newValue = (int)e.NewValue; 42 | if (!(sender is ScrollViewer scrollViewer) || newValue < 0) 43 | { 44 | return; 45 | } 46 | ScrollViewer sc = (ScrollViewer)sender; 47 | ScrollBar scrollbar = (ScrollBar)sc.Template.FindName("PART_HorizontalScrollBar", sc); 48 | if (scrollbar != null) 49 | { 50 | scrollbar.Height = newValue; 51 | } 52 | else 53 | { 54 | sc.Loaded += (s, e) => 55 | { 56 | ScrollBar bar = (ScrollBar)sc.Template.FindName("PART_HorizontalScrollBar", sc); 57 | if (bar != null) 58 | { 59 | bar.Height = newValue; 60 | } 61 | }; 62 | } 63 | } 64 | public static void OnEnableHorizontalScrollChanged(object sender, DependencyPropertyChangedEventArgs e) 65 | { 66 | if (!(sender is ScrollViewer scrollViewer) || (bool)e.NewValue == false) 67 | { 68 | return; 69 | } 70 | ScrollViewer sc = (ScrollViewer)sender; 71 | sc.PreviewMouseWheel += (s, p) => 72 | { 73 | if (((ScrollViewer)s).ComputedHorizontalScrollBarVisibility == Visibility.Visible) 74 | { 75 | p.Handled = true; 76 | if (p.Delta > 0) 77 | ((ScrollViewer)s).LineLeft(); 78 | else 79 | ((ScrollViewer)s).LineRight(); 80 | } 81 | else//Bubble event up to parent if horizontal scrollbar is not needed 82 | { 83 | p.Handled = true; 84 | ScrollViewer parent = VisualHelper.FindNextParentByType((ScrollViewer)sender); 85 | if (parent != null) 86 | { 87 | var eventArg = new MouseWheelEventArgs(p.MouseDevice, p.Timestamp, p.Delta); 88 | eventArg.RoutedEvent = UIElement.MouseWheelEvent; 89 | eventArg.Source = sender; 90 | parent.RaiseEvent(eventArg); 91 | } 92 | } 93 | }; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /gamevault/Helper/StringCompressor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO.Compression; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.Helper 10 | { 11 | internal class StringCompressor 12 | { 13 | public static string CompressString(string text) 14 | { 15 | byte[] buffer = Encoding.UTF8.GetBytes(text); 16 | var memoryStream = new MemoryStream(); 17 | using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true)) 18 | { 19 | gZipStream.Write(buffer, 0, buffer.Length); 20 | } 21 | 22 | memoryStream.Position = 0; 23 | 24 | var compressedData = new byte[memoryStream.Length]; 25 | memoryStream.Read(compressedData, 0, compressedData.Length); 26 | 27 | var gZipBuffer = new byte[compressedData.Length + 4]; 28 | Buffer.BlockCopy(compressedData, 0, gZipBuffer, 4, compressedData.Length); 29 | Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4); 30 | return Convert.ToBase64String(gZipBuffer); 31 | } 32 | public static string DecompressString(string compressedText) 33 | { 34 | byte[] gZipBuffer = Convert.FromBase64String(compressedText); 35 | using (var memoryStream = new MemoryStream()) 36 | { 37 | int dataLength = BitConverter.ToInt32(gZipBuffer, 0); 38 | memoryStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4); 39 | 40 | var buffer = new byte[dataLength]; 41 | 42 | memoryStream.Position = 0; 43 | using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) 44 | { 45 | gZipStream.Read(buffer, 0, buffer.Length); 46 | } 47 | 48 | return Encoding.UTF8.GetString(buffer); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /gamevault/Helper/TaskQueue.cs: -------------------------------------------------------------------------------- 1 | using gamevault.ViewModels; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace gamevault.Helper 11 | { 12 | public class TaskQueue 13 | { 14 | #region Singleton 15 | private static TaskQueue instance = null; 16 | private static readonly object padlock = new object(); 17 | 18 | public static TaskQueue Instance 19 | { 20 | get 21 | { 22 | lock (padlock) 23 | { 24 | if (instance == null) 25 | { 26 | instance = new TaskQueue(); 27 | } 28 | return instance; 29 | } 30 | } 31 | } 32 | #endregion 33 | private SemaphoreSlim m_Semaphore; 34 | private List m_ProcessedIds; 35 | private int maxProcessCount = 1; 36 | 37 | public TaskQueue() 38 | { 39 | m_Semaphore = new SemaphoreSlim(maxProcessCount, maxProcessCount); 40 | m_ProcessedIds = new List(); 41 | } 42 | public async Task Enqueue(Func taskGenerator, int id) 43 | { 44 | m_ProcessedIds.Add(id); 45 | await m_Semaphore.WaitAsync(); 46 | try 47 | { 48 | //Debug.WriteLine($"->Task stated with id: {id}"); 49 | await taskGenerator(); 50 | } 51 | finally 52 | { 53 | m_Semaphore.Release(); 54 | m_ProcessedIds.Remove(id); 55 | //Debug.WriteLine($"###Task endet with id: {id}"); 56 | } 57 | } 58 | public void ClearQueue() 59 | { 60 | if (m_Semaphore != null) 61 | { 62 | m_Semaphore.Dispose(); 63 | } 64 | m_Semaphore = new SemaphoreSlim(maxProcessCount, maxProcessCount); 65 | m_ProcessedIds.Clear(); 66 | } 67 | public bool IsAlreadyInProcess(int id) 68 | { 69 | return m_ProcessedIds.Contains(id); 70 | } 71 | public async Task WaitForProcessToFinish(int id) 72 | { 73 | while (IsAlreadyInProcess(id)) 74 | { 75 | await Task.Delay(25); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /gamevault/Helper/VisualHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Controls; 7 | using System.Windows.Media; 8 | using System.Windows; 9 | 10 | namespace gamevault.Helper 11 | { 12 | internal class VisualHelper 13 | { 14 | internal static T FindNextParentByType(DependencyObject child) 15 | { 16 | DependencyObject parentDepObj = child; 17 | do 18 | { 19 | parentDepObj = VisualTreeHelper.GetParent(parentDepObj); 20 | if (parentDepObj is T parent) return parent; 21 | } 22 | while (parentDepObj != null); 23 | return default; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /gamevault/Helper/Web/WebExceptionHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Http; 7 | using System.Text; 8 | using System.Text.Json.Nodes; 9 | using System.Threading.Tasks; 10 | 11 | namespace gamevault.Helper 12 | { 13 | internal class WebExceptionHelper 14 | { 15 | private static string GetServerMessage(WebException ex) 16 | { 17 | string errMessage = string.Empty; 18 | try 19 | { 20 | var resp = new StreamReader(ex.Response?.GetResponseStream()).ReadToEnd(); 21 | JsonObject obj = JsonNode.Parse(resp).AsObject(); 22 | errMessage = obj["message"].ToString().Replace("\n", " ").Replace("\r", ""); 23 | } 24 | catch { } 25 | return errMessage; 26 | } 27 | /// 28 | /// Tries to get the response message of the server. Else returns exception message 29 | /// 30 | internal static string TryGetServerMessage(Exception ex) 31 | { 32 | if (ex is WebException webEx) 33 | { 34 | string msg = GetServerMessage(webEx); 35 | return string.IsNullOrEmpty(msg) ? ex.Message : $"Server responded: {msg}"; 36 | } 37 | return ex.Message; 38 | } 39 | internal static string GetServerStatusCode(Exception ex) 40 | { 41 | if (ex is WebException webex) 42 | { 43 | 44 | string errMessage = string.Empty; 45 | try 46 | { 47 | if (webex.Response == null) 48 | return string.Empty; 49 | 50 | var resp = new StreamReader(webex.Response.GetResponseStream()).ReadToEnd(); 51 | JsonObject obj = JsonNode.Parse(resp).AsObject(); 52 | errMessage = obj["statusCode"].ToString().Replace("\n", " ").Replace("\r", ""); 53 | } 54 | catch { } 55 | return errMessage; 56 | } 57 | else if (ex is HttpRequestException httpEx && httpEx.StatusCode.HasValue) 58 | { 59 | return ((int)httpEx.StatusCode.Value).ToString(); 60 | } 61 | return string.Empty; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /gamevault/Lib/7z/7z.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Lib/7z/7z.dll -------------------------------------------------------------------------------- /gamevault/Lib/7z/7z.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Lib/7z/7z.exe -------------------------------------------------------------------------------- /gamevault/Lib/7z/LICENSE: -------------------------------------------------------------------------------- 1 | 7-Zip (v23.01) 2 | 3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 | License for use and distribution 5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | 7-Zip Copyright (C) 1999-2023 Igor Pavlov. 8 | 9 | The licenses for files are: 10 | 11 | 1) 7z.dll: 12 | - The "GNU LGPL" as main license for most of the code 13 | - The "GNU LGPL" with "unRAR license restriction" for some code 14 | - The "BSD 3-clause License" for some code 15 | 2) All other files: the "GNU LGPL". 16 | 17 | Redistributions in binary form must reproduce related license information from this file. 18 | 19 | Note: 20 | You can use 7-Zip on any computer, including a computer in a commercial 21 | organization. You don't need to register or pay for 7-Zip. 22 | 23 | 24 | GNU LGPL information 25 | -------------------- 26 | 27 | This library is free software; you can redistribute it and/or 28 | modify it under the terms of the GNU Lesser General Public 29 | License as published by the Free Software Foundation; either 30 | version 2.1 of the License, or (at your option) any later version. 31 | 32 | This library is distributed in the hope that it will be useful, 33 | but WITHOUT ANY WARRANTY; without even the implied warranty of 34 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 35 | Lesser General Public License for more details. 36 | 37 | You can receive a copy of the GNU Lesser General Public License from 38 | http://www.gnu.org/ 39 | 40 | 41 | 42 | 43 | BSD 3-clause License 44 | -------------------- 45 | 46 | The "BSD 3-clause License" is used for the code in 7z.dll that implements LZFSE data decompression. 47 | That code was derived from the code in the "LZFSE compression library" developed by Apple Inc, 48 | that also uses the "BSD 3-clause License": 49 | 50 | ---- 51 | Copyright (c) 2015-2016, Apple Inc. All rights reserved. 52 | 53 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 54 | 55 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 56 | 57 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer 58 | in the documentation and/or other materials provided with the distribution. 59 | 60 | 3. Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived 61 | from this software without specific prior written permission. 62 | 63 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 64 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 65 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 66 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 68 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 | ---- 70 | 71 | 72 | 73 | 74 | unRAR license restriction 75 | ------------------------- 76 | 77 | The decompression engine for RAR archives was developed using source 78 | code of unRAR program. 79 | All copyrights to original unRAR code are owned by Alexander Roshal. 80 | 81 | The license for original unRAR code has the following restriction: 82 | 83 | The unRAR sources cannot be used to re-create the RAR compression algorithm, 84 | which is proprietary. Distribution of modified unRAR sources in separate form 85 | or as a part of other software is permitted, provided that it is clearly 86 | stated in the documentation and source comments that the code may 87 | not be used to develop a RAR (WinRAR) compatible archiver. 88 | 89 | 90 | -- 91 | Igor Pavlov 92 | -------------------------------------------------------------------------------- /gamevault/Lib/Preferences.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Lib/Preferences.dll -------------------------------------------------------------------------------- /gamevault/Lib/savegame/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Matthew T. Kennerly (mtkennerly) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /gamevault/Lib/savegame/ludusavi.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Lib/savegame/ludusavi.exe -------------------------------------------------------------------------------- /gamevault/Models/ImageCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace gamevault.Models 8 | { 9 | public enum ImageCache 10 | { 11 | GameCover, 12 | GameBackground, 13 | UserAvatar, 14 | UserBackground 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /gamevault/Models/Mapping/MapGameDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | using System.Text.Json.Serialization; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.Models.Mapping 10 | { 11 | public class MapGameDto 12 | { 13 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 14 | [JsonPropertyName("provider_slug")] 15 | public string ProviderSlug { get; set; } 16 | 17 | /// id of the target game from the provider. If not provided, the metadata for the specified provider will be unmapped. 18 | [JsonPropertyName("provider_data_id")] 19 | public string ProviderDataId { get; set; } 20 | 21 | /// opional priority override of the provider for the specified game. If not provided, the default priority of the provider will be used. 22 | [JsonPropertyName("provider_priority")] 23 | public int? ProviderPriority { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /gamevault/Models/Mapping/MetadataProviderDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | using System.Text.Json.Serialization; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.Models.Mapping 10 | { 11 | public class MetadataProviderDto 12 | { 13 | [JsonPropertyName("slug")] 14 | public string? Slug { get; set; } 15 | [JsonPropertyName("name")] 16 | public string? Name { get; set; } 17 | 18 | [JsonPropertyName("priority")] 19 | public int? Priority { get; set; } 20 | [JsonPropertyName("enabled")] 21 | public bool? Enabled { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gamevault/Models/Mapping/UpdateGameDto.cs: -------------------------------------------------------------------------------- 1 | using IO.Swagger.Model; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Text.Json.Serialization; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.Models.Mapping 10 | { 11 | internal class UpdateGameDto 12 | { 13 | /// 14 | /// The updated user metadata. If not provided, the user_metadata will not be updated. 15 | /// 16 | /// The updated user metadata. If not provided, the user_metadata will not be updated. 17 | [JsonPropertyName("user_metadata")] 18 | public UpdateGameUserMetadataDto? UserMetadata { get; set; } 19 | 20 | /// 21 | /// The mapping requests. If not provided, the game will not be remapped. 22 | /// 23 | /// The mapping requests. If not provided, the game will not be remapped. 24 | [JsonPropertyName("mapping_requests")] 25 | public List? MappingRequests { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /gamevault/Models/Mapping/UpdateUserDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | 8 | namespace gamevault.Models.Mapping 9 | { 10 | public class UpdateUserDto 11 | { 12 | /// 13 | /// username of the user 14 | /// 15 | /// username of the user 16 | [JsonPropertyName("username")] 17 | public string Username { get; set; } 18 | 19 | /// 20 | /// email of the user 21 | /// 22 | /// email of the user 23 | [JsonPropertyName("email")] 24 | public string EMail { get; set; } 25 | 26 | /// 27 | /// password of the user 28 | /// 29 | /// password of the user 30 | [JsonPropertyName("password")] 31 | public string Password { get; set; } 32 | 33 | /// 34 | /// first name of the user 35 | /// 36 | /// first name of the user 37 | [JsonPropertyName("first_name")] 38 | public string FirstName { get; set; } 39 | 40 | /// 41 | /// last name of the user 42 | /// 43 | /// last name of the user 44 | [JsonPropertyName("last_name")] 45 | public string LastName { get; set; } 46 | 47 | /// 48 | /// date of birth of the user 49 | /// 50 | /// date of birth of the user 51 | [JsonPropertyName("birth_date")] 52 | public DateTime? BirthDate { get; set; } 53 | 54 | /// 55 | /// id of the avatar image of the user 56 | /// 57 | /// id of the avatar image of the user 58 | [JsonPropertyName("avatar_id")] 59 | public int? AvatarId { get; set; } 60 | 61 | /// 62 | /// id of the background image of the User 63 | /// 64 | /// id of the background image of the User 65 | [JsonPropertyName("background_id")] 66 | public int? BackgroundId { get; set; } 67 | 68 | /// 69 | /// wether or not the user is activated. Not yet working. 70 | /// 71 | /// wether or not the user is activated. Not yet working. 72 | [JsonPropertyName("activated")] 73 | public bool? Activated { get; set; } 74 | 75 | /// 76 | /// The role determines the set of permissions and access rights for a user in the system. 77 | /// 78 | /// The role determines the set of permissions and access rights for a user in the system. 79 | [JsonPropertyName("role")] 80 | public PERMISSION_ROLE? Role { get; set; } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /gamevault/Models/Media.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Runtime.Serialization; 6 | using System.Text.Json.Serialization; 7 | 8 | 9 | namespace gamevault.Models 10 | { 11 | public class Media 12 | { 13 | /// 14 | /// Unique gamevault-identifier of the entity 15 | /// 16 | /// Unique gamevault-identifier of the entity 17 | 18 | [JsonPropertyName("id")] 19 | public int ID { get; set; } 20 | 21 | /// 22 | /// date the entity was created 23 | /// 24 | /// date the entity was created 25 | 26 | [JsonPropertyName("created_at")] 27 | public DateTime? CreatedAt { get; set; } 28 | 29 | /// 30 | /// date the entity was updated 31 | /// 32 | /// date the entity was updated 33 | 34 | [JsonPropertyName("updated_at")] 35 | public DateTime? UpdatedAt { get; set; } 36 | 37 | /// 38 | /// date the entity was soft-deleted (null if not deleted) 39 | /// 40 | /// date the entity was soft-deleted (null if not deleted) 41 | 42 | [JsonPropertyName("deleted_at")] 43 | public DateTime? DeletedAt { get; set; } 44 | 45 | /// 46 | /// incremental version number of the entity 47 | /// 48 | /// incremental version number of the entity 49 | 50 | [JsonPropertyName("entity_version")] 51 | public decimal? EntityVersion { get; set; } 52 | 53 | /// 54 | /// the original source URL of the media 55 | /// 56 | /// the original source URL of the media 57 | 58 | [JsonPropertyName("source_url")] 59 | public string Source { get; set; } 60 | 61 | /// 62 | /// the path of the media on the filesystem 63 | /// 64 | /// the path of the media on the filesystem 65 | 66 | [JsonPropertyName("file_path")] 67 | public string Path { get; set; } 68 | 69 | /// 70 | /// the media type of the media on the filesystem 71 | /// 72 | /// the media type of the media on the filesystem 73 | 74 | [JsonPropertyName("type")] 75 | public string Type { get; set; } 76 | 77 | /// 78 | /// the uploader of the media 79 | /// 80 | /// the uploader of the media 81 | 82 | [JsonPropertyName("uploader")] 83 | public User Uploader { get; set; } 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /gamevault/Models/Metadata/DeveloperMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Runtime.Serialization; 6 | using System.Text.Json.Serialization; 7 | 8 | namespace gamevault.Models 9 | { 10 | public class DeveloperMetadata 11 | { 12 | /// 13 | /// Unique gamevault-identifier of the entity 14 | /// 15 | /// Unique gamevault-identifier of the entity 16 | 17 | [JsonPropertyName("id")] 18 | public int? ID { get; set; } 19 | 20 | /// 21 | /// date the entity was created 22 | /// 23 | /// date the entity was created 24 | 25 | [JsonPropertyName("created_at")] 26 | public DateTime? CreatedAt { get; set; } 27 | 28 | /// 29 | /// date the entity was updated 30 | /// 31 | /// date the entity was updated 32 | 33 | [JsonPropertyName("updated_at")] 34 | public DateTime? UpdatedAt { get; set; } 35 | 36 | /// 37 | /// date the entity was soft-deleted (null if not deleted) 38 | /// 39 | /// date the entity was soft-deleted (null if not deleted) 40 | 41 | [JsonPropertyName("deleted_at")] 42 | public DateTime? DeletedAt { get; set; } 43 | 44 | /// 45 | /// incremental version number of the entity 46 | /// 47 | /// incremental version number of the entity 48 | 49 | [JsonPropertyName("entity_version")] 50 | public decimal? EntityVersion { get; set; } 51 | 52 | /// 53 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 54 | /// 55 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 56 | 57 | [JsonPropertyName("provider_slug")] 58 | public string ProviderSlug { get; set; } 59 | 60 | /// 61 | /// id of the developer from the provider 62 | /// 63 | /// id of the developer from the provider 64 | 65 | [JsonPropertyName("provider_data_id")] 66 | public string ProviderDataId { get; set; } 67 | 68 | /// 69 | /// name of the developer 70 | /// 71 | /// name of the developer 72 | 73 | [JsonPropertyName("name")] 74 | public string Name { get; set; } 75 | 76 | /// 77 | /// games developed by the developer 78 | /// 79 | /// games developed by the developer 80 | 81 | [JsonPropertyName("games")] 82 | public List Games { get; set; } 83 | 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /gamevault/Models/Metadata/GenreMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Runtime.Serialization; 6 | using System.Text.Json.Serialization; 7 | 8 | 9 | namespace gamevault.Models 10 | { 11 | public interface IGenreMetadata 12 | { 13 | int ID { get; set; } 14 | string Name { get; set; } 15 | string ProviderDataId { get; set; } 16 | string ProviderSlug { get; set; } 17 | } 18 | 19 | public class GenreMetadata : IGenreMetadata 20 | { 21 | /// 22 | /// Unique gamevault-identifier of the entity 23 | /// 24 | /// Unique gamevault-identifier of the entity 25 | 26 | [JsonPropertyName("id")] 27 | public int ID { get; set; } 28 | 29 | /// 30 | /// date the entity was created 31 | /// 32 | /// date the entity was created 33 | 34 | [JsonPropertyName("created_at")] 35 | public DateTime? CreatedAt { get; set; } 36 | 37 | /// 38 | /// date the entity was updated 39 | /// 40 | /// date the entity was updated 41 | 42 | [JsonPropertyName("updated_at")] 43 | public DateTime? UpdatedAt { get; set; } 44 | 45 | /// 46 | /// date the entity was soft-deleted (null if not deleted) 47 | /// 48 | /// date the entity was soft-deleted (null if not deleted) 49 | 50 | [JsonPropertyName("deleted_at")] 51 | public DateTime? DeletedAt { get; set; } 52 | 53 | /// 54 | /// incremental version number of the entity 55 | /// 56 | /// incremental version number of the entity 57 | 58 | [JsonPropertyName("entity_version")] 59 | public decimal? EntityVersion { get; set; } 60 | 61 | /// 62 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 63 | /// 64 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 65 | 66 | [JsonPropertyName("provider_slug")] 67 | public string ProviderSlug { get; set; } 68 | 69 | /// 70 | /// id of the developer from the provider 71 | /// 72 | /// id of the developer from the provider 73 | 74 | [JsonPropertyName("provider_data_id")] 75 | public string ProviderDataId { get; set; } 76 | 77 | /// 78 | /// name of the genre 79 | /// 80 | /// name of the genre 81 | 82 | [JsonPropertyName("name")] 83 | public string Name { get; set; } 84 | 85 | /// 86 | /// games of the genre 87 | /// 88 | /// games of the genre 89 | 90 | [JsonPropertyName("games")] 91 | public List Games { get; set; } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /gamevault/Models/Metadata/PublisherMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Runtime.Serialization; 6 | using System.Text.Json.Serialization; 7 | 8 | namespace gamevault.Models 9 | { 10 | public class PublisherMetadata 11 | { 12 | /// 13 | /// Unique gamevault-identifier of the entity 14 | /// 15 | /// Unique gamevault-identifier of the entity 16 | 17 | [JsonPropertyName("id")] 18 | public int ID { get; set; } 19 | 20 | /// 21 | /// date the entity was created 22 | /// 23 | /// date the entity was created 24 | 25 | [JsonPropertyName("created_at")] 26 | public DateTime? CreatedAt { get; set; } 27 | 28 | /// 29 | /// date the entity was updated 30 | /// 31 | /// date the entity was updated 32 | 33 | [JsonPropertyName("updated_at")] 34 | public DateTime? UpdatedAt { get; set; } 35 | 36 | /// 37 | /// date the entity was soft-deleted (null if not deleted) 38 | /// 39 | /// date the entity was soft-deleted (null if not deleted) 40 | 41 | [JsonPropertyName("deleted_at")] 42 | public DateTime? DeletedAt { get; set; } 43 | 44 | /// 45 | /// incremental version number of the entity 46 | /// 47 | /// incremental version number of the entity 48 | 49 | [JsonPropertyName("entity_version")] 50 | public decimal? EntityVersion { get; set; } 51 | 52 | /// 53 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 54 | /// 55 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 56 | 57 | [JsonPropertyName("provider_slug")] 58 | public string ProviderSlug { get; set; } 59 | 60 | /// 61 | /// id of the developer from the provider 62 | /// 63 | /// id of the developer from the provider 64 | 65 | [JsonPropertyName("provider_data_id")] 66 | public string ProviderDataId { get; set; } 67 | 68 | /// 69 | /// name of the publisher 70 | /// 71 | /// name of the publisher 72 | 73 | [JsonPropertyName("name")] 74 | public string Name { get; set; } 75 | 76 | /// 77 | /// games published by the publisher 78 | /// 79 | /// games published by the publisher 80 | 81 | [JsonPropertyName("games")] 82 | public List Games { get; set; } 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /gamevault/Models/Metadata/TagMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Runtime.Serialization; 6 | using System.Text.Json.Serialization; 7 | 8 | namespace gamevault.Models 9 | { 10 | public interface ITagMetadata 11 | { 12 | int ID { get; set; } 13 | string Name { get; set; } 14 | string ProviderDataId { get; set; } 15 | string ProviderSlug { get; set; } 16 | } 17 | 18 | public class TagMetadata : ITagMetadata 19 | { 20 | /// 21 | /// Unique gamevault-identifier of the entity 22 | /// 23 | /// Unique gamevault-identifier of the entity 24 | 25 | [JsonPropertyName("id")] 26 | public int ID { get; set; } 27 | 28 | /// 29 | /// date the entity was created 30 | /// 31 | /// date the entity was created 32 | 33 | [JsonPropertyName("created_at")] 34 | public DateTime? CreatedAt { get; set; } 35 | 36 | /// 37 | /// date the entity was updated 38 | /// 39 | /// date the entity was updated 40 | 41 | [JsonPropertyName("updated_at")] 42 | public DateTime? UpdatedAt { get; set; } 43 | 44 | /// 45 | /// date the entity was soft-deleted (null if not deleted) 46 | /// 47 | /// date the entity was soft-deleted (null if not deleted) 48 | 49 | [JsonPropertyName("deleted_at")] 50 | public DateTime? DeletedAt { get; set; } 51 | 52 | /// 53 | /// incremental version number of the entity 54 | /// 55 | /// incremental version number of the entity 56 | 57 | [JsonPropertyName("entity_version")] 58 | public decimal? EntityVersion { get; set; } 59 | 60 | /// 61 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 62 | /// 63 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 64 | 65 | [JsonPropertyName("provider_slug")] 66 | public string ProviderSlug { get; set; } 67 | 68 | /// 69 | /// id of the developer from the provider 70 | /// 71 | /// id of the developer from the provider 72 | 73 | [JsonPropertyName("provider_data_id")] 74 | public string ProviderDataId { get; set; } 75 | 76 | /// 77 | /// name of the tag 78 | /// 79 | /// name of the tag 80 | 81 | [JsonPropertyName("name")] 82 | public string Name { get; set; } 83 | 84 | /// 85 | /// games tagged with the tag 86 | /// 87 | /// games tagged with the tag 88 | 89 | [JsonPropertyName("games")] 90 | public List Games { get; set; } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /gamevault/Models/MinimalGame.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.Serialization; 5 | using System.Text; 6 | using System.Text.Json.Serialization; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.Models 10 | { 11 | public class MinimalGame 12 | { 13 | /// 14 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 15 | /// 16 | /// slug (url-friendly name) of the provider. This is the primary identifier. Must be formatted like a valid slug. 17 | 18 | [JsonPropertyName("provider_slug")] 19 | public string ProviderSlug { get; set; } 20 | 21 | /// 22 | /// id of the game from the provider 23 | /// 24 | /// id of the game from the provider 25 | 26 | [JsonPropertyName("provider_data_id")] 27 | public string ProviderDataId { get; set; } 28 | 29 | /// 30 | /// gamevault's calculated probability of the metadata being the correct one. 31 | /// 32 | /// gamevault's calculated probability of the metadata being the correct one. 33 | 34 | [JsonPropertyName("provider_probability")] 35 | public decimal? ProviderProbability { get; set; } 36 | 37 | /// 38 | /// title of the game 39 | /// 40 | /// title of the game 41 | 42 | [JsonPropertyName("title")] 43 | public string Title { get; set; } 44 | 45 | /// 46 | /// release date of the game 47 | /// 48 | /// release date of the game 49 | 50 | [JsonPropertyName("release_date")] 51 | public DateTime? ReleaseDate { get; set; } 52 | 53 | /// 54 | /// box image url of the game 55 | /// 56 | /// box image url of the game 57 | 58 | [JsonPropertyName("cover_url")] 59 | public string CoverUrl { get; set; } 60 | 61 | [JsonPropertyName("description")] 62 | public string Description { get; set; } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /gamevault/Models/PaginatedGame.cs: -------------------------------------------------------------------------------- 1 | using ImageMagick; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.Json.Serialization; 8 | using System.Threading.Tasks; 9 | 10 | namespace gamevault.Models 11 | { 12 | public class PaginatedData 13 | { 14 | [JsonPropertyName("data")] 15 | public T[] Data { get; set; } 16 | [JsonPropertyName("meta")] 17 | public MetaData Meta { get; set; } 18 | [JsonPropertyName("links")] 19 | public Links Links { get; set; } 20 | } 21 | public class MetaData 22 | { 23 | //[JsonPropertyName("itemsPerPage")] 24 | //public long ItemsPerPage { get; set; } 25 | [JsonPropertyName("totalItems")] 26 | public int TotalItems { get; set; } 27 | //[JsonPropertyName("currentPage")] 28 | //public int CurrentPage { get; set; } 29 | //[JsonPropertyName("totalPages")] 30 | //public int TotalPages { get; set; } 31 | //[JsonPropertyName("sortBy")] 32 | //public string SortBy { get; set; } 33 | //[JsonPropertyName("search")] 34 | //public string Search { get; set; } 35 | //[JsonPropertyName("filter")] 36 | //public string[] Filter { get; set; } 37 | } 38 | public class Links 39 | { 40 | [JsonPropertyName("first")] 41 | public string First { get; set; } 42 | [JsonPropertyName("previous")] 43 | public string Previous { get; set; } 44 | [JsonPropertyName("current")] 45 | public string Current { get; set; } 46 | [JsonPropertyName("next")] 47 | public string Next { get; set; } 48 | [JsonPropertyName("last")] 49 | public string Last { get; set; } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /gamevault/Models/PhalcodeProduct.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | 8 | namespace gamevault.Models 9 | { 10 | public class PhalcodeProduct 11 | { 12 | [JsonPropertyName("stripe_id")] 13 | public string? StripeID { get; set; } 14 | [JsonPropertyName("stripe_subscription_item_id")] 15 | public string? StripeSubscriptionItemID { get; set; } 16 | [JsonPropertyName("price_stripe_id")] 17 | public string? PriceStripeID { get; set; } 18 | [JsonPropertyName("product_stripe_id")] 19 | public string? ProductStripeID { get; set; } 20 | [JsonPropertyName("customer_stripe_id")] 21 | public string? CustomerStripeID { get; set; } 22 | [JsonPropertyName("status")] 23 | public string? Status { get; set; } 24 | [JsonPropertyName("currency")] 25 | public string? Currency { get; set; } 26 | [JsonPropertyName("current_period_start")] 27 | public DateTime? CurrentPeriodStart { get; set; } 28 | [JsonPropertyName("current_period_end")] 29 | public DateTime? CurrentPeriodEnd { get; set; } 30 | [JsonPropertyName("started_at")] 31 | public DateTime? StartedAt { get; set; } 32 | [JsonPropertyName("ended_at")] 33 | public DateTime? EndedAt { get; set; } 34 | [JsonPropertyName("cancel_at")] 35 | public DateTime? CancelAt { get; set; } 36 | [JsonPropertyName("trial_ends_at")] 37 | public DateTime? TrialEndsAt { get; set; } 38 | [JsonPropertyName("cancel_at_period_end")] 39 | public bool? CancelAtPeriodEnd { get; set; } 40 | public string? UserName { get; set; } 41 | public bool IsActive() 42 | { 43 | return (CurrentPeriodEnd != null && CurrentPeriodEnd > DateTime.UtcNow); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /gamevault/Models/Pill.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | 8 | namespace gamevault.Models 9 | { 10 | public class Pill : IGenreMetadata, ITagMetadata 11 | { 12 | private int id; 13 | private string name; 14 | private string providerDataId; 15 | private string providerSlug; 16 | [JsonPropertyName("id")] 17 | public int ID { get => id; set => id = value; } 18 | [JsonPropertyName("name")] 19 | public string Name { get => name; set => name = value; } 20 | [JsonPropertyName("provider_data_id")] 21 | public string ProviderDataId { get => providerDataId; set => providerDataId = value; } 22 | [JsonPropertyName("provider_slug")] 23 | public string ProviderSlug { get => providerSlug; set => providerSlug = value; } 24 | 25 | public string OriginName { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /gamevault/Models/Progress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Runtime.Serialization; 6 | using System.Text; 7 | using System.Text.Json; 8 | using System.Text.Json.Serialization; 9 | using System.Threading.Tasks; 10 | 11 | namespace gamevault.Models 12 | { 13 | public enum State 14 | { 15 | [Description("Unplayed")] 16 | UNPLAYED, 17 | [Description("Infinite")] 18 | INFINITE, 19 | [Description("Playing")] 20 | PLAYING, 21 | [Description("Completed")] 22 | COMPLETED, 23 | [Description("Temporarily Aborted")] 24 | ABORTED_TEMPORARY, 25 | [Description("Permanently Aborted")] 26 | ABORTED_PERMANENT 27 | } 28 | public class Progress 29 | { 30 | [JsonPropertyName("id")] 31 | public int? ID { get; set; } 32 | [JsonPropertyName("minutes_played")] 33 | public int? MinutesPlayed { get; set; } 34 | [JsonPropertyName("state")] 35 | public string? State { get; set; } 36 | [JsonPropertyName("last_played_at")] 37 | public DateTime? LastPlayedAt { get; set; } 38 | [JsonPropertyName("game")] 39 | public Game? Game { get; set; } 40 | [JsonPropertyName("user")] 41 | public User? User { get; set; } 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /gamevault/Models/ServerInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | 8 | namespace gamevault.Models 9 | { 10 | public struct ServerInfo 11 | { 12 | [JsonPropertyName("status")] 13 | public string Status { get; set; } 14 | [JsonPropertyName("version")] 15 | public string Version { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gamevault/Models/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | 8 | namespace gamevault.Models 9 | { 10 | public enum PERMISSION_ROLE 11 | { 12 | GUEST, 13 | USER, 14 | EDITOR, 15 | ADMIN 16 | } 17 | public class User 18 | { 19 | [JsonPropertyName("id")] 20 | public int ID { get; set; } 21 | [JsonPropertyName("username")] 22 | public string Username { get; set; } 23 | [JsonPropertyName("avatar")] 24 | public Media Avatar { get; set; } 25 | [JsonPropertyName("background")] 26 | public Media Background { get; set; } 27 | [JsonPropertyName("email")] 28 | public string EMail { get; set; } 29 | [JsonPropertyName("first_name")] 30 | public string FirstName { get; set; } 31 | [JsonPropertyName("last_name")] 32 | public string LastName { get; set; } 33 | [JsonPropertyName("password")] 34 | public string Password { get; set; } 35 | public string RepeatPassword { get; set; } 36 | [JsonPropertyName("progresses")] 37 | public Progress[]? Progresses { get; set; } 38 | [JsonPropertyName("role")] 39 | public PERMISSION_ROLE? Role { get; set; } 40 | [JsonPropertyName("activated")] 41 | public bool? Activated { get; set; } 42 | [JsonPropertyName("deleted_at")] 43 | public string DeletedAt { get; set; } 44 | [JsonPropertyName("created_at")] 45 | public DateTime? CreatedAt { get; set; } 46 | [JsonPropertyName("birth_date")] 47 | public DateTime? BirthDate { get; set; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /gamevault/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "gamevault": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /gamevault/Resources/Assets/Colors.xaml: -------------------------------------------------------------------------------- 1 |  3 | #079185 4 | -------------------------------------------------------------------------------- /gamevault/Resources/Assets/MarkdownStyles.xaml: -------------------------------------------------------------------------------- 1 |  4 | 9 | 14 | 19 | 25 | -------------------------------------------------------------------------------- /gamevault/Resources/Assets/Themes/ThemeChristmasDark.xaml: -------------------------------------------------------------------------------- 1 | 6 | 1 7 | 8 | 9 | 1 10 | 11 | ThemeChristmasDark 12 | 13 | Phalcode 14 | 15 | Celebrate a cozy and festive Christmas with us. We ho-ho-hope you love it! 16 | 17 | Christmas (Dark) 18 | 19 | 20 | #FFFFFFFF 21 | 22 | #FFFFFFFF 23 | 25 | #FF0C1600 26 | 27 | #FF550000 28 | 29 | #FF005508 30 | 31 | #99005508 32 | 33 | #66005508 34 | 35 | #33005508 36 | 37 | #FFB39800 38 | 39 | #00000000 40 | 41 | -------------------------------------------------------------------------------- /gamevault/Resources/Assets/Themes/ThemeClassicDark.xaml: -------------------------------------------------------------------------------- 1 |  2 | 1 3 | 4 | 5 | 1 6 | 7 | ThemeClassicDark 8 | 9 | Phalcode 10 | 11 | This theme preserves the traditional application colors for users accustomed to the old dark design of GameVault. 12 | 13 | Classic (Dark) 14 | 15 | 16 | #FFFFFFFF 17 | 18 | #FFFFFFFF 19 | 20 | #FF252525 21 | 22 | #FF444444 23 | 24 | #FF574EB9 25 | 26 | #99574EB9 27 | 28 | #66574EB9 29 | 30 | #33574EB9 31 | 32 | #FF3B3767 33 | 34 | Black 35 | 36 | -------------------------------------------------------------------------------- /gamevault/Resources/Assets/Themes/ThemeDefaultDark.xaml: -------------------------------------------------------------------------------- 1 |  2 | 1 3 | 4 | 5 | 1 6 | 7 | ThemeGameVaultDark 8 | 9 | Phalcode 10 | 11 | The default GameVault theme, reflecting the 2024 GameVault rebrand with dark tones. 12 | 13 | Default (Dark) 14 | 15 | 16 | #FFF6F5FA 17 | 18 | #FFF6F5FA 19 | 20 | #FF11101E 21 | 22 | #FF171528 23 | 24 | #FF4F46AF 25 | 26 | #994F46AF 27 | 28 | #664F46AF 29 | 30 | #334F46AF 31 | 32 | #FF6660A9 33 | 34 | Black 35 | 36 | -------------------------------------------------------------------------------- /gamevault/Resources/Assets/Themes/ThemeDefaultLight.xaml: -------------------------------------------------------------------------------- 1 |  2 | 1 3 | 4 | 5 | 1 6 | 7 | ThemeDefaultLight 8 | 9 | Phalcode 10 | 11 | An alternative light version of the default GameVault theme, also based on the 2024 GameVault rebrand. 12 | 13 | Default (Light) 14 | 15 | 16 | #FF06050A 17 | 18 | #FFF6F5FA 19 | 20 | #FFE2E1EF 21 | 22 | #FFD9D7EA 23 | 24 | #FF5950B9 25 | 26 | #995950B9 27 | 28 | #665950B9 29 | 30 | #335950B9 31 | 32 | #FF5C569F 33 | 34 | White 35 | 36 | -------------------------------------------------------------------------------- /gamevault/Resources/Assets/Themes/ThemeHalloweenDark.xaml: -------------------------------------------------------------------------------- 1 | 6 | 1 7 | 8 | 9 | 1 10 | 11 | ThemeHalloweenDark 12 | 13 | Phalcode 14 | 15 | A Halloween-themed ambiance to set the mood for horror games in autumn. 16 | 17 | Halloween (Dark) 18 | 19 | 20 | #FFFBF0E3 21 | 22 | #FFFBF0E3 23 | 25 | #FF130912 26 | 27 | #FF3E1C33 28 | 29 | #FFC46C08 30 | 31 | #99C46C08 32 | 33 | #66C46C08 34 | 35 | #33C46C08 36 | 37 | #FFB14623 38 | 39 | #FF000000 40 | 41 | -------------------------------------------------------------------------------- /gamevault/Resources/Assets/Themes/ThemePhalcodeDark.xaml: -------------------------------------------------------------------------------- 1 |  2 | 1 3 | 4 | 5 | 1 6 | 7 | ThemePhalcodeDark 8 | 9 | Phalcode 10 | 11 | A dark theme aligned with our Phalcode brand. 12 | 13 | Phalcode (Dark) 14 | 15 | 16 | #FFEEF1EF 17 | 18 | #FFFFFFFF 19 | 20 | #FF1C1C1C 21 | 22 | #FF212121 23 | 24 | #FF12AE84 25 | 26 | #9912AE84 27 | 28 | #6612AE84 29 | 30 | #3312AE84 31 | 32 | #FF2A5F47 33 | 34 | Black 35 | 36 | -------------------------------------------------------------------------------- /gamevault/Resources/Assets/Themes/ThemePhalcodeLight.xaml: -------------------------------------------------------------------------------- 1 |  2 | 1 3 | 4 | 5 | 1 6 | 7 | ThemePhalcodeLight 8 | 9 | Phalcode 10 | 11 | A light theme aligned with our Phalcode brand. 12 | 13 | Phalcode (Light) 14 | 15 | 16 | #FF121212 17 | 18 | #FFFFFFFF 19 | 20 | #FFFFFFFF 21 | 22 | #FFDDDDDD 23 | 24 | #FF12AE84 25 | 26 | #9912AE84 27 | 28 | #6612AE84 29 | 30 | #3312AE84 31 | 32 | #FF2A5F47 33 | 34 | White 35 | 36 | -------------------------------------------------------------------------------- /gamevault/Resources/Images/ContextMenuIcon_Community.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/ContextMenuIcon_Community.png -------------------------------------------------------------------------------- /gamevault/Resources/Images/ContextMenuIcon_Downloads.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/ContextMenuIcon_Downloads.png -------------------------------------------------------------------------------- /gamevault/Resources/Images/ContextMenuIcon_Exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/ContextMenuIcon_Exit.png -------------------------------------------------------------------------------- /gamevault/Resources/Images/ContextMenuIcon_Library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/ContextMenuIcon_Library.png -------------------------------------------------------------------------------- /gamevault/Resources/Images/ContextMenuIcon_Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/ContextMenuIcon_Settings.png -------------------------------------------------------------------------------- /gamevault/Resources/Images/com_NoUserAvatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/com_NoUserAvatar.png -------------------------------------------------------------------------------- /gamevault/Resources/Images/gameView_NoBackground.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/gameView_NoBackground.jpg -------------------------------------------------------------------------------- /gamevault/Resources/Images/glyph_premium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/glyph_premium.png -------------------------------------------------------------------------------- /gamevault/Resources/Images/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/icon.ico -------------------------------------------------------------------------------- /gamevault/Resources/Images/install_NoGameFound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/install_NoGameFound.png -------------------------------------------------------------------------------- /gamevault/Resources/Images/library_NoGameCover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/library_NoGameCover.png -------------------------------------------------------------------------------- /gamevault/Resources/Images/library_NoGameFound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Phalcode/gamevault-app/b3061169bf2e18150397ccef40989dff93309ba9/gamevault/Resources/Images/library_NoGameFound.png -------------------------------------------------------------------------------- /gamevault/UserControls/DownloadsUserControl.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 31 | 32 | 33 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /gamevault/UserControls/GeneralControls/CacheImage.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /gamevault/UserControls/GeneralControls/DateRangeSelector.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /gamevault/UserControls/GeneralControls/DateRangeSelector.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace gamevault.UserControls 18 | { 19 | /// 20 | /// Interaction logic for DateRangeSelector.xaml 21 | /// 22 | public partial class DateRangeSelector : UserControl 23 | { 24 | public string YearToPlaceholder { get; set; } 25 | public string YearFromPlaceholder { get; set; } = "1980"; 26 | public event EventHandler EntriesUpdated; 27 | public DateRangeSelector() 28 | { 29 | InitializeComponent(); 30 | YearToPlaceholder = DateTime.Now.Year.ToString(); 31 | this.DataContext = this; 32 | } 33 | public bool IsValid() 34 | { 35 | return uiFilterYearFrom.Text != string.Empty && uiFilterYearTo.Text != string.Empty; 36 | } 37 | public string GetYearFrom() 38 | { 39 | return uiFilterYearFrom.Text; 40 | } 41 | public string GetYearTo() 42 | { 43 | return uiFilterYearTo.Text; 44 | } 45 | public void ClearSelection() 46 | { 47 | uiFilterYearFrom.Text = string.Empty; uiFilterYearTo.Text = string.Empty; 48 | } 49 | private void StackPanel_LostFocus(object sender, RoutedEventArgs e) 50 | { 51 | if (EntriesUpdated != null && IsValid()) 52 | EntriesUpdated(this, e); 53 | } 54 | private void YearSelector_Changed(object sender, TextCompositionEventArgs e) 55 | { 56 | Regex regex = new Regex("[^0-9]+"); 57 | e.Handled = (((TextBox)e.Source).Text == "" && e.Text == "0") || regex.IsMatch(e.Text); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /gamevault/UserControls/GeneralControls/IconButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Text.Json; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Controls.Primitives; 10 | using System.Windows.Media; 11 | 12 | namespace gamevault.UserControls 13 | { 14 | public enum ButtonKind 15 | { 16 | Primary, 17 | Skeleton, 18 | Danger 19 | } 20 | public class IconButton : ButtonBase 21 | { 22 | public static readonly DependencyProperty CornerRadiusProperty = 23 | DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(IconButton)); 24 | public static readonly DependencyProperty IconProperty = 25 | DependencyProperty.Register("Icon", typeof(Geometry), typeof(IconButton)); 26 | public static readonly DependencyProperty TextProperty = 27 | DependencyProperty.Register("Text", typeof(string), typeof(IconButton)); 28 | public static readonly DependencyProperty KindProperty = 29 | DependencyProperty.Register("Kind", typeof(ButtonKind), typeof(IconButton), new PropertyMetadata(ButtonKind.Primary)); 30 | public static readonly DependencyProperty OverrideIconTransformProperty = 31 | DependencyProperty.Register("OverrideIconTransform", typeof(bool), typeof(IconButton), new FrameworkPropertyMetadata(true)); 32 | public static readonly DependencyProperty IconScaleProperty = 33 | DependencyProperty.Register("IconScale", typeof(double), typeof(IconButton), new FrameworkPropertyMetadata(1.0)); 34 | public static readonly DependencyProperty IconMarginProperty = 35 | DependencyProperty.Register("IconMargin", typeof(Thickness), typeof(IconButton), new FrameworkPropertyMetadata(new Thickness(0))); 36 | 37 | 38 | public CornerRadius CornerRadius 39 | { 40 | get { return (CornerRadius)GetValue(CornerRadiusProperty); } 41 | set { SetValue(CornerRadiusProperty, value); } 42 | } 43 | public Geometry Icon 44 | { 45 | get { return (Geometry)GetValue(IconProperty); } 46 | set { SetValue(IconProperty, value); } 47 | } 48 | public string Text 49 | { 50 | get { return (string)GetValue(TextProperty); } 51 | set { SetValue(TextProperty, value); } 52 | } 53 | public ButtonKind Kind 54 | { 55 | get { return (ButtonKind)GetValue(KindProperty); } 56 | set { SetValue(KindProperty, value); } 57 | } 58 | public bool OverrideIconTransform 59 | { 60 | get { return (bool)GetValue(OverrideIconTransformProperty); } 61 | set { SetValue(OverrideIconTransformProperty, value); } 62 | } 63 | public double IconScale 64 | { 65 | get { return (double)GetValue(IconScaleProperty); } 66 | set { SetValue(IconScaleProperty, value); } 67 | } 68 | public Thickness IconMargin 69 | { 70 | get { return (Thickness)GetValue(IconMarginProperty); } 71 | set { SetValue(IconMarginProperty, value); } 72 | } 73 | public IconButton() 74 | { 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /gamevault/UserControls/GeneralControls/NewsPopup.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /gamevault/UserControls/GeneralControls/NewsPopup.xaml.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Helper; 2 | using gamevault.Models; 3 | using gamevault.ViewModels; 4 | using Markdig; 5 | using Markdig.Wpf; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | using System.Windows; 14 | using System.Windows.Controls; 15 | using System.Windows.Data; 16 | using System.Windows.Documents; 17 | using System.Windows.Input; 18 | using System.Windows.Markup; 19 | using System.Windows.Media; 20 | using System.Windows.Media.Imaging; 21 | using System.Windows.Navigation; 22 | using System.Windows.Shapes; 23 | 24 | namespace gamevault.UserControls 25 | { 26 | /// 27 | /// Interaction logic for NewsPopup.xaml 28 | /// 29 | public partial class NewsPopup : UserControl 30 | { 31 | public NewsPopup() 32 | { 33 | InitializeComponent(); 34 | } 35 | private async void UserControl_Loaded(object sender, RoutedEventArgs e) 36 | { 37 | this.Focus(); 38 | try 39 | { 40 | string gameVaultNews = await WebHelper.DownloadFileContentAsync("https://gamevau.lt/news.md"); 41 | uiGameVaultNews.Markdown = gameVaultNews; 42 | string serverNews = await WebHelper.GetRequestAsync($"{SettingsViewModel.Instance.ServerUrl}/api/config/news"); 43 | uiServerNews.Markdown = serverNews; 44 | } 45 | catch { } 46 | } 47 | #region Markdown 48 | private void OpenHyperlink(object sender, System.Windows.Input.ExecutedRoutedEventArgs e) 49 | { 50 | try 51 | { 52 | if (Uri.IsWellFormedUriString(e.Parameter.ToString(), UriKind.Absolute)) 53 | { 54 | Process.Start(new ProcessStartInfo(e.Parameter.ToString()) { UseShellExecute = true }); 55 | } 56 | } 57 | catch { } 58 | } 59 | #endregion 60 | 61 | private void OnClose(object sender, object e) 62 | { 63 | MainWindowViewModel.Instance.ClosePopup(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /gamevault/UserControls/GeneralControls/PillSelector.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /gamevault/UserControls/GeneralControls/TransitioningContentControlEx.cs: -------------------------------------------------------------------------------- 1 | using MahApps.Metro.Controls; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Controls; 8 | using System.Windows; 9 | 10 | namespace gamevault.UserControls 11 | { 12 | internal class TransitioningContentControlEx : TransitioningContentControl 13 | { 14 | protected override void OnContentChanged(object oldContent, object newContent) 15 | { 16 | if ((((FrameworkElement)oldContent)?.Tag?.ToString() == "NoPopupTransition") || (((FrameworkElement)newContent)?.Tag?.ToString() == "NoPopupTransition")) 17 | return; 18 | 19 | base.OnContentChanged(oldContent, newContent); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /gamevault/UserControls/SettingsComponents/LoginUserControl.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /gamevault/UserControls/SettingsComponents/LoginUserControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Helper; 2 | using gamevault.ViewModels; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | using System.Windows.Controls; 10 | using System.Windows.Data; 11 | using System.Windows.Documents; 12 | using System.Windows.Input; 13 | using System.Windows.Media; 14 | using System.Windows.Media.Imaging; 15 | using System.Windows.Navigation; 16 | using System.Windows.Shapes; 17 | 18 | namespace gamevault.UserControls.SettingsComponents 19 | { 20 | /// 21 | /// Interaction logic for LoginUserControl.xaml 22 | /// 23 | public partial class LoginUserControl : UserControl 24 | { 25 | public LoginUserControl() 26 | { 27 | InitializeComponent(); 28 | } 29 | private async void Login_Clicked(object sender, System.Windows.RoutedEventArgs e) 30 | { 31 | ((FrameworkElement)sender).IsEnabled = false; 32 | await Login(); 33 | ((FrameworkElement)sender).IsEnabled = true; 34 | } 35 | 36 | private async void Login_KeyDown(object sender, KeyEventArgs e) 37 | { 38 | if (e.Key == Key.Enter) 39 | { 40 | await Login(); 41 | } 42 | } 43 | private async Task Login() 44 | { 45 | uiBtnLogin.IsEnabled = false; 46 | if (SettingsViewModel.Instance.UserName != string.Empty && uiPwBox.Password != string.Empty) 47 | { 48 | if (LoginManager.Instance.IsLoggedIn() && LoginManager.Instance.GetCurrentUser().Username.ToLower() == SettingsViewModel.Instance.UserName.ToLower()) 49 | { 50 | MainWindowViewModel.Instance.AppBarText = $"You are already logged in as '{SettingsViewModel.Instance.UserName}'"; 51 | } 52 | else 53 | { 54 | LoginState state = await LoginManager.Instance.ManualLogin(SettingsViewModel.Instance.UserName, uiPwBox.Password); 55 | if (LoginState.Success == state) 56 | { 57 | await MainWindowViewModel.Instance.Library.LoadLibrary();//Load library, because otherwise it would be empty for new users at the first login 58 | MainWindowViewModel.Instance.AppBarText = $"Successfully logged in as '{SettingsViewModel.Instance.UserName}'"; 59 | } 60 | else if (LoginState.Unauthorized == state) 61 | { 62 | MainWindowViewModel.Instance.AppBarText = "Login failed. Couldn't establish a secure connection to the server, or your username/password was incorrect."; 63 | } 64 | else if (LoginState.Forbidden == state) 65 | { 66 | MainWindowViewModel.Instance.AppBarText = "Login failed. User is not activated. Contact an Administrator to activate the User."; 67 | } 68 | else if (LoginState.Error == state) 69 | { 70 | MainWindowViewModel.Instance.AppBarText = LoginManager.Instance.GetLoginMessage(); 71 | } 72 | MainWindowViewModel.Instance.UserAvatar = LoginManager.Instance.GetCurrentUser(); 73 | } 74 | } 75 | else 76 | { 77 | MainWindowViewModel.Instance.AppBarText = "Username or password are not set"; 78 | } 79 | uiBtnLogin.IsEnabled = true; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /gamevault/UserControls/SettingsComponents/RegisterUserControl.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /gamevault/UserControls/SettingsComponents/RegisterUserControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Helper; 2 | using gamevault.Models; 3 | using gamevault.ViewModels; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Text; 9 | using System.Text.Json; 10 | using System.Threading.Tasks; 11 | using System.Windows; 12 | using System.Windows.Controls; 13 | using System.Windows.Data; 14 | using System.Windows.Documents; 15 | using System.Windows.Input; 16 | using System.Windows.Media; 17 | using System.Windows.Media.Imaging; 18 | using System.Windows.Navigation; 19 | using System.Windows.Shapes; 20 | 21 | namespace gamevault.UserControls.SettingsComponents 22 | { 23 | /// 24 | /// Interaction logic for RegisterUserControl.xaml 25 | /// 26 | public partial class RegisterUserControl : UserControl 27 | { 28 | public RegisterUserControl() 29 | { 30 | InitializeComponent(); 31 | } 32 | private async void Registration_Clicked(object sender, System.Windows.RoutedEventArgs e) 33 | { 34 | await Register(); 35 | } 36 | private async void Register_KeyDown(object sender, KeyEventArgs e) 37 | { 38 | if (e.Key == Key.Enter) 39 | { 40 | await Register(); 41 | } 42 | } 43 | private bool HasEmptyFields() 44 | { 45 | SettingsViewModel.Instance.RegistrationUser.Password = uiPwReg.Password.ToString(); 46 | SettingsViewModel.Instance.RegistrationUser.RepeatPassword = uiPwRegRepeat.Password.ToString(); 47 | 48 | if (string.IsNullOrEmpty(SettingsViewModel.Instance.RegistrationUser.Username) || string.IsNullOrEmpty(SettingsViewModel.Instance.RegistrationUser.Password) || string.IsNullOrEmpty(SettingsViewModel.Instance.RegistrationUser.RepeatPassword)) 49 | { 50 | return true; 51 | } 52 | return false; 53 | } 54 | private async Task Register() 55 | { 56 | uiBtnRegister.IsEnabled = false; 57 | await Task.Run(async () => 58 | { 59 | try 60 | { 61 | string message = string.Empty; 62 | if (!HasEmptyFields()) 63 | { 64 | if (SettingsViewModel.Instance.RegistrationUser.Password != SettingsViewModel.Instance.RegistrationUser.RepeatPassword) 65 | { 66 | MainWindowViewModel.Instance.AppBarText = "Password must be equal"; 67 | return; 68 | } 69 | string jsonObject = JsonSerializer.Serialize(SettingsViewModel.Instance.RegistrationUser); 70 | WebHelper.Post($"{SettingsViewModel.Instance.ServerUrl}/api/users/register", jsonObject); 71 | message = "Successfully registered"; 72 | SettingsViewModel.Instance.RegistrationUser = new User(); 73 | App.Current.Dispatcher.Invoke((Action)delegate 74 | { 75 | uiPwReg.Password = string.Empty; 76 | uiPwRegRepeat.Password = string.Empty; 77 | }); 78 | } 79 | else 80 | { 81 | message = "All mandatory fields must be filled"; 82 | } 83 | MainWindowViewModel.Instance.AppBarText = message; 84 | } 85 | catch (Exception ex) 86 | { 87 | string errMessage = WebExceptionHelper.TryGetServerMessage(ex); 88 | MainWindowViewModel.Instance.AppBarText = errMessage; 89 | } 90 | }); 91 | uiBtnRegister.IsEnabled = true; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /gamevault/UserControls/SettingsComponents/RootPathUserControl.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /gamevault/UserControls/SettingsComponents/RootPathUserControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using gamevault.ViewModels; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace gamevault.UserControls.SettingsComponents 18 | { 19 | /// 20 | /// Interaction logic for RootPathUserControl.xaml 21 | /// 22 | public partial class RootPathUserControl : UserControl 23 | { 24 | public RootPathUserControl() 25 | { 26 | InitializeComponent(); 27 | } 28 | private void RootPath_Click(object sender, RoutedEventArgs e) 29 | { 30 | SettingsViewModel.Instance.SelectDownloadPath(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gamevault/UserControls/SettingsComponents/ServerUrlUserControl.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /gamevault/UserControls/SettingsComponents/ServerUrlUserControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using ABI.System; 2 | using gamevault.Models; 3 | using gamevault.ViewModels; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | using System.Windows; 10 | using System.Windows.Controls; 11 | 12 | 13 | namespace gamevault.UserControls.SettingsComponents 14 | { 15 | /// 16 | /// Interaction logic for ServerUrlUserControl.xaml 17 | /// 18 | public partial class ServerUrlUserControl : UserControl 19 | { 20 | public ServerUrlUserControl() 21 | { 22 | InitializeComponent(); 23 | } 24 | private void SaveServerUrl_Click(object sender, RoutedEventArgs e) 25 | { 26 | SaveServerURL(); 27 | } 28 | 29 | private void Save_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) 30 | { 31 | if (e.Key == System.Windows.Input.Key.Enter) 32 | { 33 | SaveServerURL(); 34 | } 35 | } 36 | private void SaveServerURL() 37 | { 38 | if (SettingsViewModel.Instance.ServerUrl.EndsWith("/")) 39 | { 40 | SettingsViewModel.Instance.ServerUrl = SettingsViewModel.Instance.ServerUrl.Substring(0, SettingsViewModel.Instance.ServerUrl.Length - 1); 41 | } 42 | if (!SettingsViewModel.Instance.ServerUrl.Contains(System.Uri.UriSchemeHttp)) 43 | { 44 | SettingsViewModel.Instance.ServerUrl = $"{System.Uri.UriSchemeHttps}://{SettingsViewModel.Instance.ServerUrl}"; 45 | } 46 | Preferences.Set(AppConfigKey.ServerUrl, SettingsViewModel.Instance.ServerUrl, AppFilePath.UserFile, true); 47 | MainWindowViewModel.Instance.AppBarText = "Server URL saved"; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /gamevault/UserControls/Wizard.xaml.cs: -------------------------------------------------------------------------------- 1 | using gamevault.UserControls.SettingsComponents; 2 | using gamevault.ViewModels; 3 | using MahApps.Metro.Controls.Dialogs; 4 | using MahApps.Metro.Controls; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Diagnostics; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows; 12 | using System.Windows.Controls; 13 | using System.Windows.Data; 14 | using System.Windows.Documents; 15 | using System.Windows.Forms; 16 | using System.Windows.Input; 17 | using System.Windows.Media; 18 | using System.Windows.Media.Imaging; 19 | using System.Windows.Navigation; 20 | using System.Windows.Shapes; 21 | using UserControl = System.Windows.Controls.UserControl; 22 | 23 | namespace gamevault.UserControls 24 | { 25 | /// 26 | /// Interaction logic for Wizard.xaml 27 | /// 28 | public partial class Wizard : UserControl 29 | { 30 | public Wizard() 31 | { 32 | InitializeComponent(); 33 | this.DataContext = SettingsViewModel.Instance; 34 | } 35 | 36 | private void Next_Clicked(object sender, RoutedEventArgs e) 37 | { 38 | uiTabControl.SelectedIndex += 1; 39 | } 40 | 41 | private void Back_Clicked(object sender, RoutedEventArgs e) 42 | { 43 | uiTabControl.SelectedIndex -= 1; 44 | } 45 | 46 | private void Login_Clicked(object sender, RoutedEventArgs e) 47 | { 48 | uiLoginRegisterPopup.Child = new LoginUserControl(); 49 | uiLoginRegisterPopup.IsOpen = true; 50 | } 51 | 52 | private void Register_Clicked(object sender, RoutedEventArgs e) 53 | { 54 | uiLoginRegisterPopup.Child = new RegisterUserControl(); 55 | uiLoginRegisterPopup.IsOpen = true; 56 | } 57 | 58 | private void Help_Clicked(object sender, MouseButtonEventArgs e) 59 | { 60 | try 61 | { 62 | string? url = (string)((FrameworkElement)sender).Tag; 63 | if (Uri.IsWellFormedUriString(url, UriKind.Absolute)) 64 | { 65 | Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); 66 | } 67 | } 68 | catch { } 69 | } 70 | 71 | private async void Finish_Clicked(object sender, RoutedEventArgs e) 72 | { 73 | MessageDialogResult result = await ((MetroWindow)App.Current.MainWindow).ShowMessageAsync("", $"Do you want to leave the setup wizard?", MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings() { AffirmativeButtonText = "Yes", NegativeButtonText = "No", AnimateHide = false, DialogMessageFontSize = 50 }); 74 | if (result == MessageDialogResult.Affirmative) 75 | { 76 | MainWindowViewModel.Instance.SetActiveControl(null); 77 | MainWindowViewModel.Instance.SetActiveControl(MainControl.Library); 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /gamevault/ViewModels/AdminConsoleViewModel.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace gamevault.ViewModels 9 | { 10 | internal class AdminConsoleViewModel : ViewModelBase 11 | { 12 | private User[] m_Users { get; set; } 13 | private bool showDeletedUsers { get; set; } 14 | private KeyValuePair m_ServerVersionInfo { get; set; } 15 | 16 | public User[]? Users 17 | { 18 | get { return m_Users; } 19 | set { m_Users = value; OnPropertyChanged(); } 20 | } 21 | public bool ShowDeletedUsers 22 | { 23 | get { return showDeletedUsers; } 24 | set { showDeletedUsers = value; OnPropertyChanged(); } 25 | } 26 | public Array PermissionRoleEnumTypes 27 | { 28 | get 29 | { 30 | return Enum.GetValues(typeof(PERMISSION_ROLE)); 31 | } 32 | } 33 | public KeyValuePair ServerVersionInfo 34 | { 35 | get { return m_ServerVersionInfo; } 36 | set { m_ServerVersionInfo = value; OnPropertyChanged(); } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /gamevault/ViewModels/CommunityViewModel.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.ViewModels 10 | { 11 | internal class CommunityViewModel : ViewModelBase 12 | { 13 | #region PrivateMembers 14 | 15 | private User[]? m_Users { get; set; } 16 | private User? m_CurrentShownUser { get; set; } 17 | private List m_UserProgresses { get; set; } 18 | 19 | #endregion 20 | public User[]? Users 21 | { 22 | get { return m_Users; } 23 | set { m_Users = value; OnPropertyChanged(); } 24 | } 25 | public User? CurrentShownUser 26 | { 27 | get { return m_CurrentShownUser; } 28 | set 29 | { 30 | m_CurrentShownUser = value; 31 | UserProgresses = new List(m_CurrentShownUser.Progresses); 32 | m_CurrentShownUser.Progresses = null; 33 | OnPropertyChanged(); 34 | } 35 | } 36 | 37 | public List UserProgresses 38 | { 39 | get 40 | { 41 | if(m_UserProgresses== null) 42 | { 43 | m_UserProgresses = new List(); 44 | } 45 | return m_UserProgresses; 46 | } 47 | set 48 | { 49 | m_UserProgresses = value; OnPropertyChanged(); 50 | } 51 | } 52 | public string[] SortBy 53 | { 54 | get 55 | { 56 | return new string[] { "State", "Time played", "Last played" }; 57 | } 58 | } 59 | 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /gamevault/ViewModels/DownloadsViewModel.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using gamevault.UserControls; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace gamevault.ViewModels 11 | { 12 | internal class DownloadsViewModel : ViewModelBase 13 | { 14 | #region Singleton 15 | private static DownloadsViewModel instance = null; 16 | private static readonly object padlock = new object(); 17 | 18 | public static DownloadsViewModel Instance 19 | { 20 | get 21 | { 22 | lock (padlock) 23 | { 24 | if (instance == null) 25 | { 26 | instance = new DownloadsViewModel(); 27 | } 28 | return instance; 29 | } 30 | } 31 | } 32 | #endregion 33 | #region PrivateMembers 34 | private ObservableCollection m_DownloadedGames { get; set; } 35 | 36 | #endregion 37 | 38 | public ObservableCollection DownloadedGames 39 | { 40 | get 41 | { 42 | if (m_DownloadedGames == null) 43 | { 44 | m_DownloadedGames = new ObservableCollection(); 45 | } 46 | return m_DownloadedGames; 47 | } 48 | set { m_DownloadedGames = value; OnPropertyChanged(); } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /gamevault/ViewModels/GameViewViewModel.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Documents; 10 | 11 | namespace gamevault.ViewModels 12 | { 13 | internal class GameViewViewModel : ViewModelBase 14 | { 15 | #region PrivateMembers 16 | private Game? game { get; set; } 17 | private Progress? currentUserProgress { get; set; } 18 | private Progress[]? userProgresses { get; set; } 19 | private Dictionary gameStates { get; set; } 20 | private bool isInstalled { get; set; } 21 | private bool? isDownloaded { get; set; } 22 | private string? descriptionMarkdown { get; set; } 23 | private string? notesMarkdown { get; set; } 24 | private string cloudSaveMatchTitle { get; set; } 25 | #endregion 26 | public Game? Game 27 | { 28 | get { return game; } 29 | set { game = value; OnPropertyChanged(); } 30 | } 31 | public Progress? CurrentUserProgress 32 | { 33 | get { return currentUserProgress; } 34 | set { currentUserProgress = value; OnPropertyChanged(); } 35 | } 36 | public Progress[]? UserProgresses 37 | { 38 | get { return userProgresses; } 39 | set { userProgresses = value; OnPropertyChanged(); } 40 | } 41 | public Dictionary? GameStates 42 | { 43 | get => gameStates ?? (gameStates = Enum.GetValues(typeof(State)) 44 | .Cast() 45 | .ToDictionary(state => GetEnumDescription(state), state => state.ToString())); 46 | set { gameStates = value; OnPropertyChanged(); } 47 | } 48 | 49 | private static string GetEnumDescription(State value) => 50 | (Attribute.GetCustomAttribute(value.GetType().GetField(value.ToString()), typeof(DescriptionAttribute)) is DescriptionAttribute attribute) ? attribute.Description : value.ToString(); 51 | public bool IsInstalled 52 | { 53 | get { return isInstalled; } 54 | set { isInstalled = value; OnPropertyChanged(); } 55 | } 56 | public bool? IsDownloaded 57 | { 58 | get { return isDownloaded; } 59 | set { isDownloaded = value; OnPropertyChanged(); } 60 | } 61 | public string? DescriptionMarkdown 62 | { 63 | get { return descriptionMarkdown; } 64 | set { descriptionMarkdown = value; OnPropertyChanged(); } 65 | } 66 | public string? NotesMarkdown 67 | { 68 | get { return notesMarkdown; } 69 | set { notesMarkdown = value; OnPropertyChanged(); } 70 | } 71 | public string CloudSaveMatchTitle 72 | { 73 | get { return cloudSaveMatchTitle; } 74 | set { cloudSaveMatchTitle = value; OnPropertyChanged(); } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /gamevault/ViewModels/InstallViewModel.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using gamevault.UserControls; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.ComponentModel; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace gamevault.ViewModels 12 | { 13 | internal class InstallViewModel : ViewModelBase 14 | { 15 | #region Singleton 16 | private static InstallViewModel instance = null; 17 | private static readonly object padlock = new object(); 18 | 19 | public static InstallViewModel Instance 20 | { 21 | get 22 | { 23 | lock (padlock) 24 | { 25 | if (instance == null) 26 | { 27 | instance = new InstallViewModel(); 28 | } 29 | return instance; 30 | } 31 | } 32 | } 33 | #endregion 34 | #region PrivateMembers 35 | private ObservableCollection> m_InstalledGames { get; set; } 36 | public ICollectionView? installedGamesFilter { get; set; } 37 | private int rows { get; set; } = 0; 38 | private int colums { get; set; } = 0; 39 | #endregion 40 | public ObservableCollection> InstalledGames 41 | { 42 | get 43 | { 44 | if (m_InstalledGames == null) 45 | { 46 | m_InstalledGames = new ObservableCollection>(); 47 | } 48 | return m_InstalledGames; 49 | } 50 | set { m_InstalledGames = value; OnPropertyChanged(); } 51 | } 52 | public ICollectionView? InstalledGamesFilter 53 | { 54 | get { return installedGamesFilter; } 55 | set { installedGamesFilter = value; OnPropertyChanged(); } 56 | } 57 | public void RefreshGame(Game gameToRefreshParam) 58 | { 59 | KeyValuePair gameToRefresh = InstalledGames.Where(g => g.Key.ID == gameToRefreshParam.ID).FirstOrDefault(); 60 | if (!gameToRefresh.Equals(default(KeyValuePair))) 61 | { 62 | int index = InstalledGames.IndexOf(gameToRefresh); 63 | InstalledGames[index] = new KeyValuePair(gameToRefreshParam, gameToRefresh.Value); 64 | } 65 | } 66 | public int Rows 67 | { 68 | get { return rows; } 69 | 70 | set 71 | { 72 | rows = value; OnPropertyChanged(); 73 | } 74 | } 75 | public int Colums 76 | { 77 | get { return colums; } 78 | 79 | set 80 | { 81 | colums = value; OnPropertyChanged(); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /gamevault/ViewModels/LibraryViewModel.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | 10 | namespace gamevault.ViewModels 11 | { 12 | internal class LibraryViewModel : ViewModelBase 13 | { 14 | #region PrivateMembers 15 | private ObservableCollection gameCards { get; set; } 16 | private int totalGamesCount = -1; 17 | private Visibility scrollToTopVisibility { get; set; } 18 | private Visibility filterVisibility = Visibility.Collapsed; 19 | private KeyValuePair m_SelectedGameFilterSortBy { get; set; } 20 | private string filterCounter { get; set; } = string.Empty; 21 | private bool canLoadServerGames { get; set; } = true; 22 | #endregion 23 | public ObservableCollection GameCards 24 | { 25 | get 26 | { 27 | if (gameCards == null) 28 | { 29 | gameCards = new ObservableCollection(); 30 | } 31 | return gameCards; 32 | } 33 | set { gameCards = value; } 34 | } 35 | public int TotalGamesCount 36 | { 37 | get { return totalGamesCount; } 38 | set { totalGamesCount = value; OnPropertyChanged(); } 39 | } 40 | public Visibility ScrollToTopVisibility 41 | { 42 | get { return scrollToTopVisibility; } 43 | set { scrollToTopVisibility = value; OnPropertyChanged(); } 44 | } 45 | public Visibility FilterVisibility 46 | { 47 | get { return filterVisibility; } 48 | set { filterVisibility = value; OnPropertyChanged(); } 49 | } 50 | public string? NextPage { get; set; } 51 | public Dictionary GameFilterSortByValues 52 | { 53 | get 54 | { 55 | var dict = new Dictionary 56 | { 57 | {"Title","sort_title"}, 58 | {"Size","size" }, 59 | {"Date Added","created_at" }, 60 | {"Release Date","metadata.release_date" }, 61 | {"Rating","metadata.rating" }, 62 | {"Download Count","download_count" }, 63 | {"Average Playtime","metadata.average_playtime" }, 64 | }; 65 | return dict; 66 | } 67 | } 68 | public KeyValuePair SelectedGameFilterSortBy 69 | { 70 | get { return m_SelectedGameFilterSortBy; } 71 | set { m_SelectedGameFilterSortBy = value; } 72 | } 73 | public string FilterCounter 74 | { 75 | get { return filterCounter; } 76 | set { filterCounter = value; OnPropertyChanged(); } 77 | } 78 | public bool CanLoadServerGames 79 | { 80 | get { return canLoadServerGames; } 81 | set { canLoadServerGames = value; OnPropertyChanged(); } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /gamevault/ViewModels/UserSettingsViewModel.cs: -------------------------------------------------------------------------------- 1 | using gamevault.Models; 2 | using gamevault.Models.Mapping; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows.Media; 9 | 10 | namespace gamevault.ViewModels 11 | { 12 | internal class UserSettingsViewModel : ViewModelBase 13 | { 14 | #region Privates 15 | private User originUser { get; set; } 16 | private UpdateUserDto updateUser { get; set; } 17 | private bool userDetailsChanged { get; set; } 18 | private bool backgroundImageChanged { get; set; } 19 | private bool avatarImageChanged { get; set; } 20 | private ImageSource backgroundImageSource { get; set; } 21 | private string avatarImageUrl { get; set; } 22 | #endregion 23 | public User OriginUser 24 | { 25 | get { return originUser; } 26 | set { originUser = value; OnPropertyChanged(); } 27 | } 28 | public UpdateUserDto UpdateUser 29 | { 30 | get { return updateUser; } 31 | set { updateUser = value; OnPropertyChanged(); } 32 | } 33 | public bool UserDetailsChanged 34 | { 35 | get { return userDetailsChanged; } 36 | set { userDetailsChanged = value; OnPropertyChanged(); } 37 | } 38 | public bool BackgroundImageChanged 39 | { 40 | get { return backgroundImageChanged; } 41 | set { backgroundImageChanged = value; OnPropertyChanged(); } 42 | } 43 | public bool AvatarImageChanged 44 | { 45 | get { return avatarImageChanged; } 46 | set { avatarImageChanged = value; OnPropertyChanged(); } 47 | } 48 | public ImageSource BackgroundImageSource 49 | { 50 | get { return backgroundImageSource; } 51 | set { backgroundImageSource = value; OnPropertyChanged(); BackgroundImageChanged = true; } 52 | } 53 | public string AvatarImageUrl 54 | { 55 | get { return avatarImageUrl; } 56 | set { avatarImageUrl = value; OnPropertyChanged(); AvatarImageChanged = true; } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /gamevault/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Runtime.CompilerServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace gamevault.ViewModels 10 | { 11 | abstract class ViewModelBase : INotifyPropertyChanged 12 | { 13 | public event PropertyChangedEventHandler PropertyChanged; 14 | 15 | protected void OnPropertyChanged([CallerMemberName] string name = "") 16 | { 17 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /gamevault/Windows/ExceptionWindow.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | An unhandeled Error has occured in GameVault 21 | You can view technical details in the Error Log that has been created. 22 | 23 |