using System; using System.Diagnostics; using System.Text; using System.Threading.Tasks; using System.Timers; using System.Windows; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.ViewModel; using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher { public partial class App : IDisposable, ISingleInstanceApp { public static PublicAPIInstance API { get; private set; } private const string Unique = "Flow.Launcher_Unique_Application_Mutex"; private static bool _disposed; private Settings _settings; private MainViewModel _mainVM; private SettingWindowViewModel _settingsVM; private readonly Updater _updater = new Updater(Flow.Launcher.Properties.Settings.Default.GithubRepo); private readonly Portable _portable = new Portable(); private readonly PinyinAlphabet _alphabet = new PinyinAlphabet(); private StringMatcher _stringMatcher; [STAThread] public static void Main() { if (SingleInstance.InitializeAsFirstInstance(Unique)) { using (var application = new App()) { application.InitializeComponent(); application.Run(); } } } private async void OnStartupAsync(object sender, StartupEventArgs e) { await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => { _portable.PreStartCleanUpAfterPortabilityUpdate(); Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------"); Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}"); RegisterAppDomainExceptions(); RegisterDispatcherUnhandledException(); ImageLoader.Initialize(); _settingsVM = new SettingWindowViewModel(_updater, _portable); _settings = _settingsVM.Settings; _alphabet.Initialize(_settings); _stringMatcher = new StringMatcher(_alphabet); StringMatcher.Instance = _stringMatcher; _stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision; PluginManager.LoadPlugins(_settings.PluginSettings); _mainVM = new MainViewModel(_settings); API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet); Http.API = API; Http.Proxy = _settings.Proxy; await PluginManager.InitializePluginsAsync(API); var window = new MainWindow(_settings, _mainVM); Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}"); Current.MainWindow = window; Current.MainWindow.Title = Constant.FlowLauncher; HotKeyMapper.Initialize(_mainVM); // happlebao todo temp fix for instance code logic // load plugin before change language, because plugin language also needs be changed InternationalizationManager.Instance.Settings = _settings; InternationalizationManager.Instance.ChangeLanguage(_settings.Language); // main windows needs initialized before theme change because of blur settigns ThemeManager.Instance.Settings = _settings; ThemeManager.Instance.ChangeTheme(_settings.Theme); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); RegisterExitEvents(); AutoStartup(); AutoUpdates(); API.SaveAppAllSettings(); Log.Info("|App.OnStartup|End Flow Launcher startup ---------------------------------------------------- "); }); } private void AutoStartup() { // we try to enable auto-startup on first launch, or reenable if it was removed // but the user still has the setting set if (_settings.StartFlowLauncherOnSystemStartup && !Helper.AutoStartup.IsEnabled) { try { Helper.AutoStartup.Enable(); } catch (Exception e) { // but if it fails (permissions, etc) then don't keep retrying // this also gives the user a visual indication in the Settings widget _settings.StartFlowLauncherOnSystemStartup = false; Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"), e.Message); } } } //[Conditional("RELEASE")] private void AutoUpdates() { Task.Run(async () => { if (_settings.AutoUpdates) { // check udpate every 5 hours var timer = new Timer(1000 * 60 * 60 * 5); timer.Elapsed += async (s, e) => { await _updater.UpdateAppAsync(API); }; timer.Start(); // check updates on startup await _updater.UpdateAppAsync(API); } }); } private void RegisterExitEvents() { AppDomain.CurrentDomain.ProcessExit += (s, e) => Dispose(); Current.Exit += (s, e) => Dispose(); Current.SessionEnding += (s, e) => Dispose(); } /// /// let exception throw as normal is better for Debug /// [Conditional("RELEASE")] private void RegisterDispatcherUnhandledException() { DispatcherUnhandledException += ErrorReporting.DispatcherUnhandledException; } /// /// let exception throw as normal is better for Debug /// [Conditional("RELEASE")] private static void RegisterAppDomainExceptions() { AppDomain.CurrentDomain.UnhandledException += ErrorReporting.UnhandledExceptionHandle; } public void Dispose() { // if sessionending is called, exit proverbially be called when log off / shutdown // but if sessionending is not called, exit won't be called when log off / shutdown if (!_disposed) { API.SaveAppAllSettings(); _disposed = true; } } public void OnSecondAppStarted() { Current.MainWindow.Show(); } } }