Changed how the built-in extensions work and fixed tab loading

This commit is contained in:
AlastorFox committed 2026-10-01 22:36:17 +03:00
1 parent 79c1d88b58
commit 4d916207a4
3 files changed
+89 -11

No files matched your search

+6
View File
@@ -38,6 +38,7 @@ public sealed class Session
public static class SessionStore
{
private static readonly string SessionPath = Path.Combine(AppContext.BaseDirectory, "session.json");
private static readonly SemaphoreSlim SaveGate = new(1, 1);
private static readonly JsonSerializerOptions JsonOptions = new()
{
@@ -47,6 +48,7 @@ public static class SessionStore
public static async Task SaveAsync(IEnumerable<BrowserTab> tabs, int activeIndex)
{
await SaveGate.WaitAsync();
try
{
var snapshots = tabs.Select(t => new TabSnapshot
@@ -83,6 +85,10 @@ public static class SessionStore
{
System.Diagnostics.Debug.WriteLine($"[SessionStore] Save failed: {ex.Message}");
}
finally
{
SaveGate.Release();
}
}
public static async Task<Session?> LoadAsync()
+69 -8
View File
@@ -26,6 +26,7 @@ public sealed class TabManager : IAsyncDisposable
private bool _minimizedMode;
private bool _navigationInProgress;
private bool _switchInProgress;
private bool _restoringSession;
private readonly string _blockedElementsPath = Path.Combine(AppContext.BaseDirectory, "blocked-elements.json");
private readonly Dictionary<string, List<string>> _blockedElements;
@@ -43,6 +44,7 @@ public sealed class TabManager : IAsyncDisposable
public BrowserTab? ActiveTab { get; private set; }
public bool IsMinimizedMode => _minimizedMode;
public bool ExtensionsAvailable { get; private set; }
public bool SessionReady { get; private set; }
public CoreWebView2Environment Environment => _environment;
public WebView2 View => _view;
public ExtensionManager? ExtensionManager { get; private set; }
@@ -68,8 +70,18 @@ public sealed class TabManager : IAsyncDisposable
_view.CoreWebView2.IsDocumentPlayingAudioChanged += OnAudioStateChanged;
_view.CoreWebView2.HistoryChanged += OnHistoryChanged;
_view.CoreWebView2.WebMessageReceived += OnWebMessageReceived;
_restoringSession = true;
try
{
await RestoreSessionOrDefaultAsync();
}
finally
{
_restoringSession = false;
SessionReady = true;
}
await SaveSessionAsync();
}
public async Task SaveSessionAsync()
{
@@ -129,7 +141,9 @@ public sealed class TabManager : IAsyncDisposable
_audioOnly = tab.IsAudioOnly;
ActiveTabStateChanged?.Invoke(this, EventArgs.Empty);
_navigationInProgress = true;
await UpdateDocumentCreatedScriptAsync();
core.Navigate(tab.Address);
if (!_restoringSession) await SaveSessionAsync();
await Task.Yield();
}
finally { _switchInProgress = false; }
@@ -143,6 +157,7 @@ public sealed class TabManager : IAsyncDisposable
tab.Address = NormalizeAddress(address);
if (ActiveTab != tab) { await SwitchToTabAsync(tab); return; }
_navigationInProgress = true;
await UpdateDocumentCreatedScriptAsync();
core.Navigate(tab.Address);
}
@@ -276,13 +291,20 @@ public sealed class TabManager : IAsyncDisposable
public void GoForward() { var core = _view.CoreWebView2; if (core?.CanGoForward == true) core.GoForward(); }
public void Reload() { var core = _view.CoreWebView2; if (core is null) return; _navigationInProgress = true; core.Reload(); }
public void CloseTab(BrowserTab tab)
public async Task CloseTabAsync(BrowserTab tab)
{
var index = Tabs.IndexOf(tab);
if (index < 0) return;
Tabs.Remove(tab);
if (Tabs.Count == 0) { _ = AddTabAsync(); return; }
if (ActiveTab == tab) _ = SwitchToTabAsync(Tabs[Math.Min(index, Tabs.Count - 1)]);
_ = SaveSessionAsync();
if (Tabs.Count == 0)
{
await AddTabAsync();
return;
}
if (ActiveTab == tab)
await SwitchToTabAsync(Tabs[Math.Min(index, Tabs.Count - 1)]);
else
await SaveSessionAsync();
}
public async ValueTask DisposeAsync()
@@ -367,6 +389,47 @@ public sealed class TabManager : IAsyncDisposable
try { await _view.CoreWebView2.ExecuteScriptAsync(script); } catch { }
}
private async Task UpdateDocumentCreatedScriptAsync()
{
var core = _view.CoreWebView2;
if (core is null) return;
var host = GetCurrentHost();
var selectors = host is not null && _blockedElements.TryGetValue(host, out var savedSelectors)
? savedSelectors
: new List<string>();
var darkEnabled = ActiveTab?.IsDarkMode == true &&
Uri.TryCreate(ActiveTab.Address, UriKind.Absolute, out var address) &&
(address.Scheme == Uri.UriSchemeHttp || address.Scheme == Uri.UriSchemeHttps);
var brightness = (ActiveTab?.DarkBrightness ?? 0.72).ToString(System.Globalization.CultureInfo.InvariantCulture);
var contrast = (ActiveTab?.DarkContrast ?? 1.08).ToString(System.Globalization.CultureInfo.InvariantCulture);
var saturation = (ActiveTab?.DarkSaturation ?? 0.88).ToString(System.Globalization.CultureInfo.InvariantCulture);
var script = """
(()=>{
const selectors=__SELECTORS__, dark=__DARK__, brightness=__BRIGHTNESS__, contrast=__CONTRAST__, saturation=__SATURATION__;
const apply=()=>{
const root=document.documentElement;
if(!root){setTimeout(apply,0);return;}
let darkStyle=document.getElementById('fox-dark-mode');
if(!darkStyle){darkStyle=document.createElement('style');darkStyle.id='fox-dark-mode';root.appendChild(darkStyle);}
let blockedStyle=document.getElementById('fox-blocked-elements');
if(!blockedStyle){blockedStyle=document.createElement('style');blockedStyle.id='fox-blocked-elements';root.appendChild(blockedStyle);}
const darkCss=dark?'html{background:#111!important;color-scheme:dark!important}html.fox-dark-mode{background:#111!important;color-scheme:dark!important}html.fox-dark-mode body{background-color:#15171b!important;filter:brightness('+brightness+') contrast('+contrast+') saturate('+saturation+')!important}html.fox-dark-mode input,html.fox-dark-mode textarea,html.fox-dark-mode select,html.fox-dark-mode button{color-scheme:dark!important}':'';
darkStyle.textContent=darkCss;
blockedStyle.textContent=selectors.map(x=>x+'{display:none!important;}').join('');
if(dark) root.classList.add('fox-dark-mode'); else root.classList.remove('fox-dark-mode');
};
apply();
})();
"""
.Replace("__SELECTORS__", JsonSerializer.Serialize(selectors), StringComparison.Ordinal)
.Replace("__DARK__", darkEnabled ? "true" : "false", StringComparison.Ordinal)
.Replace("__BRIGHTNESS__", brightness, StringComparison.Ordinal)
.Replace("__CONTRAST__", contrast, StringComparison.Ordinal)
.Replace("__SATURATION__", saturation, StringComparison.Ordinal);
try { await core.AddScriptToExecuteOnDocumentCreatedAsync(script); } catch { }
}
private string? GetCurrentHost()
{
return Uri.TryCreate(ActiveTab?.Address, UriKind.Absolute, out var uri) &&
@@ -470,11 +533,9 @@ public sealed class TabManager : IAsyncDisposable
const root=document.documentElement;
if(!root)return;
root.classList.add('fox-dark-mode');
document.getElementById('fox-dark-mode')?.remove();
const s=document.createElement('style');
s.id='fox-dark-mode';
let s=document.getElementById('fox-dark-mode');
if(!s){s=document.createElement('style');s.id='fox-dark-mode';(document.head||root).appendChild(s);}
s.textContent=`html.fox-dark-mode{background:#111!important;color-scheme:dark!important}html.fox-dark-mode body{background-color:#15171b!important;filter:brightness(__BRIGHTNESS__) contrast(__CONTRAST__) saturate(__SATURATION__)!important}html.fox-dark-mode input,html.fox-dark-mode textarea,html.fox-dark-mode select,html.fox-dark-mode button{color-scheme:dark!important}`;
(document.head||root).appendChild(s);
})();
"""
: """
+14 -3
View File
@@ -19,6 +19,7 @@ public partial class MainWindow : Window
private TabManager? _tabManager;
private TrayIconManager? _tray;
private bool _allowClose;
private bool _closingAfterSessionSave;
private readonly DispatcherTimer _watchdogTimer = new() { Interval = TimeSpan.FromSeconds(30) };
private AudioSessionLabeler? _audioLabeler;
private bool _updatingDarkModeMenu;
@@ -149,6 +150,7 @@ public partial class MainWindow : Window
_tabManager.ActiveTabStateChanged += (_, _) => Dispatcher.Invoke(RefreshAddressBar);
DataContext = _tabManager;
await _tabManager.InitializeAsync();
TabStrip.SelectedItem = _tabManager.ActiveTab;
var iconPath = ResolveAppIconPath(_appSettings);
try
{
@@ -330,15 +332,16 @@ public partial class MainWindow : Window
private async void TabStrip_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.Source != TabStrip || TabStrip.SelectedItem is not BrowserTab tab || _tabManager is null) return;
if (e.Source != TabStrip || TabStrip.SelectedItem is not BrowserTab tab || _tabManager is null || !_tabManager.SessionReady) return;
AddressBox.Text = tab.Address;
await _tabManager.SwitchToTabAsync(tab);
RefreshAddressBar();
}
private void CloseTab_Click(object sender, RoutedEventArgs e)
private async void CloseTab_Click(object sender, RoutedEventArgs e)
{
if ((sender as System.Windows.Controls.Button)?.Tag is BrowserTab tab) _tabManager?.CloseTab(tab);
if ((sender as System.Windows.Controls.Button)?.Tag is BrowserTab tab && _tabManager is not null)
await _tabManager.CloseTabAsync(tab);
RefreshAddressBar();
}
@@ -360,6 +363,14 @@ public partial class MainWindow : Window
}
else
{
if (!_closingAfterSessionSave)
{
e.Cancel = true;
_closingAfterSessionSave = true;
if (_tabManager is not null) await _tabManager.SaveSessionAsync();
Close();
return;
}
_watchdogTimer.Stop();
_tray?.Dispose();
_audioLabeler?.Dispose();