mirror of
https://github.com/RoyalnetworkTR/simple-launcher.git
synced 2026-09-25 01:39:49 +03:00
Backend (PHP+SQLite): Discord OAuth2 + JWT, coklu hesap (1 Discord = 3-5), tek-kullanimlik join token (/api/join/prepare+verify), custom skin yukleme/sunma, hesap/Discord/HWID ban, admin paneli kartlari; deterministik offline UUID (PHP<->C# paritesi dogrulandi). 25 entegrasyon testi gecti. AthenaCore (Forge 1.12.2): tek client+server mod — join token dogrulama + kick, grace-gate, custom skin uygulama. Sunucu offline-mode kalir (UUID/dunya verisi korunur). Masaustu: WPF -> Avalonia (Windows+Linux), Discord giris/hesap/skin/oyna; WMI/DPAPI yerine cross-platform (machine-id HWID, AES-GCM secret store). Derlenir + calisir. CI: athenacore-mod.yml (JDK8), desktop-release.yml (Win+Linux self-contained). Deploy: deploy.sh (.env uretimi, php-gd, nginx Authorization gecisi) + HANDOFF.md. Android: backend hazir; entegrasyon spec'i ANDROID_INTEGRATION.md.
73 lines
2.2 KiB
C#
73 lines
2.2 KiB
C#
using System.Collections.Generic;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Media;
|
||
|
||
namespace OfflineMinecraftLauncher.Pages;
|
||
|
||
public partial class NewsPage : UserControl
|
||
{
|
||
private readonly LauncherCore _core;
|
||
private bool _loaded;
|
||
|
||
public NewsPage(LauncherCore core)
|
||
{
|
||
_core = core;
|
||
InitializeComponent();
|
||
}
|
||
|
||
public async void Reload()
|
||
{
|
||
if (_loaded) return;
|
||
_loaded = true; // tekrar girişi (hızlı sekme değişimi) senkron olarak engelle
|
||
List<ChangelogEntry> entries;
|
||
try { entries = await _core.FetchChangelogAsync(); }
|
||
catch { entries = new List<ChangelogEntry>(); }
|
||
|
||
NewsList.Children.Clear();
|
||
EmptyLabel.Visibility = entries.Count == 0 ? Visibility.Visible : Visibility.Collapsed;
|
||
|
||
foreach (var entry in entries)
|
||
NewsList.Children.Add(BuildCard(entry));
|
||
}
|
||
|
||
private Border BuildCard(ChangelogEntry entry)
|
||
{
|
||
var card = new Border
|
||
{
|
||
Style = (Style)FindResource("Card"),
|
||
Margin = new Thickness(0, 0, 0, 10)
|
||
};
|
||
var sp = new StackPanel();
|
||
|
||
var header = new StackPanel { Orientation = Orientation.Horizontal };
|
||
var badge = new Border
|
||
{
|
||
Background = (Brush)FindResource("AccentBrush"),
|
||
CornerRadius = new CornerRadius(8),
|
||
Padding = new Thickness(10, 3, 10, 3)
|
||
};
|
||
badge.Child = new TextBlock { Text = "v" + entry.Version, Foreground = Brushes.White, FontWeight = FontWeights.SemiBold, FontSize = 12 };
|
||
header.Children.Add(badge);
|
||
header.Children.Add(new TextBlock
|
||
{
|
||
Text = entry.Timestamp,
|
||
Foreground = (Brush)FindResource("TextMutedBrush"),
|
||
FontSize = 11,
|
||
VerticalAlignment = VerticalAlignment.Center,
|
||
Margin = new Thickness(10, 0, 0, 0)
|
||
});
|
||
sp.Children.Add(header);
|
||
|
||
sp.Children.Add(new TextBlock
|
||
{
|
||
Text = entry.Note,
|
||
TextWrapping = TextWrapping.Wrap,
|
||
Margin = new Thickness(0, 10, 0, 0)
|
||
});
|
||
|
||
card.Child = sp;
|
||
return card;
|
||
}
|
||
}
|