From 9ef83c1a1e3b2db8c481206da2306588372adbd8 Mon Sep 17 00:00:00 2001 From: SuperDooper <37051355+superdooper86@users.noreply.github.com> Date: Fri, 8 May 2026 22:04:10 +0200 Subject: [PATCH] refactor: LoginWindow only saves cookies; all data fetched by background browser --- windows/LoginWindow.xaml.cs | 106 ++---------------------------------- 1 file changed, 6 insertions(+), 100 deletions(-) diff --git a/windows/LoginWindow.xaml.cs b/windows/LoginWindow.xaml.cs index a3c6ab4..c27fa6b 100644 --- a/windows/LoginWindow.xaml.cs +++ b/windows/LoginWindow.xaml.cs @@ -1,8 +1,5 @@ using Microsoft.Web.WebView2.Core; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text.Json; using System.Threading.Tasks; using System.Windows; @@ -22,7 +19,7 @@ public partial class LoginWindow : Window { var env = await CoreWebView2Environment.CreateAsync(userDataFolder: System.IO.Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "ClaudeChecker", "WebView2")); await Browser.EnsureCoreWebView2Async(env); @@ -35,9 +32,9 @@ public partial class LoginWindow : Window if (!uri.Contains("claude.ai")) return; var cookies = await Browser.CoreWebView2.CookieManager.GetCookiesAsync("https://claude.ai"); - var signedIn = cookies.Any(c => - c.Name.Equals("sessionKey", StringComparison.OrdinalIgnoreCase) || - c.Name.StartsWith("sk-ant", StringComparison.OrdinalIgnoreCase)); + var signedIn = System.Linq.Enumerable.Any(cookies, c => + c.Name.Equals("sessionKey", System.StringComparison.OrdinalIgnoreCase) || + c.Name.StartsWith("sk-ant", System.StringComparison.OrdinalIgnoreCase)); await Dispatcher.InvokeAsync(() => { @@ -64,101 +61,10 @@ public partial class LoginWindow : Window if (_closing) return; _closing = true; + // Persist cookies so the app knows the user is signed in on next startup. + // All live data is fetched by the background WebView2 on the next refresh. UsageViewModel.SaveCookies(cookies); - try - { - // Use WebMessageReceived so the async script can post back without relying - // on Promise-awaiting support in the WebView2 runtime version. - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - EventHandler? msgHandler = null; - msgHandler = (_, args) => - { - Browser.CoreWebView2.WebMessageReceived -= msgHandler; - tcs.TrySetResult(args.WebMessageAsJson); - }; - Browser.CoreWebView2.WebMessageReceived += msgHandler; - - const string script = @"(async()=>{try{ - const h={headers:{accept:'application/json'}}; - const b=await(await fetch('/api/bootstrap',h)).json(); - const org0=b?.account?.memberships?.[0]?.organization; - let id=org0?.uuid||b?.memberships?.[0]?.organization?.uuid - ||b?.organizations?.[0]?.uuid||b?.default_organization?.uuid||null; - const e=b?.account?.email_address||b?.account?.email||b?.email||null; - const caps=org0?.capabilities||[]; - const capStr=caps.find(c=>typeof c==='string'&&c.startsWith('claude_'))||null; - const planLabel=capStr?(capStr.slice(7,8).toUpperCase()+capStr.slice(8).toLowerCase()):null; - let orgSrc='bootstrap'; - if(!id){ - try{const ol=await(await fetch('/api/organizations',h)).json(); - if(Array.isArray(ol)&&ol.length>0){id=ol[0]?.uuid||null;orgSrc='orgs-list';}}catch(e2){} - } - if(!id){ - let pu=null; - try{pu=await(await fetch('/api/usage',h)).json();}catch(e3){} - window.chrome.webview.postMessage({email:e,orgId:null,planLabel,usage:(pu&&!pu.error?pu:null),debug:'no-org'}); - return; - } - const [u,ov,pp]=await Promise.all([ - fetch('/api/organizations/'+id+'/usage',h).then(r=>r.json()).catch(()=>null), - fetch('/api/organizations/'+id+'/overage_spend_limit',h).then(r=>r.ok?r.json():null).catch(()=>null), - fetch('/api/organizations/'+id+'/prepaid/credits',h).then(r=>r.ok?r.json():null).catch(()=>null) - ]); - window.chrome.webview.postMessage({email:e,orgId:id,planLabel,usage:u,overage:ov,prepaid:pp,debug:'src:'+orgSrc+'|plan:'+(planLabel||'none')}); - }catch(ex){window.chrome.webview.postMessage({error:String(ex)});}})()"; - - await Browser.CoreWebView2.ExecuteScriptAsync(script); - - // Wait up to 15 s for the script to post its message - var completed = await Task.WhenAny(tcs.Task, Task.Delay(15000)); - var json = completed == tcs.Task ? tcs.Task.Result : null; - - if (!string.IsNullOrEmpty(json)) - { - using var doc = JsonDocument.Parse(json); - var root = doc.RootElement; - - if (root.TryGetProperty("email", out var em) && em.ValueKind == JsonValueKind.String) - AppSettings.Default.Email = em.GetString() ?? ""; - - if (root.TryGetProperty("orgId", out var oi) && oi.ValueKind == JsonValueKind.String) - AppSettings.Default.OrgId = oi.GetString() ?? ""; - - if (root.TryGetProperty("usage", out var us) && us.ValueKind == JsonValueKind.Object) - AppSettings.Default.UsageJson = us.GetRawText(); - - if (root.TryGetProperty("planLabel", out var pl) && pl.ValueKind == JsonValueKind.String - && !string.IsNullOrEmpty(pl.GetString())) - AppSettings.Default.PlanLabel = pl.GetString()!; - - if (root.TryGetProperty("overage", out var ov) && ov.ValueKind == JsonValueKind.Object) - AppSettings.Default.OverageJson = ov.GetRawText(); - - if (root.TryGetProperty("prepaid", out var pp) && pp.ValueKind == JsonValueKind.Object) - AppSettings.Default.PrepaidJson = pp.GetRawText(); - - if (root.TryGetProperty("debug", out var dbg) && dbg.ValueKind == JsonValueKind.String) - AppSettings.Default.DebugInfo = dbg.GetString() ?? ""; - else if (root.TryGetProperty("error", out var err)) - AppSettings.Default.DebugInfo = "JS error: " + err.GetRawText(); - else - AppSettings.Default.DebugInfo = "timeout or empty message"; - - AppSettings.Default.Save(); - } - else - { - AppSettings.Default.DebugInfo = json == null ? "script timeout (15s)" : "empty message"; - AppSettings.Default.Save(); - } - } - catch (Exception ex) - { - AppSettings.Default.DebugInfo = "exception: " + ex.Message; - AppSettings.Default.Save(); - } - await Dispatcher.InvokeAsync(() => DialogResult = true); } }