From 472a0f30b9baede7c19a08fbe8aa5c773f2e7d6e Mon Sep 17 00:00:00 2001 From: Michael Bucari-Tovo Date: Mon, 13 Feb 2023 15:47:25 -0700 Subject: [PATCH] Launch hangover from Libation app bundle for mac --- Documentation/InstallOnMac.md | 48 +++++++++---------- Source/DataLayer/DataLayer.csproj | 2 +- Source/FileManager/FileManager.csproj | 2 +- .../ViewModels/MainVM.Database.cs | 2 +- .../HangoverWinForms/HangoverWinForms.csproj | 1 + Source/LibationAvalonia/Program.cs | 20 +++++++- .../Views/MainWindow.Settings.cs | 16 ++++++- .../LibationAvalonia/Views/MainWindow.axaml | 2 + .../Views/ProductsDisplay.axaml.cs | 5 +- .../Configuration.LibationFiles.cs | 16 ++----- Source/LibationWinForms/Form1.Designer.cs | 13 +++++ Source/LibationWinForms/Form1.Settings.cs | 14 +++++- .../LibationWinForms/GridView/ProductsGrid.cs | 3 +- 13 files changed, 98 insertions(+), 46 deletions(-) diff --git a/Documentation/InstallOnMac.md b/Documentation/InstallOnMac.md index 0f8a805f..7c40b106 100644 --- a/Documentation/InstallOnMac.md +++ b/Documentation/InstallOnMac.md @@ -4,40 +4,38 @@ ...or just tell more friends. As long as I'm maintaining this software, it will remain **free** and **open source**. - # Run Libation on MacOS This walkthrough should get you up and running with Libation on your Mac. ## Install Libation -- Download latest MacOS zip to downloads folder -- Extract and rename folder to Libation -- in terminal type cd and then drag your folder of libation to terminal so it looks like `cd/users/YourName/Downloads/Libation` -- Type following commands +- Download the `Libation.app.x.x.x.tar.gz` file from the latest release and extract it. +- Move the extracted Libation app bundle to your applications folder. +- Open a terminal (Go > Utilities > Terminal) +- In the terminal type the following commands + - `sudo spctl --add --label "Libation" /Applications/Libation.app` (you'll be prompted to enter your password.) + - `sudo spctl --master-disable` +- Keep the terminal open and run the Libation app +- Go back to terminal and type the following command + - `sudo spctl --master-enable` +- Close the terminal -```console -chmod +x ./Libation -sudo spctl --add --label "Libation" ./Libation -./Libation +Libation is now registered with gatekeeper and will run even when gatekeeper is turned back on. + +## Running Hangover + +Libation comes with a recovery app called Hangover. You can start it by running this command: +```Console +open /Applications/Libation.app --args hangover ``` -## Trouble with Gatekeeper? +## Runnign LibationCli -If Gatekeeper is giving you trouble with Libation: - -Disable the block - -`sudo spctl --master-disable` - -Launch Libation and login, etc. and allow the rules to update then re-enable the block. - -`sudo spctl --master-enable` - -Once Gatekeeper reenabled, you can open Libation again without it being blocked. - -Thanks [joseph-holland](https://github.com/rmcrackan/Libation/issues/327#issuecomment-1268993349)! - -Report bugs to https://github.com/rmcrackan/Libation/issues +Libation comes with a command-line interface. Unfortunately, due to the way apps are sandboxed on mac, its use is somewhat limited. To open a new sandboxed terminal in LibationCli's directory, run the following command: +```Console +open /Applications/Libation.app --args cli +``` +To use LibationCli from an unsandboxed terminal, you must disable gatekeeper again and run the program directly at `/Applications/Libation.app/Contents/MacOS/LibationCli` ## Get Libation running on Mac diff --git a/Source/DataLayer/DataLayer.csproj b/Source/DataLayer/DataLayer.csproj index a0ab68c0..9f49643f 100644 --- a/Source/DataLayer/DataLayer.csproj +++ b/Source/DataLayer/DataLayer.csproj @@ -10,7 +10,7 @@ - + all diff --git a/Source/FileManager/FileManager.csproj b/Source/FileManager/FileManager.csproj index 94a6136f..29c0dff4 100644 --- a/Source/FileManager/FileManager.csproj +++ b/Source/FileManager/FileManager.csproj @@ -5,7 +5,7 @@ - + diff --git a/Source/HangoverAvalonia/ViewModels/MainVM.Database.cs b/Source/HangoverAvalonia/ViewModels/MainVM.Database.cs index 0e11d5b4..ee6ec3dd 100644 --- a/Source/HangoverAvalonia/ViewModels/MainVM.Database.cs +++ b/Source/HangoverAvalonia/ViewModels/MainVM.Database.cs @@ -17,7 +17,7 @@ namespace HangoverAvalonia.ViewModels private void Load_databaseVM() { - _tab = new(new(() => SqlQuery, s => SqlResults = s, s => SqlResults = s)); + _tab = new(new DatabaseTabCommands(() => SqlQuery, s => SqlResults += s, s => SqlResults = s)); _tab.LoadDatabaseFile(); if (_tab.DbFile is null) diff --git a/Source/HangoverWinForms/HangoverWinForms.csproj b/Source/HangoverWinForms/HangoverWinForms.csproj index 95ad37a2..dd37f2e3 100644 --- a/Source/HangoverWinForms/HangoverWinForms.csproj +++ b/Source/HangoverWinForms/HangoverWinForms.csproj @@ -4,6 +4,7 @@ WinExe net7.0-windows true + Hangover true hangover.ico enable diff --git a/Source/LibationAvalonia/Program.cs b/Source/LibationAvalonia/Program.cs index d820eb28..79efb369 100644 --- a/Source/LibationAvalonia/Program.cs +++ b/Source/LibationAvalonia/Program.cs @@ -2,6 +2,7 @@ using System; using System.Diagnostics; using System.IO; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using ApplicationServices; using Avalonia; @@ -13,8 +14,25 @@ namespace LibationAvalonia { static class Program { - static void Main() + static void Main(string[] args) { + if (Configuration.IsMacOs && args != null && args.Length != 0 && args[0] == "hangover") + { + //Launch the Hangover app within the sandbox + Assembly asm = Assembly.GetExecutingAssembly(); + string path = Path.GetDirectoryName(asm.Location); + Process.Start("Hangover" + (Configuration.IsWindows ? ".exe" : "")); + return; + } + if (Configuration.IsMacOs && args != null && args.Length != 0 && args[0] == "cli") + { + //Open a new Terminal in the sandbox + Assembly asm2 = Assembly.GetExecutingAssembly(); + string libationProgramFiles = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + Process.Start("/System/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal", $"\"{libationProgramFiles}\""); + return; + } + //***********************************************// // // // do not use Configuration before this line // diff --git a/Source/LibationAvalonia/Views/MainWindow.Settings.cs b/Source/LibationAvalonia/Views/MainWindow.Settings.cs index 296def23..add4ecfa 100644 --- a/Source/LibationAvalonia/Views/MainWindow.Settings.cs +++ b/Source/LibationAvalonia/Views/MainWindow.Settings.cs @@ -1,5 +1,7 @@ -using System; +using LibationFileManager; +using System; using System.Linq; +using System.Reflection; namespace LibationAvalonia.Views { @@ -16,5 +18,17 @@ namespace LibationAvalonia.Views public async void aboutToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => await MessageBox.Show($"Libation {AppScaffolding.LibationScaffolding.Variety}{Environment.NewLine}Version {AppScaffolding.LibationScaffolding.BuildVersion}", $"Libation v{AppScaffolding.LibationScaffolding.BuildVersion}"); + + public void launchHangoverToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) + { + try + { + System.Diagnostics.Process.Start("Hangover" + (Configuration.IsWindows ? ".exe" : "")); + } + catch(Exception ex) + { + Serilog.Log.Logger.Error(ex, "Failed to launch Hangover"); + } + } } } diff --git a/Source/LibationAvalonia/Views/MainWindow.axaml b/Source/LibationAvalonia/Views/MainWindow.axaml index 9fac32e2..6241135c 100644 --- a/Source/LibationAvalonia/Views/MainWindow.axaml +++ b/Source/LibationAvalonia/Views/MainWindow.axaml @@ -131,6 +131,8 @@ + + diff --git a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs index d407af76..3bdd2d6d 100644 --- a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs +++ b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using ApplicationServices; using Avalonia; using Avalonia.Controls; @@ -100,9 +101,9 @@ namespace LibationAvalonia.Views setNotDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.NotLiberated); var removeMenuItem = new MenuItem() { Header = "_Remove from library" }; - removeMenuItem.Click += (_, __) => LibraryCommands.RemoveBook(entry.AudibleProductId); + removeMenuItem.Click += async (_, __) => await Task.Run(() => LibraryCommands.RemoveBook(entry.AudibleProductId)); - var locateFileMenuItem = new MenuItem() { Header = "_Locate file..." }; + var locateFileMenuItem = new MenuItem() { Header = "_Locate file..." }; locateFileMenuItem.Click += async (_, __) => { try diff --git a/Source/LibationFileManager/Configuration.LibationFiles.cs b/Source/LibationFileManager/Configuration.LibationFiles.cs index 5a1443c2..7608f6c8 100644 --- a/Source/LibationFileManager/Configuration.LibationFiles.cs +++ b/Source/LibationFileManager/Configuration.LibationFiles.cs @@ -5,6 +5,7 @@ using FileManager; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using Serilog; +using Dinah.Core.Logging; namespace LibationFileManager { @@ -111,7 +112,7 @@ namespace LibationFileManager } catch(Exception ex) { - Log.Error(ex, $"Failed to create {appsettingsFile}"); + Log.Logger.TryLogError(ex, $"Failed to create {appsettingsFile}"); } } @@ -145,20 +146,11 @@ namespace LibationFileManager // now it's set in the file again but no settings have moved yet File.WriteAllText(AppsettingsJsonFile, endingContents); - tryLog(() => Log.Logger.Information("Libation files changed {@DebugInfo}", new { AppsettingsJsonFile, LIBATION_FILES_KEY, directory })); + Log.Logger.TryLogInformation("Libation files changed {@DebugInfo}", new { AppsettingsJsonFile, LIBATION_FILES_KEY, directory }); } catch (IOException ex) { - tryLog(() => Log.Logger.Error(ex, "Failed to change Libation files location {@DebugInfo}", new { AppsettingsJsonFile, LIBATION_FILES_KEY, directory })); - } - - static void tryLog(Action logAction) - { - try - { - logAction(); - } - catch { } + Log.Logger.TryLogError(ex, "Failed to change Libation files location {@DebugInfo}", new { AppsettingsJsonFile, LIBATION_FILES_KEY, directory }); } } } diff --git a/Source/LibationWinForms/Form1.Designer.cs b/Source/LibationWinForms/Form1.Designer.cs index 56e99a98..fc51a930 100644 --- a/Source/LibationWinForms/Form1.Designer.cs +++ b/Source/LibationWinForms/Form1.Designer.cs @@ -62,6 +62,8 @@ this.setDownloadedAutoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.launchHangoverToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.locateAudiobooksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.accountsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -378,6 +380,8 @@ this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.accountsToolStripMenuItem, this.basicSettingsToolStripMenuItem, + this.toolStripSeparator4, + this.launchHangoverToolStripMenuItem, this.toolStripSeparator2, this.aboutToolStripMenuItem}); this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; @@ -572,6 +576,13 @@ this.locateAudiobooksToolStripMenuItem.Text = "L&ocate Audiobooks"; this.locateAudiobooksToolStripMenuItem.Click += new System.EventHandler(this.locateAudiobooksToolStripMenuItem_Click); // + // launchHangoverToolStripMenuItem + // + this.launchHangoverToolStripMenuItem.Name = "launchHangoverToolStripMenuItem"; + this.launchHangoverToolStripMenuItem.Size = new System.Drawing.Size(247, 22); + this.launchHangoverToolStripMenuItem.Text = "Launch &Hangover"; + this.launchHangoverToolStripMenuItem.Click += new System.EventHandler(this.launchHangoverToolStripMenuItem_Click); + // // toolStripSeparator3 // this.toolStripSeparator3.Name = "toolStripSeparator3"; @@ -648,6 +659,8 @@ private System.Windows.Forms.ToolStripMenuItem removeToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; private System.Windows.Forms.ToolStripMenuItem locateAudiobooksToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripMenuItem launchHangoverToolStripMenuItem; private LibationWinForms.FormattableToolStripMenuItem liberateVisibleToolStripMenuItem_LiberateMenu; private System.Windows.Forms.SplitContainer splitContainer1; private LibationWinForms.ProcessQueue.ProcessQueueControl processBookQueue1; diff --git a/Source/LibationWinForms/Form1.Settings.cs b/Source/LibationWinForms/Form1.Settings.cs index 7b453008..5f6240d3 100644 --- a/Source/LibationWinForms/Form1.Settings.cs +++ b/Source/LibationWinForms/Form1.Settings.cs @@ -14,5 +14,17 @@ namespace LibationWinForms private void aboutToolStripMenuItem_Click(object sender, EventArgs e) => MessageBox.Show($"Libation {AppScaffolding.LibationScaffolding.Variety}{Environment.NewLine}Version {AppScaffolding.LibationScaffolding.BuildVersion}", $"Libation v{AppScaffolding.LibationScaffolding.BuildVersion}"); - } + + private void launchHangoverToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + System.Diagnostics.Process.Start("Hangover.exe"); + } + catch (Exception ex) + { + Serilog.Log.Logger.Error(ex, "Failed to launch Hangover"); + } + } + } } diff --git a/Source/LibationWinForms/GridView/ProductsGrid.cs b/Source/LibationWinForms/GridView/ProductsGrid.cs index 7096f2e7..e19fb4bc 100644 --- a/Source/LibationWinForms/GridView/ProductsGrid.cs +++ b/Source/LibationWinForms/GridView/ProductsGrid.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data; using System.Drawing; using System.Linq; +using System.Threading.Tasks; using System.Windows.Forms; using ApplicationServices; using DataLayer; @@ -152,7 +153,7 @@ namespace LibationWinForms.GridView setNotDownloadMenuItem.Click += (_, __) => entry.Book.UpdateBookStatus(LiberatedStatus.NotLiberated); var removeMenuItem = new ToolStripMenuItem() { Text = "&Remove from library" }; - removeMenuItem.Click += (_, __) => LibraryCommands.RemoveBook(entry.AudibleProductId); + removeMenuItem.Click += async (_, __) => await Task.Run(() => LibraryCommands.RemoveBook(entry.AudibleProductId)); var locateFileMenuItem = new ToolStripMenuItem() { Text = "&Locate file..." }; locateFileMenuItem.Click += (_, __) =>