BASE changed interface
This commit is contained in:
commit
256bb084c5
30 files changed
+2836
No files matched your search
@@ -0,0 +1,214 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Threading;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using FoxBrowser.Core;
|
||||
using FoxBrowser.Native;
|
||||
using FoxBrowser.UI;
|
||||
|
||||
namespace FoxBrowser;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private TabManager? _tabManager;
|
||||
private TrayIconManager? _tray;
|
||||
private bool _allowClose;
|
||||
private readonly DispatcherTimer _watchdogTimer = new() { Interval = TimeSpan.FromSeconds(30) };
|
||||
private AudioSessionLabeler? _audioLabeler;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
try
|
||||
{
|
||||
var icoPath = Path.Combine(AppContext.BaseDirectory, "FoxBrowser.ico");
|
||||
if (File.Exists(icoPath))
|
||||
Icon = new System.Windows.Media.Imaging.BitmapImage(new Uri(icoPath, UriKind.Absolute));
|
||||
}
|
||||
catch { }
|
||||
SourceInitialized += (_, _) => ApplyDarkTitleBar(true);
|
||||
Loaded += MainWindow_Loaded;
|
||||
}
|
||||
|
||||
private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_tray = new TrayIconManager(this, ExitApplication);
|
||||
var environmentFactory = new WebView2EnvironmentFactory();
|
||||
var recoveryMode = false;
|
||||
CoreWebView2Environment environment;
|
||||
try
|
||||
{
|
||||
environment = await environmentFactory.CreateAsync();
|
||||
}
|
||||
catch (Exception ex) when ((uint)ex.HResult == 0x8007139Fu)
|
||||
{
|
||||
// Another FoxBrowser/WebView2 process may hold the persistent profile lock.
|
||||
// Use a disposable recovery profile so the browser can still start.
|
||||
recoveryMode = true;
|
||||
var recoveryData = Path.Combine(
|
||||
Path.GetTempPath(), $"FoxBrowser_Recovery_{Environment.ProcessId}_{Guid.NewGuid():N}");
|
||||
Directory.CreateDirectory(recoveryData);
|
||||
environment = await environmentFactory.CreateAsync(recoveryData);
|
||||
}
|
||||
var startupNotice = environmentFactory.TakeStartupNotice();
|
||||
if (startupNotice is not null)
|
||||
System.Windows.MessageBox.Show(this, startupNotice, "FoxBrowser", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
_tabManager = new TabManager(WebViewHost, environment, !recoveryMode);
|
||||
_tabManager.ActiveTabStateChanged += (_, _) => Dispatcher.Invoke(RefreshAddressBar);
|
||||
DataContext = _tabManager;
|
||||
await _tabManager.InitializeAsync();
|
||||
var iconPath = Path.Combine(AppContext.BaseDirectory, "FoxBrowser.ico");
|
||||
try
|
||||
{
|
||||
_audioLabeler = new AudioSessionLabeler((uint)Process.GetCurrentProcess().Id, iconPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Audio labeling is optional; a missing endpoint must not break browsing.
|
||||
_audioLabeler = null;
|
||||
}
|
||||
PinnedExtensionStrip.ItemsSource = _tabManager.ExtensionManager?.PinnedExtensions;
|
||||
_watchdogTimer.Tick += async (_, _) => await _tabManager.SoftReloadIfNeededAsync();
|
||||
_watchdogTimer.Start();
|
||||
BrowserStatus.Visibility = Visibility.Collapsed;
|
||||
RefreshAddressBar();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
BrowserStatus.Text = $"WebView2 не запустився: {ex.Message}";
|
||||
BrowserStatus.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
private async void NewTab_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_tabManager is not null) await _tabManager.AddTabAsync();
|
||||
RefreshAddressBar();
|
||||
}
|
||||
|
||||
private async void AddressBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
|
||||
{
|
||||
if (e.Key != Key.Enter) return;
|
||||
await NavigateFromAddressBarAsync();
|
||||
Keyboard.ClearFocus();
|
||||
}
|
||||
|
||||
private async void Go_Click(object sender, RoutedEventArgs e) => await NavigateFromAddressBarAsync();
|
||||
|
||||
private async void AudioOnly_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_tabManager is null) return;
|
||||
await _tabManager.ToggleAudioOnlyAsync();
|
||||
TabStrip.Items.Refresh();
|
||||
}
|
||||
|
||||
private async Task NavigateFromAddressBarAsync()
|
||||
{
|
||||
if (_tabManager?.ActiveTab is null) return;
|
||||
await _tabManager.NavigateAsync(_tabManager.ActiveTab, AddressBox.Text);
|
||||
AddressBox.Text = _tabManager.ActiveTab.Address;
|
||||
}
|
||||
|
||||
private void Back_Click(object sender, RoutedEventArgs e) => _tabManager?.GoBack();
|
||||
private void Forward_Click(object sender, RoutedEventArgs e) => _tabManager?.GoForward();
|
||||
private void Reload_Click(object sender, RoutedEventArgs e) => _tabManager?.Reload();
|
||||
private void Extensions_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_tabManager?.ExtensionManager is null) return;
|
||||
var window = new ExtensionsSettingsWindow(
|
||||
_tabManager.ExtensionManager,
|
||||
_tabManager.Environment,
|
||||
() => _tabManager.OpenUrlAsync("https://chromewebstore.google.com/category/extensions"),
|
||||
_tabManager.ExtensionsAvailable)
|
||||
{ Owner = this };
|
||||
window.ShowDialog();
|
||||
}
|
||||
|
||||
private void PinnedExtension_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_tabManager?.ExtensionManager is null || sender is not System.Windows.Controls.Button button || button.DataContext is not PinnedExtensionItem item)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(item.PopupPage))
|
||||
{
|
||||
Extensions_Click(sender, e);
|
||||
return;
|
||||
}
|
||||
|
||||
var screenPositionWpf = button.PointToScreen(new System.Windows.Point(0, button.ActualHeight));
|
||||
var screenPosition = new System.Drawing.Point((int)screenPositionWpf.X, (int)screenPositionWpf.Y);
|
||||
|
||||
var popup = new ExtensionPopupWindow(_tabManager.Environment, item.Extension.Id, item.PopupPage, screenPosition)
|
||||
{
|
||||
Owner = this
|
||||
};
|
||||
popup.Show();
|
||||
}
|
||||
|
||||
private async void TabStrip_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Source != TabStrip || TabStrip.SelectedItem is not BrowserTab tab || _tabManager is null) return;
|
||||
AddressBox.Text = tab.Address;
|
||||
await _tabManager.SwitchToTabAsync(tab);
|
||||
RefreshAddressBar();
|
||||
}
|
||||
|
||||
private void CloseTab_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if ((sender as System.Windows.Controls.Button)?.Tag is BrowserTab tab) _tabManager?.CloseTab(tab);
|
||||
RefreshAddressBar();
|
||||
}
|
||||
|
||||
private async void Window_StateChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (_tabManager is null) return;
|
||||
var minimized = WindowState == WindowState.Minimized;
|
||||
if (minimized) _tray?.MinimizeToTray();
|
||||
await _tabManager.SetMinimizedModeAsync(minimized);
|
||||
}
|
||||
|
||||
private async void Window_Closing(object? sender, CancelEventArgs e)
|
||||
{
|
||||
if (!_allowClose)
|
||||
{
|
||||
e.Cancel = true;
|
||||
_tray?.MinimizeToTray();
|
||||
if (_tabManager is not null) await _tabManager.SetMinimizedModeAsync(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_watchdogTimer.Stop();
|
||||
_tray?.Dispose();
|
||||
_audioLabeler?.Dispose();
|
||||
if (_tabManager is not null) await _tabManager.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private void ExitApplication()
|
||||
{
|
||||
_allowClose = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void ApplyDarkTitleBar(bool enabled)
|
||||
{
|
||||
var hwnd = new WindowInteropHelper(this).Handle;
|
||||
Win32Interop.ApplyDarkTitleBar(hwnd, enabled);
|
||||
}
|
||||
|
||||
private void RefreshAddressBar()
|
||||
{
|
||||
if (_tabManager?.ActiveTab is not null)
|
||||
{
|
||||
if (!ReferenceEquals(TabStrip.SelectedItem, _tabManager.ActiveTab)) TabStrip.SelectedItem = _tabManager.ActiveTab;
|
||||
AddressBox.Text = _tabManager.ActiveTab.Address;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user