2017-10-03 03:28:56 +02:00
using ElectronNET.API.Entities ;
using Newtonsoft.Json ;
using Newtonsoft.Json.Linq ;
using Newtonsoft.Json.Serialization ;
using System ;
2020-05-17 21:40:20 -04:00
using System.Runtime.InteropServices ;
2017-11-10 01:48:06 +01:00
using System.Threading ;
2017-10-12 02:24:27 +02:00
using System.Threading.Tasks ;
2020-05-31 03:09:54 +02:00
using ElectronNET.API.Extensions ;
2017-10-03 03:28:56 +02:00
namespace ElectronNET.API
{
2017-10-24 21:43:27 +02:00
/// <summary>
/// Control your application's event lifecycle.
/// </summary>
2017-10-14 17:58:16 +02:00
public sealed class App
2017-10-03 03:28:56 +02:00
{
2017-10-14 19:57:49 +02:00
/// <summary>
/// Emitted when all windows have been closed.
2020-05-31 03:09:54 +02:00
/// <para/>
/// If you do not subscribe to this event and all windows are closed, the default behavior is to quit
/// the app; however, if you subscribe, you control whether the app quits or not.If the user pressed
/// Cmd + Q, or the developer called <see cref="Quit"/>, Electron will first try to close all the windows
/// and then emit the <see cref="WillQuit"/> event, and in this case the <see cref="WindowAllClosed"/> event
/// would not be emitted.
2017-10-14 19:57:49 +02:00
/// </summary>
public event Action WindowAllClosed
{
add
{
if ( _windowAllClosed = = null )
{
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . On ( "app-window-all-closed" + GetHashCode ( ) , ( ) = >
2017-10-14 19:57:49 +02:00
{
2020-05-17 21:40:20 -04:00
if ( ! Electron . WindowManager . IsQuitOnWindowAllClosed | | RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) )
2017-11-10 01:48:06 +01:00
{
_windowAllClosed ( ) ;
}
2017-10-14 19:57:49 +02:00
} ) ;
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . Emit ( "register-app-window-all-closed-event" , GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
_windowAllClosed + = value ;
}
remove
{
_windowAllClosed - = value ;
2017-10-25 21:28:43 +02:00
if ( _windowAllClosed = = null )
BridgeConnector . Socket . Off ( "app-window-all-closed" + GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
}
private event Action _windowAllClosed ;
/// <summary>
/// Emitted before the application starts closing its windows.
2020-05-31 03:09:54 +02:00
/// <para/>
/// Note: If application quit was initiated by <see cref="AutoUpdater.QuitAndInstall"/> then <see cref="BeforeQuit"/>
/// is emitted after emitting close event on all windows and closing them.
/// <para/>
/// Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.
2017-10-14 19:57:49 +02:00
/// </summary>
2017-11-10 03:11:13 +01:00
public event Func < QuitEventArgs , Task > BeforeQuit
2017-10-14 19:57:49 +02:00
{
add
{
if ( _beforeQuit = = null )
{
2017-11-10 01:48:06 +01:00
BridgeConnector . Socket . On ( "app-before-quit" + GetHashCode ( ) , async ( ) = >
2017-10-14 19:57:49 +02:00
{
2017-11-10 03:11:13 +01:00
await _beforeQuit ( new QuitEventArgs ( ) ) ;
2017-11-10 01:48:06 +01:00
2017-11-10 03:11:13 +01:00
if ( _preventQuit )
2017-11-10 01:48:06 +01:00
{
2017-11-10 03:11:13 +01:00
_preventQuit = false ;
2017-11-10 01:48:06 +01:00
}
2017-11-10 03:11:13 +01:00
else
2017-11-10 01:48:06 +01:00
{
2017-11-10 03:11:13 +01:00
if ( _willQuit = = null & & _quitting = = null )
2017-11-10 01:48:06 +01:00
{
Exit ( ) ;
2017-11-10 03:11:13 +01:00
}
else if ( _willQuit ! = null )
{
await _willQuit ( new QuitEventArgs ( ) ) ;
if ( _preventQuit )
{
_preventQuit = false ;
}
else
{
if ( _quitting = = null )
{
Exit ( ) ;
}
else
{
await _quitting ( ) ;
Exit ( ) ;
}
}
}
else if ( _quitting ! = null )
2017-11-10 01:48:06 +01:00
{
await _quitting ( ) ;
Exit ( ) ;
}
}
2017-10-14 19:57:49 +02:00
} ) ;
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . Emit ( "register-app-before-quit-event" , GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
_beforeQuit + = value ;
}
remove
{
_beforeQuit - = value ;
2017-10-25 21:28:43 +02:00
if ( _beforeQuit = = null )
BridgeConnector . Socket . Off ( "app-before-quit" + GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
}
2017-11-10 03:11:13 +01:00
private event Func < QuitEventArgs , Task > _beforeQuit ;
2017-10-14 19:57:49 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Emitted when all windows have been closed and the application will quit.
/// <para/>
/// See the description of the <see cref="WindowAllClosed"/> event for the differences between the <see cref="WillQuit"/>
/// and <see cref="WindowAllClosed"/> events.
/// <para/>
/// Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.
2017-10-14 19:57:49 +02:00
/// </summary>
2017-11-10 03:11:13 +01:00
public event Func < QuitEventArgs , Task > WillQuit
2017-10-14 19:57:49 +02:00
{
add
{
if ( _willQuit = = null )
{
2017-11-10 01:48:06 +01:00
BridgeConnector . Socket . On ( "app-will-quit" + GetHashCode ( ) , async ( ) = >
2017-10-14 19:57:49 +02:00
{
2017-11-10 03:11:13 +01:00
await _willQuit ( new QuitEventArgs ( ) ) ;
2017-11-10 01:48:06 +01:00
2017-11-10 03:11:13 +01:00
if ( _preventQuit )
2017-11-10 01:48:06 +01:00
{
2017-11-10 03:11:13 +01:00
_preventQuit = false ;
2017-11-10 01:48:06 +01:00
}
else
{
2017-11-10 03:11:13 +01:00
if ( _quitting = = null )
{
Exit ( ) ;
}
else
{
await _quitting ( ) ;
Exit ( ) ;
}
2017-11-10 01:48:06 +01:00
}
2017-10-14 19:57:49 +02:00
} ) ;
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . Emit ( "register-app-will-quit-event" , GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
_willQuit + = value ;
}
remove
{
_willQuit - = value ;
2017-10-25 21:28:43 +02:00
if ( _willQuit = = null )
BridgeConnector . Socket . Off ( "app-will-quit" + GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
}
2017-11-10 03:11:13 +01:00
private event Func < QuitEventArgs , Task > _willQuit ;
2017-10-14 19:57:49 +02:00
/// <summary>
/// Emitted when the application is quitting.
2020-05-31 03:09:54 +02:00
/// <para/>
/// Note: On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.
2017-10-14 19:57:49 +02:00
/// </summary>
2017-11-10 01:48:06 +01:00
public event Func < Task > Quitting
2017-10-14 19:57:49 +02:00
{
add
{
if ( _quitting = = null )
{
2017-11-10 01:48:06 +01:00
BridgeConnector . Socket . On ( "app-will-quit" + GetHashCode ( ) + "quitting" , async ( ) = >
2017-10-14 19:57:49 +02:00
{
2017-11-10 01:48:06 +01:00
if ( _willQuit = = null )
{
await _quitting ( ) ;
Exit ( ) ;
}
2017-10-14 19:57:49 +02:00
} ) ;
2017-11-10 01:48:06 +01:00
BridgeConnector . Socket . Emit ( "register-app-will-quit-event" , GetHashCode ( ) + "quitting" ) ;
2017-10-14 19:57:49 +02:00
}
_quitting + = value ;
}
remove
{
_quitting - = value ;
2017-10-25 21:28:43 +02:00
if ( _quitting = = null )
2017-11-10 01:48:06 +01:00
BridgeConnector . Socket . Off ( "app-will-quit" + GetHashCode ( ) + "quitting" ) ;
2017-10-14 19:57:49 +02:00
}
}
2017-11-10 01:48:06 +01:00
private event Func < Task > _quitting ;
2017-10-14 19:57:49 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Emitted when a <see cref="BrowserWindow"/> blurred.
2017-10-14 19:57:49 +02:00
/// </summary>
public event Action BrowserWindowBlur
{
add
{
if ( _browserWindowBlur = = null )
{
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . On ( "app-browser-window-blur" + GetHashCode ( ) , ( ) = >
2017-10-14 19:57:49 +02:00
{
_browserWindowBlur ( ) ;
} ) ;
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . Emit ( "register-app-browser-window-blur-event" , GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
_browserWindowBlur + = value ;
}
remove
{
_browserWindowBlur - = value ;
2017-10-25 21:28:43 +02:00
if ( _browserWindowBlur = = null )
BridgeConnector . Socket . Off ( "app-browser-window-blur" + GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
}
private event Action _browserWindowBlur ;
/// <summary>
2020-05-31 03:09:54 +02:00
/// Emitted when a <see cref="BrowserWindow"/> gets focused.
2017-10-14 19:57:49 +02:00
/// </summary>
public event Action BrowserWindowFocus
{
add
{
if ( _browserWindowFocus = = null )
{
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . On ( "app-browser-window-focus" + GetHashCode ( ) , ( ) = >
2017-10-14 19:57:49 +02:00
{
_browserWindowFocus ( ) ;
} ) ;
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . Emit ( "register-app-browser-window-focus-event" , GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
_browserWindowFocus + = value ;
}
remove
{
_browserWindowFocus - = value ;
2017-10-25 21:28:43 +02:00
if ( _browserWindowFocus = = null )
BridgeConnector . Socket . Off ( "app-browser-window-focus" + GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
}
private event Action _browserWindowFocus ;
/// <summary>
2020-05-31 03:09:54 +02:00
/// Emitted when a new <see cref="BrowserWindow"/> is created.
2017-10-14 19:57:49 +02:00
/// </summary>
public event Action BrowserWindowCreated
{
add
{
if ( _browserWindowCreated = = null )
{
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . On ( "app-browser-window-created" + GetHashCode ( ) , ( ) = >
2017-10-14 19:57:49 +02:00
{
_browserWindowCreated ( ) ;
} ) ;
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . Emit ( "register-app-browser-window-created-event" , GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
_browserWindowCreated + = value ;
}
remove
{
_browserWindowCreated - = value ;
2017-10-25 21:28:43 +02:00
if ( _browserWindowCreated = = null )
BridgeConnector . Socket . Off ( "app-browser-window-created" + GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
}
private event Action _browserWindowCreated ;
/// <summary>
2020-05-31 03:09:54 +02:00
/// Emitted when a new <see cref="WebContents"/> is created.
2017-10-14 19:57:49 +02:00
/// </summary>
public event Action WebContentsCreated
{
add
{
if ( _webContentsCreated = = null )
{
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . On ( "app-web-contents-created" + GetHashCode ( ) , ( ) = >
2017-10-14 19:57:49 +02:00
{
_webContentsCreated ( ) ;
} ) ;
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . Emit ( "register-app-web-contents-created-event" , GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
_webContentsCreated + = value ;
}
remove
{
_webContentsCreated - = value ;
2017-10-25 21:28:43 +02:00
if ( _webContentsCreated = = null )
BridgeConnector . Socket . Off ( "app-web-contents-created" + GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
}
private event Action _webContentsCreated ;
/// <summary>
2020-05-31 03:09:54 +02:00
/// Emitted when Chrome’ s accessibility support changes. This event fires when assistive technologies, such as
/// screen readers, are enabled or disabled. See https://www.chromium.org/developers/design-documents/accessibility for more details.
2017-10-14 19:57:49 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <returns><see langword="true"/> when Chrome's accessibility support is enabled, <see langword="false"/> otherwise.</returns>
2017-10-14 19:57:49 +02:00
public event Action < bool > AccessibilitySupportChanged
{
add
{
if ( _accessibilitySupportChanged = = null )
{
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . On ( "app-accessibility-support-changed" + GetHashCode ( ) , ( state ) = >
2017-10-14 19:57:49 +02:00
{
_accessibilitySupportChanged ( ( bool ) state ) ;
} ) ;
2017-10-25 21:28:43 +02:00
BridgeConnector . Socket . Emit ( "register-app-accessibility-support-changed-event" , GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
_accessibilitySupportChanged + = value ;
}
remove
{
_accessibilitySupportChanged - = value ;
2017-10-25 21:28:43 +02:00
if ( _accessibilitySupportChanged = = null )
BridgeConnector . Socket . Off ( "app-accessibility-support-changed" + GetHashCode ( ) ) ;
2017-10-14 19:57:49 +02:00
}
}
private event Action < bool > _accessibilitySupportChanged ;
2017-10-12 02:24:27 +02:00
2020-05-24 18:50:35 +02:00
/// <summary>
/// Emitted when the application has finished basic startup.
/// </summary>
2020-05-24 22:00:32 +02:00
public event Action Ready
{
add
{
if ( IsReady )
{
value ( ) ;
}
_ready + = value ;
}
remove
{
_ready - = value ;
}
}
private event Action _ready ;
2020-05-24 18:50:35 +02:00
2020-05-24 02:51:34 +02:00
/// <summary>
/// Application host fully started.
/// </summary>
2020-05-24 18:50:35 +02:00
public bool IsReady
{
get { return _isReady ; }
internal set
{
_isReady = value ;
if ( value )
{
2020-05-24 22:00:32 +02:00
_ready ? . Invoke ( ) ;
2020-05-24 18:50:35 +02:00
}
}
}
private bool _isReady = false ;
2020-05-24 02:51:34 +02:00
2020-04-18 17:15:58 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// A <see cref="string"/> property that indicates the current application's name, which is the name in the
/// application's package.json file.
2020-04-18 17:15:58 +02:00
///
2020-05-31 03:09:54 +02:00
/// Usually the name field of package.json is a short lowercase name, according to the npm modules spec. You
/// should usually also specify a productName field, which is your application's full capitalized name, and
/// which will be preferred over name by Electron.
2020-04-18 17:15:58 +02:00
/// </summary>
public string Name
2020-07-08 11:16:00 +02:00
{
[Obsolete("Use the asynchronous version NameAsync instead")]
get
{
return AsyncHelper . RunSync ( async ( ) = > await NameAsync ) ;
}
set
{
BridgeConnector . Socket . Emit ( "appSetName" , value ) ;
}
}
/// <summary>
/// A <see cref="string"/> property that indicates the current application's name, which is the name in the
/// application's package.json file.
///
/// Usually the name field of package.json is a short lowercase name, according to the npm modules spec. You
/// should usually also specify a productName field, which is your application's full capitalized name, and
/// which will be preferred over name by Electron.
/// </summary>
public Task < string > NameAsync
2020-04-18 17:15:58 +02:00
{
get
{
return Task . Run < string > ( ( ) = >
{
var taskCompletionSource = new TaskCompletionSource < string > ( ) ;
BridgeConnector . Socket . On ( "appGetNameCompleted" , ( result ) = >
{
BridgeConnector . Socket . Off ( "appGetNameCompleted" ) ;
taskCompletionSource . SetResult ( ( string ) result ) ;
} ) ;
BridgeConnector . Socket . Emit ( "appGetName" ) ;
return taskCompletionSource . Task ;
2020-07-08 11:16:00 +02:00
} ) ;
2020-04-18 17:15:58 +02:00
}
}
2020-07-08 11:16:00 +02:00
/// <summary>
///
/// </summary>
/// <returns></returns>
public Task < string > GetName ( )
{
var taskCompletionSource = new TaskCompletionSource < string > ( ) ;
BridgeConnector . Socket . On ( "appGetNameCompleted" , ( result ) = >
{
BridgeConnector . Socket . Off ( "appGetNameCompleted" ) ;
taskCompletionSource . SetResult ( ( string ) result ) ;
} ) ;
BridgeConnector . Socket . Emit ( "appGetName" ) ;
return taskCompletionSource . Task ;
}
2019-11-30 01:30:22 +01:00
internal App ( )
{
CommandLine = new CommandLine ( ) ;
}
2017-10-03 03:28:56 +02:00
2017-10-15 06:03:48 +02:00
internal static App Instance
2017-10-03 03:28:56 +02:00
{
2017-10-14 17:58:16 +02:00
get
2017-10-03 03:28:56 +02:00
{
2017-10-14 17:58:16 +02:00
if ( _app = = null )
{
2017-11-04 00:16:14 +01:00
lock ( _syncRoot )
{
if ( _app = = null )
{
_app = new App ( ) ;
}
}
2017-10-14 17:58:16 +02:00
}
2017-10-03 03:28:56 +02:00
2017-10-14 17:58:16 +02:00
return _app ;
}
}
2017-10-03 03:28:56 +02:00
2017-10-14 19:57:49 +02:00
private static App _app ;
2019-05-18 02:00:56 +02:00
private static object _syncRoot = new object ( ) ;
2017-10-14 19:57:49 +02:00
2020-05-31 03:09:54 +02:00
private readonly JsonSerializer _jsonSerializer = new JsonSerializer ( )
2017-10-14 17:58:16 +02:00
{
ContractResolver = new CamelCasePropertyNamesContractResolver ( )
} ;
2017-10-03 03:28:56 +02:00
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Try to close all windows. The <see cref="BeforeQuit"/> event will be emitted first. If all windows are successfully
/// closed, the <see cref="WillQuit"/> event will be emitted and by default the application will terminate. This method
/// guarantees that all beforeunload and unload event handlers are correctly executed. It is possible
/// that a window cancels the quitting by returning <see langword="false"/> in the beforeunload event handler.
2017-10-14 14:41:11 +02:00
/// </summary>
2017-10-14 17:58:16 +02:00
public void Quit ( )
2017-10-12 02:24:27 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appQuit" ) ;
2017-10-12 02:24:27 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// All windows will be closed immediately without asking user and the <see cref="BeforeQuit"/> and <see cref="WillQuit"/>
/// events will not be emitted.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="exitCode">Exits immediately with exitCode. exitCode defaults to 0.</param>
2017-10-14 17:58:16 +02:00
public void Exit ( int exitCode = 0 )
2017-10-12 02:24:27 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appExit" , exitCode ) ;
2017-10-12 02:24:27 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Relaunches the app when current instance exits. By default the new instance will use the same working directory
/// and command line arguments with current instance.
/// <para/>
/// Note that this method does not quit the app when executed, you have to call <see cref="Quit"/> or <see cref="Exit"/>
/// after calling <see cref="Relaunch()"/> to make the app restart.
/// <para/>
/// When <see cref="Relaunch()"/> is called for multiple times, multiple instances will be started after current instance
/// exited.
2017-10-14 14:41:11 +02:00
/// </summary>
2017-10-14 17:58:16 +02:00
public void Relaunch ( )
2017-10-12 02:24:27 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appRelaunch" ) ;
2017-10-12 02:24:27 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Relaunches the app when current instance exits. By default the new instance will use the same working directory
/// and command line arguments with current instance. When <see cref="RelaunchOptions.Args"/> is specified, the
/// <see cref="RelaunchOptions.Args"/> will be passed as command line arguments instead. When <see cref="RelaunchOptions.ExecPath"/>
/// is specified, the <see cref="RelaunchOptions.ExecPath"/> will be executed for relaunch instead of current app.
/// <para/>
/// Note that this method does not quit the app when executed, you have to call <see cref="Quit"/> or <see cref="Exit"/>
/// after calling <see cref="Relaunch()"/> to make the app restart.
/// <para/>
/// When <see cref="Relaunch()"/> is called for multiple times, multiple instances will be started after current instance
/// exited.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="relaunchOptions">Options for the relaunch.</param>
2017-10-14 17:58:16 +02:00
public void Relaunch ( RelaunchOptions relaunchOptions )
2017-10-12 02:24:27 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appRelaunch" , JObject . FromObject ( relaunchOptions , _jsonSerializer ) ) ;
2017-10-12 02:24:27 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// On Linux, focuses on the first visible window. On macOS, makes the application the active app. On Windows, focuses
/// on the application's first window.
2017-10-14 14:41:11 +02:00
/// </summary>
2017-10-14 17:58:16 +02:00
public void Focus ( )
2017-10-12 02:24:27 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appFocus" ) ;
2017-10-12 02:24:27 +02:00
}
2020-05-31 03:09:54 +02:00
/// <summary>
/// On Linux, focuses on the first visible window. On macOS, makes the application the active app. On Windows, focuses
/// on the application's first window.
/// <para/>
/// You should seek to use the <see cref="FocusOptions.Steal"/> option as sparingly as possible.
/// </summary>
public void Focus ( FocusOptions focusOptions )
{
BridgeConnector . Socket . Emit ( "appFocus" , JObject . FromObject ( focusOptions , _jsonSerializer ) ) ;
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// Hides all application windows without minimizing them.
/// </summary>
2017-10-14 17:58:16 +02:00
public void Hide ( )
2017-10-12 02:24:27 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appHide" ) ;
2017-10-12 02:24:27 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// Shows application windows after they were hidden. Does not automatically focus them.
/// </summary>
2017-10-14 17:58:16 +02:00
public void Show ( )
2017-10-12 02:24:27 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appShow" ) ;
2017-10-12 02:24:27 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// The current application directory.
/// </summary>
2020-05-31 03:09:54 +02:00
public async Task < string > GetAppPathAsync ( CancellationToken cancellationToken = default )
2017-10-12 02:24:27 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-12 02:24:27 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < string > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-12 02:24:27 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appGetAppPathCompleted" , ( path ) = >
{
BridgeConnector . Socket . Off ( "appGetAppPathCompleted" ) ;
taskCompletionSource . SetResult ( path . ToString ( ) ) ;
} ) ;
2017-10-12 02:24:27 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appGetAppPath" ) ;
2017-10-12 02:24:27 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-12 02:24:27 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Sets or creates a directory your app's logs which can then be manipulated with <see cref="GetPathAsync"/>
/// or <see cref="SetPath"/>.
/// <para/>
/// Calling <see cref="SetAppLogsPath"/> without a path parameter will result in this directory being set to
/// ~/Library/Logs/YourAppName on macOS, and inside the userData directory on Linux and Windows.
/// </summary>
/// <param name="path">A custom path for your logs. Must be absolute.</param>
public void SetAppLogsPath ( string path )
{
BridgeConnector . Socket . Emit ( "appSetAppLogsPath" , path ) ;
}
/// <summary>
/// The path to a special directory. If <see cref="GetPathAsync"/> is called without called
/// <see cref="SetAppLogsPath"/> being called first, a default directory will be created equivalent
/// to calling <see cref="SetAppLogsPath"/> without a path parameter.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="pathName">Special directory.</param>
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>A path to a special directory or file associated with name.</returns>
2020-05-31 03:09:54 +02:00
public async Task < string > GetPathAsync ( PathName pathName , CancellationToken cancellationToken = default )
2017-10-12 02:24:27 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-12 02:24:27 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < string > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
{
BridgeConnector . Socket . On ( "appGetPathCompleted" , ( path ) = >
{
BridgeConnector . Socket . Off ( "appGetPathCompleted" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
taskCompletionSource . SetResult ( path . ToString ( ) ) ;
} ) ;
2017-10-12 02:24:27 +02:00
2020-05-31 03:09:54 +02:00
BridgeConnector . Socket . Emit ( "appGetPath" , pathName . GetDescription ( ) ) ;
2017-10-12 02:24:27 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-12 02:24:27 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Overrides the path to a special directory or file associated with name. If the path specifies a directory
/// that does not exist, an Error is thrown. In that case, the directory should be created with fs.mkdirSync or similar.
/// <para/>
/// You can only override paths of a name defined in <see cref="GetPathAsync"/>.
/// <para/>
/// By default, web pages' cookies and caches will be stored under the <see cref="PathName.UserData"/> directory. If you
/// want to change this location, you have to override the <see cref="PathName.UserData"/> path before the <see cref="Ready"/>
/// event of the <see cref="App"/> module is emitted.
/// <param name="name">Special directory.</param>
/// <param name="path">New path to a special directory.</param>
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
public void SetPath ( PathName name , string path )
2017-10-14 00:06:58 +02:00
{
2020-05-31 03:09:54 +02:00
BridgeConnector . Socket . Emit ( "appSetPath" , name . GetDescription ( ) , path ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// The version of the loaded application. If no version is found in the application’ s package.json file,
2017-10-14 14:41:11 +02:00
/// the version of the current bundle or executable is returned.
/// </summary>
2020-05-31 03:09:54 +02:00
/// <returns>The version of the loaded application.</returns>
public async Task < string > GetVersionAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < string > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appGetVersionCompleted" , ( version ) = >
{
BridgeConnector . Socket . Off ( "appGetVersionCompleted" ) ;
taskCompletionSource . SetResult ( version . ToString ( ) ) ;
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appGetVersion" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// The current application locale. Possible return values are documented <see href="https://www.electronjs.org/docs/api/locales">here</see>.
/// <para/>
/// Note: When distributing your packaged app, you have to also ship the locales folder.
/// <para/>
/// Note: On Windows, you have to call it after the <see cref="Ready"/> events gets emitted.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <returns>The current application locale.</returns>
public async Task < string > GetLocaleAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < string > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appGetLocaleCompleted" , ( local ) = >
{
BridgeConnector . Socket . Off ( "appGetLocaleCompleted" ) ;
taskCompletionSource . SetResult ( local . ToString ( ) ) ;
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appGetLocale" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Adds path to the recent documents list. This list is managed by the OS. On Windows you can visit the
/// list from the task bar, and on macOS you can visit it from dock menu.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="path">Path to add.</param>
2017-10-14 17:58:16 +02:00
public void AddRecentDocument ( string path )
2017-10-14 00:06:58 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appAddRecentDocument" , path ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// Clears the recent documents list.
/// </summary>
2017-10-14 17:58:16 +02:00
public void ClearRecentDocuments ( )
2017-10-14 00:06:58 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appClearRecentDocuments" ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Sets the current executable as the default handler for a protocol (aka URI scheme). It allows you to
/// integrate your app deeper into the operating system. Once registered, all links with your-protocol://
/// will be opened with the current executable. The whole link, including protocol, will be passed to your
/// application as a parameter.
/// <para/>
/// Note: On macOS, you can only register protocols that have been added to your app's info.plist, which
/// cannot be modified at runtime. However, you can change the file during build time via
/// <see href="https://www.electronforge.io/">Electron Forge</see>,
/// <see href="https://github.com/electron/electron-packager">Electron Packager</see>, or by editing info.plist
/// with a text editor. Please refer to
/// <see href="https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115">Apple's documentation</see>
/// for details.
/// <para/>
/// Note: In a Windows Store environment (when packaged as an appx) this API will return true for all calls but
/// the registry key it sets won't be accessible by other applications. In order to register your Windows Store
/// application as a default protocol handler you <see href="https://docs.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/element-uap-protocol">must declare the protocol in your manifest</see>.
/// <para/>
/// The API uses the Windows Registry and LSSetDefaultHandlerForURLScheme internally.
/// </summary>
/// <param name="protocol">
/// The name of your protocol, without ://. For example, if you want your app to handle electron:// links,
2017-10-14 14:41:11 +02:00
/// call this method with electron as the parameter.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>Whether the call succeeded.</returns>
2020-05-31 03:09:54 +02:00
public async Task < bool > SetAsDefaultProtocolClientAsync ( string protocol , CancellationToken cancellationToken = default )
{
return await SetAsDefaultProtocolClientAsync ( protocol , null , null , cancellationToken ) ;
}
/// <summary>
/// Sets the current executable as the default handler for a protocol (aka URI scheme). It allows you to
/// integrate your app deeper into the operating system. Once registered, all links with your-protocol://
/// will be opened with the current executable. The whole link, including protocol, will be passed to your
/// application as a parameter.
/// <para/>
/// Note: On macOS, you can only register protocols that have been added to your app's info.plist, which
/// cannot be modified at runtime. However, you can change the file during build time via
/// <see href="https://www.electronforge.io/">Electron Forge</see>,
/// <see href="https://github.com/electron/electron-packager">Electron Packager</see>, or by editing info.plist
/// with a text editor. Please refer to
/// <see href="https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115">Apple's documentation</see>
/// for details.
/// <para/>
/// Note: In a Windows Store environment (when packaged as an appx) this API will return true for all calls but
/// the registry key it sets won't be accessible by other applications. In order to register your Windows Store
/// application as a default protocol handler you <see href="https://docs.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/element-uap-protocol">must declare the protocol in your manifest</see>.
/// <para/>
/// The API uses the Windows Registry and LSSetDefaultHandlerForURLScheme internally.
/// </summary>
/// <param name="protocol">
/// The name of your protocol, without ://. For example, if you want your app to handle electron:// links,
2017-10-14 14:41:11 +02:00
/// call this method with electron as the parameter.</param>
2020-05-31 03:09:54 +02:00
/// <param name="path">The path to the Electron executable. Defaults to process.execPath</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>Whether the call succeeded.</returns>
2020-05-31 03:09:54 +02:00
public async Task < bool > SetAsDefaultProtocolClientAsync ( string protocol , string path , CancellationToken cancellationToken = default )
{
return await SetAsDefaultProtocolClientAsync ( protocol , path , null , cancellationToken ) ;
}
/// <summary>
/// Sets the current executable as the default handler for a protocol (aka URI scheme). It allows you to
/// integrate your app deeper into the operating system. Once registered, all links with your-protocol://
/// will be opened with the current executable. The whole link, including protocol, will be passed to your
/// application as a parameter.
/// <para/>
/// Note: On macOS, you can only register protocols that have been added to your app's info.plist, which
/// cannot be modified at runtime. However, you can change the file during build time via
/// <see href="https://www.electronforge.io/">Electron Forge</see>,
/// <see href="https://github.com/electron/electron-packager">Electron Packager</see>, or by editing info.plist
/// with a text editor. Please refer to
/// <see href="https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115">Apple's documentation</see>
/// for details.
/// <para/>
/// Note: In a Windows Store environment (when packaged as an appx) this API will return true for all calls but
/// the registry key it sets won't be accessible by other applications. In order to register your Windows Store
/// application as a default protocol handler you <see href="https://docs.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/element-uap-protocol">must declare the protocol in your manifest</see>.
/// <para/>
/// The API uses the Windows Registry and LSSetDefaultHandlerForURLScheme internally.
/// </summary>
/// <param name="protocol">
/// The name of your protocol, without ://. For example, if you want your app to handle electron:// links,
2017-10-14 14:41:11 +02:00
/// call this method with electron as the parameter.</param>
2020-05-31 03:09:54 +02:00
/// <param name="path">The path to the Electron executable. Defaults to process.execPath</param>
/// <param name="args">Arguments passed to the executable. Defaults to an empty array.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>Whether the call succeeded.</returns>
2020-05-31 03:09:54 +02:00
public async Task < bool > SetAsDefaultProtocolClientAsync ( string protocol , string path , string [ ] args , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < bool > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appSetAsDefaultProtocolClientCompleted" , ( success ) = >
{
BridgeConnector . Socket . Off ( "appSetAsDefaultProtocolClientCompleted" ) ;
2020-05-31 03:09:54 +02:00
taskCompletionSource . SetResult ( ( bool ) success ) ;
2017-11-13 20:47:31 +01:00
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appSetAsDefaultProtocolClient" , protocol , path , args ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// This method checks if the current executable as the default handler for a protocol (aka URI scheme).
/// If so, it will remove the app as the default handler.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="protocol">The name of your protocol, without ://.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>Whether the call succeeded.</returns>
2020-05-31 03:09:54 +02:00
public async Task < bool > RemoveAsDefaultProtocolClientAsync ( string protocol , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2020-05-31 03:09:54 +02:00
return await RemoveAsDefaultProtocolClientAsync ( protocol , null , null , cancellationToken ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// This method checks if the current executable as the default handler for a protocol (aka URI scheme).
/// If so, it will remove the app as the default handler.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="protocol">The name of your protocol, without ://.</param>
/// <param name="path">Defaults to process.execPath.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>Whether the call succeeded.</returns>
2020-05-31 03:09:54 +02:00
public async Task < bool > RemoveAsDefaultProtocolClientAsync ( string protocol , string path , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2020-05-31 03:09:54 +02:00
return await RemoveAsDefaultProtocolClientAsync ( protocol , path , null , cancellationToken ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// This method checks if the current executable as the default handler for a protocol (aka URI scheme).
/// If so, it will remove the app as the default handler.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="protocol">The name of your protocol, without ://.</param>
/// <param name="path">Defaults to process.execPath.</param>
/// <param name="args">Defaults to an empty array.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>Whether the call succeeded.</returns>
2020-05-31 03:09:54 +02:00
public async Task < bool > RemoveAsDefaultProtocolClientAsync ( string protocol , string path , string [ ] args , CancellationToken cancellationToken = default )
2017-11-13 20:47:31 +01:00
{
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < bool > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appRemoveAsDefaultProtocolClientCompleted" , ( success ) = >
{
BridgeConnector . Socket . Off ( "appRemoveAsDefaultProtocolClientCompleted" ) ;
2020-05-31 03:09:54 +02:00
taskCompletionSource . SetResult ( ( bool ) success ) ;
2017-11-13 20:47:31 +01:00
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appRemoveAsDefaultProtocolClient" , protocol , path , args ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// This method checks if the current executable is the default handler for a protocol (aka URI scheme).
/// <para/>
/// Note: On macOS, you can use this method to check if the app has been registered as the default protocol
/// handler for a protocol. You can also verify this by checking ~/Library/Preferences/com.apple.LaunchServices.plist
/// on the macOS machine. Please refer to <see href="https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme">Apple's documentation</see>
/// for details.
/// <para/>
/// The API uses the Windows Registry and LSCopyDefaultHandlerForURLScheme internally.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="protocol">The name of your protocol, without ://.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2020-05-31 03:09:54 +02:00
/// <returns>Whether the current executable is the default handler for a protocol (aka URI scheme).</returns>
public async Task < bool > IsDefaultProtocolClientAsync ( string protocol , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2020-05-31 03:09:54 +02:00
return await IsDefaultProtocolClientAsync ( protocol , null , null , cancellationToken ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// This method checks if the current executable is the default handler for a protocol (aka URI scheme).
/// <para/>
/// Note: On macOS, you can use this method to check if the app has been registered as the default protocol
/// handler for a protocol. You can also verify this by checking ~/Library/Preferences/com.apple.LaunchServices.plist
/// on the macOS machine. Please refer to <see href="https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme">Apple's documentation</see>
/// for details.
/// <para/>
/// The API uses the Windows Registry and LSCopyDefaultHandlerForURLScheme internally.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="protocol">The name of your protocol, without ://.</param>
/// <param name="path">Defaults to process.execPath.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2020-05-31 03:09:54 +02:00
/// <returns>Whether the current executable is the default handler for a protocol (aka URI scheme).</returns>
public async Task < bool > IsDefaultProtocolClientAsync ( string protocol , string path , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2020-05-31 03:09:54 +02:00
return await IsDefaultProtocolClientAsync ( protocol , path , null , cancellationToken ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// This method checks if the current executable is the default handler for a protocol (aka URI scheme).
/// <para/>
/// Note: On macOS, you can use this method to check if the app has been registered as the default protocol
/// handler for a protocol. You can also verify this by checking ~/Library/Preferences/com.apple.LaunchServices.plist
/// on the macOS machine. Please refer to <see href="https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme">Apple's documentation</see>
/// for details.
/// <para/>
/// The API uses the Windows Registry and LSCopyDefaultHandlerForURLScheme internally.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="protocol">The name of your protocol, without ://.</param>
/// <param name="path">Defaults to process.execPath.</param>
/// <param name="args">Defaults to an empty array.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2020-05-31 03:09:54 +02:00
/// <returns>Whether the current executable is the default handler for a protocol (aka URI scheme).</returns>
public async Task < bool > IsDefaultProtocolClientAsync ( string protocol , string path , string [ ] args , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < bool > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appIsDefaultProtocolClientCompleted" , ( success ) = >
{
BridgeConnector . Socket . Off ( "appIsDefaultProtocolClientCompleted" ) ;
2020-05-31 03:09:54 +02:00
taskCompletionSource . SetResult ( ( bool ) success ) ;
2017-11-13 20:47:31 +01:00
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appIsDefaultProtocolClient" , protocol , path , args ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Adds tasks to the <see cref="UserTask"/> category of the JumpList on Windows.
/// <para/>
/// Note: If you'd like to customize the Jump List even more use <see cref="SetJumpList"/> instead.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="userTasks">Array of <see cref="UserTask"/> objects.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>Whether the call succeeded.</returns>
2020-05-31 03:09:54 +02:00
public async Task < bool > SetUserTasksAsync ( UserTask [ ] userTasks , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < bool > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appSetUserTasksCompleted" , ( success ) = >
{
BridgeConnector . Socket . Off ( "appSetUserTasksCompleted" ) ;
2020-05-31 03:09:54 +02:00
taskCompletionSource . SetResult ( ( bool ) success ) ;
2017-11-13 20:47:31 +01:00
} ) ;
2017-10-14 00:06:58 +02:00
2020-05-31 03:09:54 +02:00
BridgeConnector . Socket . Emit ( "appSetUserTasks" , JArray . FromObject ( userTasks , _jsonSerializer ) ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// Jump List settings for the application.
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Jump List settings.</returns>
public async Task < JumpListSettings > GetJumpListSettingsAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < JumpListSettings > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2020-05-31 03:09:54 +02:00
BridgeConnector . Socket . On ( "appGetJumpListSettingsCompleted" , ( jumpListSettings ) = >
2017-11-13 20:47:31 +01:00
{
BridgeConnector . Socket . Off ( "appGetJumpListSettingsCompleted" ) ;
2020-05-31 03:09:54 +02:00
taskCompletionSource . SetResult ( JObject . Parse ( jumpListSettings . ToString ( ) ) . ToObject < JumpListSettings > ( ) ) ;
2017-11-13 20:47:31 +01:00
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appGetJumpListSettings" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Sets or removes a custom Jump List for the application. If categories is null the previously set custom
/// Jump List (if any) will be replaced by the standard Jump List for the app (managed by Windows).
/// <para/>
/// Note: If a <see cref="JumpListCategory"/> object has neither the <see cref="JumpListCategory.Type"/> nor
/// the <see cref="JumpListCategory.Name"/> property set then its <see cref="JumpListCategory.Type"/> is assumed
/// to be <see cref="JumpListCategoryType.tasks"/>. If the <see cref="JumpListCategory.Name"/> property is set but
/// the <see cref="JumpListCategory.Type"/> property is omitted then the <see cref="JumpListCategory.Type"/> is
/// assumed to be <see cref="JumpListCategoryType.custom"/>.
/// <para/>
/// Note: Users can remove items from custom categories, and Windows will not allow a removed item to be added
/// back into a custom category until after the next successful call to <see cref="SetJumpList"/>. Any attempt
/// to re-add a removed item to a custom category earlier than that will result in the entire custom category being
/// omitted from the Jump List. The list of removed items can be obtained using <see cref="GetJumpListSettingsAsync"/>.
/// </summary>
/// <param name="categories">Array of <see cref="JumpListCategory"/> objects.</param>
public void SetJumpList ( JumpListCategory [ ] categories )
{
BridgeConnector . Socket . Emit ( "appSetJumpList" , JArray . FromObject ( categories , _jsonSerializer ) ) ;
}
/// <summary>
/// The return value of this method indicates whether or not this instance of your application successfully obtained
/// the lock. If it failed to obtain the lock, you can assume that another instance of your application is already
/// running with the lock and exit immediately.
/// <para/>
/// I.e.This method returns <see langword="true"/> if your process is the primary instance of your application and your
/// app should continue loading. It returns <see langword="false"/> if your process should immediately quit as it has
/// sent its parameters to another instance that has already acquired the lock.
/// <para/>
/// On macOS, the system enforces single instance automatically when users try to open a second instance of your app
/// in Finder, and the open-file and open-url events will be emitted for that.However when users start your app in
/// command line, the system's single instance mechanism will be bypassed, and you have to use this method to ensure
/// single instance.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="newInstanceOpened">Lambda with an array of the second instance’ s command line arguments.
/// The second parameter is the working directory path.</param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2020-05-31 03:09:54 +02:00
/// <returns>This method returns false if your process is the primary instance of the application and your app
/// should continue loading. And returns true if your process has sent its parameters to another instance, and
/// you should immediately quit.
/// </returns>
public async Task < bool > RequestSingleInstanceLockAsync ( Action < string [ ] , string > newInstanceOpened , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < bool > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2018-09-25 23:10:58 +02:00
BridgeConnector . Socket . On ( "appRequestSingleInstanceLockCompleted" , ( success ) = >
2017-11-13 20:47:31 +01:00
{
2018-09-25 23:10:58 +02:00
BridgeConnector . Socket . Off ( "appRequestSingleInstanceLockCompleted" ) ;
2017-11-13 20:47:31 +01:00
taskCompletionSource . SetResult ( ( bool ) success ) ;
} ) ;
2017-10-14 00:06:58 +02:00
2018-09-25 23:10:58 +02:00
BridgeConnector . Socket . Off ( "secondInstance" ) ;
BridgeConnector . Socket . On ( "secondInstance" , ( result ) = >
2017-11-13 20:47:31 +01:00
{
JArray results = ( JArray ) result ;
string [ ] args = results . First . ToObject < string [ ] > ( ) ;
2020-05-31 03:09:54 +02:00
string workingDirectory = results . Last . ToObject < string > ( ) ;
2017-10-14 00:06:58 +02:00
2020-05-31 03:09:54 +02:00
newInstanceOpened ( args , workingDirectory ) ;
2017-11-13 20:47:31 +01:00
} ) ;
2017-10-14 00:06:58 +02:00
2018-09-25 23:10:58 +02:00
BridgeConnector . Socket . Emit ( "appRequestSingleInstanceLock" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// Releases all locks that were created by makeSingleInstance. This will allow
/// multiple instances of the application to once again run side by side.
/// </summary>
2018-09-25 23:10:58 +02:00
public void ReleaseSingleInstanceLock ( )
2017-10-14 00:06:58 +02:00
{
2018-09-25 23:10:58 +02:00
BridgeConnector . Socket . Emit ( "appReleaseSingleInstanceLock" ) ;
2017-10-14 00:06:58 +02:00
}
2020-05-31 03:09:54 +02:00
/// <summary>
/// This method returns whether or not this instance of your app is currently holding the single instance lock.
/// You can request the lock with <see cref="RequestSingleInstanceLockAsync"/> and release with
/// <see cref="ReleaseSingleInstanceLock"/>.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
public async Task < bool > HasSingleInstanceLockAsync ( CancellationToken cancellationToken = default )
{
cancellationToken . ThrowIfCancellationRequested ( ) ;
var taskCompletionSource = new TaskCompletionSource < bool > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
{
BridgeConnector . Socket . On ( "appHasSingleInstanceLockCompleted" , ( hasLock ) = >
{
BridgeConnector . Socket . Off ( "appHasSingleInstanceLockCompleted" ) ;
taskCompletionSource . SetResult ( ( bool ) hasLock ) ;
} ) ;
BridgeConnector . Socket . Emit ( "appHasSingleInstanceLock" ) ;
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// Creates an NSUserActivity and sets it as the current activity. The activity is
2020-05-31 03:09:54 +02:00
/// eligible for <see href="https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html">Handoff</see>
/// to another device afterward.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="type">Uniquely identifies the activity. Maps to <see href="https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType">NSUserActivity.activityType</see>.</param>
2017-10-14 14:41:11 +02:00
/// <param name="userInfo">App-specific state to store for use by another device.</param>
2017-10-14 17:58:16 +02:00
public void SetUserActivity ( string type , object userInfo )
2017-10-14 00:06:58 +02:00
{
2020-05-31 03:09:54 +02:00
SetUserActivity ( type , userInfo , null ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// Creates an NSUserActivity and sets it as the current activity. The activity is
2020-05-31 03:09:54 +02:00
/// eligible for <see href="https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html">Handoff</see>
/// to another device afterward.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="type">
/// Uniquely identifies the activity. Maps to <see href="https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType">NSUserActivity.activityType</see>.
/// </param>
2017-10-14 14:41:11 +02:00
/// <param name="userInfo">App-specific state to store for use by another device.</param>
2020-05-31 03:09:54 +02:00
/// <param name="webpageUrl">
/// The webpage to load in a browser if no suitable app is installed on the resuming device. The scheme must be http or https.
/// </param>
public void SetUserActivity ( string type , object userInfo , string webpageUrl )
2017-10-14 00:06:58 +02:00
{
2020-05-31 03:09:54 +02:00
BridgeConnector . Socket . Emit ( "appSetUserActivity" , type , userInfo , webpageUrl ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// The type of the currently running activity.
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="cancellationToken">The cancellation token.</param>
public async Task < string > GetCurrentActivityTypeAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < string > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appGetCurrentActivityTypeCompleted" , ( activityType ) = >
{
BridgeConnector . Socket . Off ( "appGetCurrentActivityTypeCompleted" ) ;
taskCompletionSource . SetResult ( activityType . ToString ( ) ) ;
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appGetCurrentActivityType" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Invalidates the current <see href="https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html">Handoff</see> user activity.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
public void InvalidateCurrentActivity ( )
{
BridgeConnector . Socket . Emit ( "appInvalidateCurrentActivity" ) ;
}
/// <summary>
/// Marks the current <see href="https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html">Handoff</see> user activity as inactive without invalidating it.
/// </summary>
public void ResignCurrentActivity ( )
{
BridgeConnector . Socket . Emit ( "appResignCurrentActivity" ) ;
}
/// <summary>
/// Changes the <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx">Application User Model ID</see> to id.
/// </summary>
/// <param name="id">Model Id.</param>
2017-10-14 17:58:16 +02:00
public void SetAppUserModelId ( string id )
2017-10-14 00:06:58 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appSetAppUserModelId" , id ) ;
2017-10-14 00:06:58 +02:00
}
2020-05-31 03:09:54 +02:00
/// TODO: Check new parameter which is a function [App.ImportCertificate]
2017-10-14 14:41:11 +02:00
/// <summary>
/// Imports the certificate in pkcs12 format into the platform certificate store.
/// callback is called with the result of import operation, a value of 0 indicates
/// success while any other value indicates failure according to chromium net_error_list.
/// </summary>
/// <param name="options"></param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>Result of import. Value of 0 indicates success.</returns>
2020-05-31 03:09:54 +02:00
public async Task < int > ImportCertificateAsync ( ImportCertificateOptions options , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < int > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appImportCertificateCompleted" , ( result ) = >
{
BridgeConnector . Socket . Off ( "appImportCertificateCompleted" ) ;
2020-05-31 03:09:54 +02:00
taskCompletionSource . SetResult ( ( int ) result ) ;
2017-11-13 20:47:31 +01:00
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appImportCertificate" , JObject . FromObject ( options , _jsonSerializer ) ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// Memory and cpu usage statistics of all the processes associated with the app.
/// </summary>
2020-05-31 03:09:54 +02:00
/// <returns>
/// Array of ProcessMetric objects that correspond to memory and cpu usage
/// statistics of all the processes associated with the app.
/// <param name="cancellationToken">The cancellation token.</param>
/// </returns>
public async Task < ProcessMetric [ ] > GetAppMetricsAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < ProcessMetric [ ] > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appGetAppMetricsCompleted" , ( result ) = >
{
BridgeConnector . Socket . Off ( "appGetAppMetricsCompleted" ) ;
var processMetrics = ( ( JArray ) result ) . ToObject < ProcessMetric [ ] > ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
taskCompletionSource . SetResult ( processMetrics ) ;
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appGetAppMetrics" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// The Graphics Feature Status from chrome://gpu/.
2020-05-31 03:09:54 +02:00
/// <para/>
/// Note: This information is only usable after the gpu-info-update event is emitted.
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
public async Task < GPUFeatureStatus > GetGpuFeatureStatusAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < GPUFeatureStatus > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appGetGpuFeatureStatusCompleted" , ( result ) = >
{
BridgeConnector . Socket . Off ( "appGetGpuFeatureStatusCompleted" ) ;
var gpuFeatureStatus = ( ( JObject ) result ) . ToObject < GPUFeatureStatus > ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
taskCompletionSource . SetResult ( gpuFeatureStatus ) ;
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appGetGpuFeatureStatus" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Sets the counter badge for current app. Setting the count to 0 will hide the badge.
/// On macOS it shows on the dock icon. On Linux it only works for Unity launcher.
/// <para/>
/// Note: Unity launcher requires the existence of a .desktop file to work, for more
/// information please read <see href="https://www.electronjs.org/docs/tutorial/desktop-environment-integration#unity-launcher">Desktop Environment Integration</see>.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="count">Counter badge.</param>
/// <param name="cancellationToken">The cancellation token.</param>
2017-10-14 14:41:11 +02:00
/// <returns>Whether the call succeeded.</returns>
2020-05-31 03:09:54 +02:00
public async Task < bool > SetBadgeCountAsync ( int count , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < bool > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appSetBadgeCountCompleted" , ( success ) = >
{
BridgeConnector . Socket . Off ( "appSetBadgeCountCompleted" ) ;
2020-05-31 03:09:54 +02:00
taskCompletionSource . SetResult ( ( bool ) success ) ;
2017-11-13 20:47:31 +01:00
} ) ;
2017-10-14 00:06:58 +02:00
2019-11-30 01:30:22 +01:00
BridgeConnector . Socket . Emit ( "appSetBadgeCount" , count ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
/// The current value displayed in the counter badge.
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="cancellationToken">The cancellation token.</param>
public async Task < int > GetBadgeCountAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < int > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appGetBadgeCountCompleted" , ( count ) = >
{
BridgeConnector . Socket . Off ( "appGetBadgeCountCompleted" ) ;
taskCompletionSource . SetResult ( ( int ) count ) ;
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appGetBadgeCount" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2019-11-30 01:30:22 +01:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// A <see cref="CommandLine"/> object that allows you to read and manipulate the command line arguments that Chromium uses.
2019-11-30 01:30:22 +01:00
/// </summary>
public CommandLine CommandLine { get ; internal set ; }
2017-10-14 14:41:11 +02:00
/// <summary>
/// Whether the current desktop environment is Unity launcher.
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="cancellationToken">The cancellation token.</param>
public async Task < bool > IsUnityRunningAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < bool > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appIsUnityRunningCompleted" , ( isUnityRunning ) = >
{
BridgeConnector . Socket . Off ( "appIsUnityRunningCompleted" ) ;
taskCompletionSource . SetResult ( ( bool ) isUnityRunning ) ;
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appIsUnityRunning" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// If you provided path and args options to <see cref="SetLoginItemSettings"/> then you need to pass the same
/// arguments here for <see cref="LoginItemSettings.OpenAtLogin"/> to be set correctly.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
public async Task < LoginItemSettings > GetLoginItemSettingsAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2020-05-31 03:09:54 +02:00
return await GetLoginItemSettingsAsync ( null , cancellationToken ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// If you provided path and args options to <see cref="SetLoginItemSettings"/> then you need to pass the same
/// arguments here for <see cref="LoginItemSettings.OpenAtLogin"/> to be set correctly.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="options"></param>
2017-11-13 20:47:31 +01:00
/// <param name="cancellationToken">The cancellation token.</param>
2020-05-31 03:09:54 +02:00
public async Task < LoginItemSettings > GetLoginItemSettingsAsync ( LoginItemSettingsOptions options , CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < LoginItemSettings > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appGetLoginItemSettingsCompleted" , ( loginItemSettings ) = >
{
BridgeConnector . Socket . Off ( "appGetLoginItemSettingsCompleted" ) ;
2020-05-31 03:09:54 +02:00
var result = ( ( JObject ) loginItemSettings ) . ToObject < LoginItemSettings > ( ) ;
taskCompletionSource . SetResult ( result ) ;
2017-11-13 20:47:31 +01:00
} ) ;
2017-10-14 00:06:58 +02:00
2020-05-31 03:09:54 +02:00
if ( options = = null )
{
BridgeConnector . Socket . Emit ( "appGetLoginItemSettings" ) ;
}
else
{
BridgeConnector . Socket . Emit ( "appGetLoginItemSettings" , JObject . FromObject ( options , _jsonSerializer ) ) ;
}
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Set the app's login item settings.
/// To work with Electron's autoUpdater on Windows, which uses <see href="https://github.com/Squirrel/Squirrel.Windows">Squirrel</see>,
/// you'll want to set the launch path to Update.exe, and pass arguments that specify your application name.
2017-10-14 14:41:11 +02:00
/// </summary>
/// <param name="loginSettings"></param>
2017-10-14 17:58:16 +02:00
public void SetLoginItemSettings ( LoginSettings loginSettings )
2017-10-14 00:06:58 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appSetLoginItemSettings" , JObject . FromObject ( loginSettings , _jsonSerializer ) ) ;
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// <see langword="true"/> if Chrome's accessibility support is enabled, <see langword="false"/> otherwise. This API will
/// return <see langword="true"/> if the use of assistive technologies, such as screen readers, has been detected.
/// See <see href="chromium.org/developers/design-documents/accessibility">Chromium's accessibility docs</see> for more details.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <returns><see langword="true"/> if Chrome’ s accessibility support is enabled, <see langword="false"/> otherwise.</returns>
public async Task < bool > IsAccessibilitySupportEnabledAsync ( CancellationToken cancellationToken = default )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
cancellationToken . ThrowIfCancellationRequested ( ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
var taskCompletionSource = new TaskCompletionSource < bool > ( ) ;
using ( cancellationToken . Register ( ( ) = > taskCompletionSource . TrySetCanceled ( ) ) )
2017-10-14 00:06:58 +02:00
{
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . On ( "appIsAccessibilitySupportEnabledCompleted" , ( isAccessibilitySupportEnabled ) = >
{
BridgeConnector . Socket . Off ( "appIsAccessibilitySupportEnabledCompleted" ) ;
taskCompletionSource . SetResult ( ( bool ) isAccessibilitySupportEnabled ) ;
} ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
BridgeConnector . Socket . Emit ( "appIsAccessibilitySupportEnabled" ) ;
2017-10-14 00:06:58 +02:00
2017-11-13 20:47:31 +01:00
return await taskCompletionSource . Task
. ConfigureAwait ( false ) ;
}
2017-10-14 00:06:58 +02:00
}
2017-10-14 14:41:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// Manually enables Chrome's accessibility support, allowing to expose accessibility switch to users in application settings.
/// See <see href="chromium.org/developers/design-documents/accessibility">Chromium's accessibility docs</see> for more details.
/// Disabled (<see langword="false"/>) by default.
/// <para/>
/// This API must be called after the <see cref="Ready"/> event is emitted.
/// <para/>
/// Note: Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.
2017-10-14 14:41:11 +02:00
/// </summary>
2020-05-31 03:09:54 +02:00
/// <param name="enabled">Enable or disable <see href="https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree">accessibility tree</see> rendering.</param>
public void SetAccessibilitySupportEnabled ( bool enabled )
{
BridgeConnector . Socket . Emit ( "appSetAboutPanelOptions" , enabled ) ;
}
/// <summary>
/// Show the app's about panel options. These options can be overridden with
/// <see cref="SetAboutPanelOptions"/>.
/// </summary>
public void ShowAboutPanel ( )
{
BridgeConnector . Socket . Emit ( "appShowAboutPanel" ) ;
}
/// <summary>
/// Set the about panel options. This will override the values defined in the app's .plist file on macOS. See the
/// <see href="https://developer.apple.com/reference/appkit/nsapplication/1428479-orderfrontstandardaboutpanelwith?language=objc">Apple docs</see>
/// for more details. On Linux, values must be set in order to be shown; there are no defaults.
/// <para/>
/// If you do not set credits but still wish to surface them in your app, AppKit will look for a file named "Credits.html",
/// "Credits.rtf", and "Credits.rtfd", in that order, in the bundle returned by the NSBundle class method main. The first file
/// found is used, and if none is found, the info area is left blank. See Apple
/// <see href="https://developer.apple.com/documentation/appkit/nsaboutpaneloptioncredits?language=objc">documentation</see> for more information.
/// </summary>
/// <param name="options">About panel options.</param>
2017-10-14 17:58:16 +02:00
public void SetAboutPanelOptions ( AboutPanelOptions options )
2017-10-14 00:06:58 +02:00
{
2017-10-14 17:58:16 +02:00
BridgeConnector . Socket . Emit ( "appSetAboutPanelOptions" , JObject . FromObject ( options , _jsonSerializer ) ) ;
2017-10-14 00:06:58 +02:00
}
2020-05-19 11:59:11 +02:00
/// <summary>
2020-05-31 03:09:54 +02:00
/// A <see cref="string"/> which is the user agent string Electron will use as a global fallback.
/// <para/>
/// This is the user agent that will be used when no user agent is set at the webContents or
/// session level. It is useful for ensuring that your entire app has the same user agent. Set to a
/// custom value as early as possible in your app's initialization to ensure that your overridden value
/// is used.
2020-05-19 11:59:11 +02:00
/// </summary>
public string UserAgentFallback
2020-07-08 11:16:00 +02:00
{
[Obsolete("Use the asynchronous version UserAgentFallbackAsync instead")]
get
{
return AsyncHelper . RunSync ( async ( ) = > await UserAgentFallbackAsync ) ;
}
set
{
BridgeConnector . Socket . Emit ( "appSetUserAgentFallback" , value ) ;
}
}
/// <summary>
/// A <see cref="string"/> which is the user agent string Electron will use as a global fallback.
/// <para/>
/// This is the user agent that will be used when no user agent is set at the webContents or
/// session level. It is useful for ensuring that your entire app has the same user agent. Set to a
/// custom value as early as possible in your app's initialization to ensure that your overridden value
/// is used.
/// </summary>
public Task < string > UserAgentFallbackAsync
2020-05-19 11:59:11 +02:00
{
get
{
return Task . Run < string > ( ( ) = >
{
var taskCompletionSource = new TaskCompletionSource < string > ( ) ;
BridgeConnector . Socket . On ( "appGetUserAgentFallbackCompleted" , ( result ) = >
2020-07-08 11:16:00 +02:00
{
BridgeConnector . Socket . Off ( "appGetUserAgentFallbackCompleted" ) ;
taskCompletionSource . SetResult ( ( string ) result ) ;
} ) ;
2020-05-19 11:59:11 +02:00
BridgeConnector . Socket . Emit ( "appGetUserAgentFallback" ) ;
return taskCompletionSource . Task ;
2020-07-08 11:16:00 +02:00
} ) ;
2020-05-19 11:59:11 +02:00
}
}
2017-11-10 03:11:13 +01:00
internal void PreventQuit ( )
{
_preventQuit = true ;
}
private bool _preventQuit = false ;
2017-10-03 03:28:56 +02:00
}
2020-05-31 03:09:54 +02:00
}