Files
Barış Keser 83be058d23 feat: Athena v2 — Discord auth, AthenaCore mod, cross-platform launcher, CI
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.
2026-06-13 23:45:21 +03:00

184 lines
5.4 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Interactivity;
using OfflineMinecraftLauncher.Services;
namespace OfflineMinecraftLauncher.Views;
public partial class MainWindow : Window
{
private readonly LocalSettings _settings = LocalSettings.Load();
private readonly AuthService _auth = new();
private readonly LauncherCore _core;
private Account? _selected;
private List<Account> _accounts = new();
private HomeView? _home;
private AccountsView? _accountsView;
private ModsView? _modsView;
private SettingsView? _settingsView;
private NewsView? _newsView;
public MainWindow()
{
InitializeComponent();
_core = new LauncherCore(_auth, _settings);
Opened += async (_, _) => await InitAsync();
}
private async Task InitAsync()
{
SetLoading("Bağlanılıyor...");
try
{
var (banned, reason) = await _core.CheckBanAsync();
if (banned) { ShowBan(reason); return; }
try { await _core.FetchConfigAsync(); } catch { }
if (!_auth.HasValidSession) { ShowLogin(); return; }
await LoadAccountsAndContinue();
}
catch (Exception e)
{
SetLoading("Hata: " + e.Message);
}
}
private async Task LoadAccountsAndContinue()
{
SetLoading("Hesaplar yükleniyor...");
_accounts = await _auth.GetAccountsAsync();
_selected = _accounts.FirstOrDefault(a => a.Id == _settings.SelectedAccountId) ?? _accounts.FirstOrDefault();
if (_selected != null) { _settings.SelectedAccountId = _selected.Id; _settings.Save(); }
LoadingOverlay.IsVisible = false;
LoginHost.IsVisible = false;
BanOverlay.IsVisible = false;
Shell.IsVisible = true;
NavigateTo(_selected == null ? "accounts" : "home");
}
private void ShowLogin()
{
var login = new LoginView(_auth);
login.LoggedIn += async () =>
{
LoginHost.IsVisible = false;
SetLoading("Giriş yapıldı...");
await LoadAccountsAndContinue();
};
LoginHost.Content = login;
Shell.IsVisible = false;
LoadingOverlay.IsVisible = false;
BanOverlay.IsVisible = false;
LoginHost.IsVisible = true;
}
private void ShowBan(string reason)
{
BanReason.Text = string.IsNullOrWhiteSpace(reason) ? "Bu cihaz yasaklandı." : reason;
LoadingOverlay.IsVisible = false;
Shell.IsVisible = false;
LoginHost.IsVisible = false;
BanOverlay.IsVisible = true;
}
private void SetLoading(string text)
{
LoadingText.Text = text;
LoadingOverlay.IsVisible = true;
}
private void NavigateTo(string tag)
{
switch (tag)
{
case "home":
_home ??= CreateHome();
_home.SetAccount(_selected);
_ = _home.RefreshStatusAsync();
PageHost.Content = _home;
break;
case "accounts":
_accountsView ??= CreateAccounts();
_ = _accountsView.RefreshAsync();
PageHost.Content = _accountsView;
break;
case "mods":
_modsView ??= new ModsView(_core, _settings);
_ = _modsView.RefreshAsync();
PageHost.Content = _modsView;
break;
case "news":
_newsView ??= new NewsView(_core);
_ = _newsView.RefreshAsync();
PageHost.Content = _newsView;
break;
case "settings":
_settingsView ??= new SettingsView(_settings);
PageHost.Content = _settingsView;
break;
}
SetActiveNav(tag);
}
private HomeView CreateHome()
{
var h = new HomeView(_core, _settings);
h.ChangeAccountRequested += () => NavigateTo("accounts");
return h;
}
private AccountsView CreateAccounts()
{
var v = new AccountsView(_auth, _settings);
v.AccountChosen += acc =>
{
_selected = acc;
_settings.SelectedAccountId = acc.Id;
_settings.Save();
NavigateTo("home");
};
return v;
}
private void SetActiveNav(string tag)
{
foreach (var b in new[] { NavHome, NavAccounts, NavMods, NavNews, NavSettings })
b.Classes.Remove("active");
Button? active = tag switch
{
"home" => NavHome,
"accounts" => NavAccounts,
"mods" => NavMods,
"news" => NavNews,
"settings" => NavSettings,
_ => null
};
active?.Classes.Add("active");
}
private void OnNav(object? sender, RoutedEventArgs e)
{
if (sender is Button b && b.Tag is string tag) NavigateTo(tag);
}
private void OnOpenDiscord(object? sender, RoutedEventArgs e)
{
try { Process.Start(new ProcessStartInfo { FileName = AppConfig.DiscordUrl, UseShellExecute = true }); }
catch { }
}
private void OnLogout(object? sender, RoutedEventArgs e)
{
_auth.Logout();
_selected = null;
_home = null; _accountsView = null; _modsView = null; _newsView = null; _settingsView = null;
ShowLogin();
}
}