diff --git a/WpfApp6.sln b/WpfApp6.sln new file mode 100644 index 0000000..7bd9200 --- /dev/null +++ b/WpfApp6.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33530.505 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PSTW", "WpfApp6\PSTW.csproj", "{355A0DBF-B506-4AFC-9C0E-2884A2169337}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {355A0DBF-B506-4AFC-9C0E-2884A2169337}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {355A0DBF-B506-4AFC-9C0E-2884A2169337}.Debug|Any CPU.Build.0 = Debug|Any CPU + {355A0DBF-B506-4AFC-9C0E-2884A2169337}.Release|Any CPU.ActiveCfg = Release|Any CPU + {355A0DBF-B506-4AFC-9C0E-2884A2169337}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {13A9430D-AC9A-43D0-92CB-D4263C2DCE35} + EndGlobalSection +EndGlobal diff --git a/WpfApp6/82b12ac249fbb223299e6a234b87b948.ico b/WpfApp6/82b12ac249fbb223299e6a234b87b948.ico new file mode 100644 index 0000000..38ffeda Binary files /dev/null and b/WpfApp6/82b12ac249fbb223299e6a234b87b948.ico differ diff --git a/WpfApp6/App.xaml b/WpfApp6/App.xaml new file mode 100644 index 0000000..9ab1b04 --- /dev/null +++ b/WpfApp6/App.xaml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/WpfApp6/App.xaml.cs b/WpfApp6/App.xaml.cs new file mode 100644 index 0000000..9a7b964 --- /dev/null +++ b/WpfApp6/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace WpfApp6 +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/WpfApp6/AssemblyInfo.cs b/WpfApp6/AssemblyInfo.cs new file mode 100644 index 0000000..427f202 --- /dev/null +++ b/WpfApp6/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/WpfApp6/MainWindow.xaml b/WpfApp6/MainWindow.xaml new file mode 100644 index 0000000..7196552 --- /dev/null +++ b/WpfApp6/MainWindow.xaml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WpfApp6/MainWindow.xaml.cs b/WpfApp6/MainWindow.xaml.cs new file mode 100644 index 0000000..3703ff4 --- /dev/null +++ b/WpfApp6/MainWindow.xaml.cs @@ -0,0 +1,165 @@ +using ModernWpf.Controls; +using System; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Navigation; +using WpfApp6.Pages; +using ModernWpf.Media.Animation; +using System.Net.NetworkInformation; +using System.IO; + +namespace WpfApp6 +{ + public partial class MainWindow : Window + { + Home home = new Home(); + Settings settings = new Settings(); + Downloader download = new Downloader(); + Loading loading = new Loading(); + AnnouncementsPage announcementsPage = new AnnouncementsPage(); // Add AnnouncementsPage instance + + public MainWindow() + { + InitializeComponent(); + + if (!CheckInternetConnection()) + { + MessageBox.Show("You need to be connected to the internet."); + Close(); + } + + ContentFrame.Navigate(loading); + + // Check server status and Version + CheckServerStatusAndVersion(); + } + + private void NavView_Loaded(object sender, RoutedEventArgs e) + { + ContentFrame.Navigate(home); + } + + private bool CheckInternetConnection() + { + try + { + Ping ping = new Ping(); + PingReply reply = ping.Send("www.google.com", 3000); + return reply != null && reply.Status == IPStatus.Success; + } + catch + { + return false; + } + } + + private void NavView_SelectionChanged(ModernWpf.Controls.NavigationView sender, ModernWpf.Controls.NavigationViewSelectionChangedEventArgs args) + { + if (args.IsSettingsSelected) + { + ContentFrame.Navigate(settings); + } + else + { + NavigationViewItem item = args.SelectedItem as NavigationViewItem; + + if (item != null) + { + if (item.Tag != null) + { + if (item.Tag.ToString() == "Home") + { + ContentFrame.Navigate(home); + } + else if (item.Tag.ToString() == "Downloader") + { + ContentFrame.Navigate(new Downloader()); + } + else if (item.Tag.ToString() == "Announcements") + { + ContentFrame.Navigate(announcementsPage); + } + } + } + } + } + + private async void CheckServerStatusAndVersion() + { + try + { + // Check server status + await CheckUrlEndpoint("http://127.0.0.1:5000/api/access_status"); //replace with your actual server ip + + // Check version + using (HttpClient client = new HttpClient()) + { + HttpResponseMessage response = await client.GetAsync("http://127.0.0.1:5000/api/version"); //replace with your actual server ip + + if (response.IsSuccessStatusCode) + { + string jsonString = await response.Content.ReadAsStringAsync(); + + // Parse the JSON string + var json = System.Text.Json.JsonDocument.Parse(jsonString); + var version = json.RootElement.GetProperty("version").GetString(); + + if (version.Equals("0.3", StringComparison.InvariantCulture)) + { + // Continue with the rest of the code + ContentFrame.Navigate(home); + } + else + { + MessageBox.Show($"Please Update The Launcher to {version}"); + Close(); + } + } + else + { + MessageBox.Show($"Server returned non-success status code: {response.StatusCode}"); + Close(); + } + } + } + catch (Exception ex) + { + MessageBox.Show($"An error occurred: {ex.Message}"); + Close(); + } + } + + private async Task CheckUrlEndpoint(string url) + { + using (HttpClient client = new HttpClient()) + { + HttpResponseMessage response = await client.GetAsync(url); + + if (response.IsSuccessStatusCode) + { + string content = await response.Content.ReadAsStringAsync(); + + if (content.Equals("Denied", StringComparison.OrdinalIgnoreCase)) + { + MessageBox.Show("Server Maintenance", "Access Denied"); + Close(); + } + // No need to check for "Allowed" explicitly, as it will continue with the execution + } + else + { + MessageBox.Show($"Failed to check the URL. Status code: {response.StatusCode}"); + Close(); + } + } + } + + private void ContentFrame_NavigationFailed(object sender, NavigationFailedEventArgs e) + { + throw new Exception("Failed to load Page."); // Never TBH + } + } +} diff --git a/WpfApp6/PSTW.csproj b/WpfApp6/PSTW.csproj new file mode 100644 index 0000000..b9a33ff --- /dev/null +++ b/WpfApp6/PSTW.csproj @@ -0,0 +1,33 @@ + + + + WinExe + net6.0-windows + enable + true + 82b12ac249fbb223299e6a234b87b948.ico + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WpfApp6/PSTW.csproj.user b/WpfApp6/PSTW.csproj.user new file mode 100644 index 0000000..8d0f58e --- /dev/null +++ b/WpfApp6/PSTW.csproj.user @@ -0,0 +1,42 @@ + + + + <_LastSelectedProfileId>C:\Users\vloge\source\repos\WpfApp6\WpfApp6\Properties\PublishProfiles\FolderProfile.pubxml + + + + Designer + + + + + Code + + + Code + + + Code + + + Code + + + + + Designer + + + Designer + + + Designer + + + Designer + + + Designer + + + \ No newline at end of file diff --git a/WpfApp6/Pages/82b12ac249fbb223299e6a234b87b948.png b/WpfApp6/Pages/82b12ac249fbb223299e6a234b87b948.png new file mode 100644 index 0000000..dd16cc0 Binary files /dev/null and b/WpfApp6/Pages/82b12ac249fbb223299e6a234b87b948.png differ diff --git a/WpfApp6/Pages/AnnouncementsPage.xaml b/WpfApp6/Pages/AnnouncementsPage.xaml new file mode 100644 index 0000000..538c503 --- /dev/null +++ b/WpfApp6/Pages/AnnouncementsPage.xaml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/WpfApp6/Pages/AnnouncementsPage.xaml.cs b/WpfApp6/Pages/AnnouncementsPage.xaml.cs new file mode 100644 index 0000000..709cac9 --- /dev/null +++ b/WpfApp6/Pages/AnnouncementsPage.xaml.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using Newtonsoft.Json.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; + +namespace WpfApp6.Pages +{ + public partial class AnnouncementsPage : Page + { + public AnnouncementsPage() + { + InitializeComponent(); + LoadDataFromApi(); + } + + private async void LoadDataFromApi() + { + try + { + string apiUrl = "http://127.0.0.1:5000/api/announcements"; //replace with actual server url + using (HttpClient client = new HttpClient()) + { + string jsonResult = await client.GetStringAsync(apiUrl); + + JObject data = JObject.Parse(jsonResult); + + if (data != null) + { + // Assuming "announcements" is the property containing the array of announcements + JArray announcementsArray = (JArray)data["announcements"]; + + if (announcementsArray != null) + { + // Deserialize the JSON array into a list of Announcement objects + List announcements = announcementsArray.Select(item => new Announcement + { + Author = item["author"].ToString(), + Avatar = item["avatar"].ToString(), + Message = item["message"].ToString(), + DateTime = DateTime.Parse(item["datetime"].ToString()) // Assuming the datetime field in JSON + }).ToList(); + + // Sort the announcements by DateTime in descending order (newest first) + announcements = announcements.OrderByDescending(a => a.DateTime).ToList(); + + // Display the sorted announcements + foreach (var announcement in announcements) + { + AddAnnouncementToUI(announcement.Author, announcement.Avatar, announcement.Message, announcement.DateTime); + } + } + } + } + } + catch (Exception ex) + { + MessageBox.Show($"Error: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + + private void AddAnnouncementToUI(string author, string avatarUrl, string message, DateTime dateTime) + { + + // Assume dateTime is in UTC + var utcTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); + + // Convert UTC time to local time + var localTimeZone = TimeZoneInfo.Local; + var localTimeConverted = TimeZoneInfo.ConvertTime(utcTime, localTimeZone); + + StackPanel announcementPanel = new StackPanel + { + Orientation = Orientation.Horizontal, + Margin = new Thickness(10) + }; + + Image avatarImage = new Image + { + Source = new System.Windows.Media.Imaging.BitmapImage(new Uri(avatarUrl)), + Width = 50, + Height = 50, + Margin = new Thickness(0, 0, 10, 0) + }; + + TextBlock authorTextBlock = new TextBlock + { + Text = $"{author}", + FontWeight = FontWeights.Bold, + Foreground = new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#ff00e2")) + }; + + TextBlock messageTextBlock = new TextBlock + { + Text = message, + Margin = new Thickness(10, 0, 0, 0) + }; + + TextBlock dateTextBlock = new TextBlock + { + Text = $" ({localTimeConverted:yyyy-MM-dd HH:mm})", + Foreground = new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#87CEEB")) // Light blue color + }; + + announcementPanel.Children.Add(avatarImage); + announcementPanel.Children.Add(authorTextBlock); + announcementPanel.Children.Add(messageTextBlock); + announcementPanel.Children.Add(dateTextBlock); + + AnnouncementsStackPanel.Children.Add(announcementPanel); + } + } + + // Define a class to represent an Announcement + public class Announcement + { + public string Author { get; set; } + public string Avatar { get; set; } + public string Message { get; set; } + public DateTime DateTime { get; set; } + } +} diff --git a/WpfApp6/Pages/CloudArrow.png b/WpfApp6/Pages/CloudArrow.png new file mode 100644 index 0000000..973c09c Binary files /dev/null and b/WpfApp6/Pages/CloudArrow.png differ diff --git a/WpfApp6/Pages/Download.png b/WpfApp6/Pages/Download.png new file mode 100644 index 0000000..8af7110 Binary files /dev/null and b/WpfApp6/Pages/Download.png differ diff --git a/WpfApp6/Pages/Downloader.xaml b/WpfApp6/Pages/Downloader.xaml new file mode 100644 index 0000000..2140a03 --- /dev/null +++ b/WpfApp6/Pages/Downloader.xaml @@ -0,0 +1,16 @@ + + + + + +