Skip to content

Commit

Permalink
Add "Auto reconnect to WebSocket" option
Browse files Browse the repository at this point in the history
  • Loading branch information
rampaa committed Sep 12, 2024
1 parent 9a6c939 commit d494400
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 39 deletions.
2 changes: 2 additions & 0 deletions JL.Core/Config/CoreConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public static class CoreConfigManager
public static double LookupRate { get; private set; } // = 0;
public static bool CaptureTextFromClipboard { get; set; } = true;
public static bool CaptureTextFromWebSocket { get; set; } // = false;
public static bool AutoReconnectToWebSocket { get; private set; } // = false;
public static bool TextBoxTrimWhiteSpaceCharacters { get; private set; } = true;
public static bool TextBoxRemoveNewlines { get; private set; } // = false;
public static Uri WebSocketUri { get; private set; } = new("ws://127.0.0.1:6677");
Expand Down Expand Up @@ -71,6 +72,7 @@ public static void ApplyPreferences(SqliteConnection connection)

{
CaptureTextFromWebSocket = ConfigDBManager.GetValueFromConfig(connection, CaptureTextFromWebSocket, nameof(CaptureTextFromWebSocket), bool.TryParse);
AutoReconnectToWebSocket = ConfigDBManager.GetValueFromConfig(connection, AutoReconnectToWebSocket, nameof(AutoReconnectToWebSocket), bool.TryParse);

string? webSocketUriStr = ConfigDBManager.GetSettingValue(connection, nameof(WebSocketUri));
if (webSocketUriStr is null)
Expand Down
96 changes: 57 additions & 39 deletions JL.Core/Network/WebSocketUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,67 +40,85 @@ private static void ListenWebSocket(CancellationToken cancellationToken)
{
s_webSocketTask = Task.Run(async () =>
{
try
do
{
using ClientWebSocket webSocketClient = new();
await webSocketClient.ConnectAsync(CoreConfigManager.WebSocketUri, CancellationToken.None).ConfigureAwait(false);
byte[] buffer = new byte[1024];

while (CoreConfigManager.CaptureTextFromWebSocket && !cancellationToken.IsCancellationRequested && webSocketClient.State is WebSocketState.Open)
try
{
try
{
WebSocketReceiveResult result = await webSocketClient.ReceiveAsync(buffer, CancellationToken.None).ConfigureAwait(false);
using ClientWebSocket webSocketClient = new();
await webSocketClient.ConnectAsync(CoreConfigManager.WebSocketUri, CancellationToken.None).ConfigureAwait(false);
Memory<byte> buffer = new byte[1024];

if (!CoreConfigManager.CaptureTextFromWebSocket || cancellationToken.IsCancellationRequested)
while (CoreConfigManager.CaptureTextFromWebSocket && !cancellationToken.IsCancellationRequested && webSocketClient.State is WebSocketState.Open)
{
try
{
return;
}
ValueWebSocketReceiveResult result = await webSocketClient.ReceiveAsync(buffer, CancellationToken.None).ConfigureAwait(false);
if (!CoreConfigManager.CaptureTextFromWebSocket || cancellationToken.IsCancellationRequested)
{
return;
}

if (result.MessageType is WebSocketMessageType.Text)
if (result.MessageType is WebSocketMessageType.Text)
{
using MemoryStream memoryStream = new();
await memoryStream.WriteAsync(buffer[..result.Count], cancellationToken).ConfigureAwait(false);

while (!result.EndOfMessage)
{
result = await webSocketClient.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false);
await memoryStream.WriteAsync(buffer[..result.Count], cancellationToken).ConfigureAwait(false);
}

_ = memoryStream.Seek(0, SeekOrigin.Begin);

string text = s_utf8NoBom.GetString(memoryStream.ToArray());
_ = Task.Run(async () => await Utils.Frontend.CopyFromWebSocket(text).ConfigureAwait(false), cancellationToken).ConfigureAwait(false);
}
}
catch (WebSocketException webSocketException)
{
using MemoryStream memoryStream = new();
await memoryStream.WriteAsync(buffer.AsMemory(0, result.Count), cancellationToken).ConfigureAwait(false);
Utils.Logger.Warning(webSocketException, "WebSocket server is closed unexpectedly");
Utils.Frontend.Alert(AlertLevel.Error, "WebSocket server is closed");

while (!result.EndOfMessage)
if (!CoreConfigManager.AutoReconnectToWebSocket)
{
result = await webSocketClient.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(false);
await memoryStream.WriteAsync(buffer.AsMemory(0, result.Count), cancellationToken).ConfigureAwait(false);
if (!CoreConfigManager.CaptureTextFromClipboard)
{
StatsUtils.StatsStopWatch.Stop();
StatsUtils.StopStatsTimer();
}
else
{
await Task.Delay(200).ConfigureAwait(false);
}
}

_ = memoryStream.Seek(0, SeekOrigin.Begin);

string text = s_utf8NoBom.GetString(memoryStream.ToArray());
_ = Task.Run(async () => await Utils.Frontend.CopyFromWebSocket(text).ConfigureAwait(false), cancellationToken).ConfigureAwait(false);
break;
}
}
catch (WebSocketException webSocketException)
}

catch (WebSocketException webSocketException)
{
if (!CoreConfigManager.AutoReconnectToWebSocket)
{
if (!CoreConfigManager.CaptureTextFromClipboard)
{
StatsUtils.StatsStopWatch.Stop();
StatsUtils.StopStatsTimer();
}

Utils.Logger.Warning(webSocketException, "WebSocket server is closed unexpectedly");
Utils.Frontend.Alert(AlertLevel.Error, "WebSocket server is closed");

break;
Utils.Logger.Warning(webSocketException, "Couldn't connect to the WebSocket server, probably because it is not running");
Utils.Frontend.Alert(AlertLevel.Error, "Couldn't connect to the WebSocket server, probably because it is not running");
}
else
{
Utils.Logger.Verbose(webSocketException, "Couldn't connect to the WebSocket server, probably because it is not running");
await Task.Delay(200).ConfigureAwait(false);
}
}
}

catch (WebSocketException webSocketException)
{
if (!CoreConfigManager.CaptureTextFromClipboard)
{
StatsUtils.StatsStopWatch.Stop();
StatsUtils.StopStatsTimer();
}

Utils.Logger.Warning(webSocketException, "Couldn't connect to the WebSocket server, probably because it is not running");
Utils.Frontend.Alert(AlertLevel.Error, "Couldn't connect to the WebSocket server, probably because it is not running");
}
while (CoreConfigManager.AutoReconnectToWebSocket && CoreConfigManager.CaptureTextFromWebSocket && !cancellationToken.IsCancellationRequested);
}, cancellationToken);
}
}
4 changes: 4 additions & 0 deletions JL.Windows/ConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,7 @@ public static void LoadPreferenceWindow(PreferencesWindow preferenceWindow)
preferenceWindow.TextBoxApplyDropShadowEffectCheckBox.IsChecked = TextBoxApplyDropShadowEffect;
preferenceWindow.CaptureTextFromClipboardCheckBox.IsChecked = CoreConfigManager.CaptureTextFromClipboard;
preferenceWindow.CaptureTextFromWebSocketCheckBox.IsChecked = CoreConfigManager.CaptureTextFromWebSocket;
preferenceWindow.AutoReconnectToWebSocketCheckBox.IsChecked = CoreConfigManager.AutoReconnectToWebSocket;
preferenceWindow.OnlyCaptureTextWithJapaneseCharsCheckBox.IsChecked = OnlyCaptureTextWithJapaneseChars;
preferenceWindow.DisableLookupsForNonJapaneseCharsInMainWindowCheckBox.IsChecked = DisableLookupsForNonJapaneseCharsInMainWindow;
preferenceWindow.MainWindowFocusOnHoverCheckBox.IsChecked = MainWindowFocusOnHover;
Expand Down Expand Up @@ -1064,6 +1065,9 @@ public static async Task SavePreferences(PreferencesWindow preferenceWindow)
ConfigDBManager.UpdateSetting(connection, nameof(CoreConfigManager.CaptureTextFromWebSocket),
preferenceWindow.CaptureTextFromWebSocketCheckBox.IsChecked.ToString()!);

ConfigDBManager.UpdateSetting(connection, nameof(CoreConfigManager.AutoReconnectToWebSocket),
preferenceWindow.AutoReconnectToWebSocketCheckBox.IsChecked.ToString()!);

ConfigDBManager.UpdateSetting(connection, nameof(OnlyCaptureTextWithJapaneseChars),
preferenceWindow.OnlyCaptureTextWithJapaneseCharsCheckBox.IsChecked.ToString()!);

Expand Down
9 changes: 9 additions & 0 deletions JL.Windows/GUI/PreferencesWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,15 @@
<TextBox x:Name="WebSocketUriTextBox" HorizontalAlignment="Right" Width="200" MaxHeight="60" TextWrapping="Wrap" />
</DockPanel>

<DockPanel>
<TextBlock HorizontalAlignment="Left" Text="Auto reconnect to WebSocket"
Style="{StaticResource TextBlockDefault}"
TextWrapping="Wrap" VerticalAlignment="Center"
Cursor="Help"
ToolTip="If this option is enabled, JL will *continously* try connecting to the specified WebSocket"/>
<CheckBox x:Name="AutoReconnectToWebSocketCheckBox" HorizontalAlignment="Right" />
</DockPanel>

<DockPanel>
<TextBlock HorizontalAlignment="Left" Text="Enable clipboard text capture"
Style="{StaticResource TextBlockDefault}"
Expand Down

0 comments on commit d494400

Please sign in to comment.