Skip to content

feat: rewrite voice functionality in rust #93

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Aerochat/Aerochat.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,7 @@
<PackageReference Include="System.Drawing.Common" Version="8.0.8" />
<PackageReference Include="System.Speech" Version="9.0.4" />
<PackageReference Include="Vanara.PInvoke.DwmApi" Version="4.0.3" />
<PackageReference Include="Vanara.PInvoke.Shared" Version="4.0.3" />
<PackageReference Include="Vanara.PInvoke.Shell32" Version="4.0.3" />
<PackageReference Include="Vanara.PInvoke.User32" Version="4.0.3" />
<PackageReference Include="Websocket.Client" Version="5.1.2" />
Expand Down
30 changes: 30 additions & 0 deletions Aerochat/Aerochat.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aerochat - Backup", "Aerochat - Backup.csproj", "{ED5B95D5-B0D5-62F8-71E6-4FC049C771E8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aerochat", "Aerochat.csproj", "{2F7F88E9-35D7-18CE-8024-F96DADC79732}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ED5B95D5-B0D5-62F8-71E6-4FC049C771E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED5B95D5-B0D5-62F8-71E6-4FC049C771E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED5B95D5-B0D5-62F8-71E6-4FC049C771E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED5B95D5-B0D5-62F8-71E6-4FC049C771E8}.Release|Any CPU.Build.0 = Release|Any CPU
{2F7F88E9-35D7-18CE-8024-F96DADC79732}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F7F88E9-35D7-18CE-8024-F96DADC79732}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F7F88E9-35D7-18CE-8024-F96DADC79732}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F7F88E9-35D7-18CE-8024-F96DADC79732}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C47F4002-1679-4B5E-83C6-32EFCEA09CDF}
EndGlobalSection
EndGlobal
31 changes: 19 additions & 12 deletions Aerochat/Settings/SettingsManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Aerochat.Enums;
using Aerochat.ViewModels;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -79,22 +80,28 @@ private static string SettingsFilePath

public static void Save()
{
// Serialize non-static properties
var properties = Instance.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(prop => prop.CanWrite && !prop.GetMethod.IsStatic)
.ToDictionary(prop => prop.Name, prop => prop.GetValue(Instance));
try
{
// Serialize non-static properties
var properties = Instance.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(prop => prop.CanWrite && !prop.GetMethod.IsStatic)
.ToDictionary(prop => prop.Name, prop => prop.GetValue(Instance));

// Ensure that the directory exists:
Directory.CreateDirectory(Path.GetDirectoryName(SettingsFilePath)!);
// Ensure that the directory exists:
Directory.CreateDirectory(Path.GetDirectoryName(SettingsFilePath)!);

var json = JsonSerializer.Serialize(properties, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(SettingsFilePath, json);
var json = JsonSerializer.Serialize(properties, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(SettingsFilePath, json);

// Call OnPropertyChanged for all properties
foreach (var property in properties.Keys)
// Call OnPropertyChanged for all properties
foreach (var property in properties.Keys)
{
Instance.InvokePropertyChanged(property);
}
} catch (Exception e)
{
Instance.InvokePropertyChanged(property);
Debug.WriteLine(e);
}
}

Expand Down
7 changes: 7 additions & 0 deletions Aerochat/ViewModels/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class UserViewModel : ViewModelBase
private SceneViewModel? _scene;
private string? _color = "#525252";
private string? _image;
private bool _isSpeaking = false;

public required string Name
{
Expand Down Expand Up @@ -66,6 +67,12 @@ public string? Image
set => SetProperty(ref _image, value);
}

public bool IsSpeaking
{
get => _isSpeaking;
set => SetProperty(ref _isSpeaking, value);
}

public static UserViewModel FromUser(DiscordUser user)
{
return new UserViewModel
Expand Down
9 changes: 7 additions & 2 deletions Aerochat/Voice/VoiceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public class VoiceManager : ViewModelBase
{
public static VoiceManager Instance = new();
private VoiceSocket? voiceSocket;
public VoiceSocket? VoiceSocket
{
get => voiceSocket;
}

public DiscordChannel? Channel => voiceSocket?.Channel;

private ChannelViewModel? _channelVM;
Expand All @@ -34,10 +39,10 @@ public async Task LeaveVoiceChannel()
ChannelVM = null;
}

public async Task JoinVoiceChannel(DiscordChannel channel)
public async Task JoinVoiceChannel(DiscordChannel channel, Action<VoiceStateChanged> onStateChange)
{
await LeaveVoiceChannel();
voiceSocket = new(Discord.Client);
voiceSocket = new(Discord.Client, onStateChange);
await voiceSocket.ConnectAsync(channel);
ChannelVM = ChannelViewModel.FromChannel(channel);
}
Expand Down
16 changes: 14 additions & 2 deletions Aerochat/Windows/Chat.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -474,12 +474,24 @@
</Grid>
</Grid>
</Button>
<ItemsControl ItemsSource="{Binding ConnectedUsers}">
<ItemsControl ItemsSource="{Binding ConnectedUsers, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="4,2,0,2">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSpeaking}" Value="True">
<Setter Property="Opacity" Value="1" />
</DataTrigger>
<DataTrigger Binding="{Binding IsSpeaking}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<controls:ProfilePictureFrame FrameSize="ExtraSmall" UserStatus="{Binding Presence.Status}" />
<TextBlock Margin="4,0,0,0" Opacity="0.5" Text="{Binding Name}" />
<TextBlock Margin="4,0,0,0" Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
Expand Down
90 changes: 58 additions & 32 deletions Aerochat/Windows/Chat.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ public async Task OnChannelChange(bool initial = false)
// We cannot edit messages or upload images across channels, so close the respective UIs.
// In the future, this design should possibly be reconsidered: the official Discord client
// persists such state between channels, and it only applies to the currently-active channel.
await Dispatcher.BeginInvoke(() => {
await Dispatcher.BeginInvoke(() =>
{
ClearReplyTarget();
LeaveEditingMessage();
CloseAttachmentsEditor();
Expand Down Expand Up @@ -663,7 +664,8 @@ private void ProcessLastRead()
if (!SettingsManager.Instance.LastReadMessages.TryGetValue(ChannelId, out var msgId))
{
SettingsManager.Instance.LastReadMessages[ChannelId] = message.Id ?? 0;
} else
}
else
{
long prevTimestamp = ((long)(msgId >> 22)) + 1420070400000;
DateTime prevLastMessageTime = DateTimeOffset.FromUnixTimeMilliseconds(prevTimestamp).DateTime;
Expand Down Expand Up @@ -775,7 +777,8 @@ public Chat(ulong id, bool allowDefault = false, PresenceViewModel? initialPrese
if (firstChannel is not null)
{
ChannelId = firstChannel.Id;
} else
}
else
{
UnavailableDialog();
return;
Expand Down Expand Up @@ -854,7 +857,8 @@ private void Chat_KeyDown(object sender, KeyEventArgs e)
PresentationSource.FromVisual(MessageTextBox),
0,
e.Key
) { RoutedEvent = Keyboard.KeyDownEvent });
)
{ RoutedEvent = Keyboard.KeyDownEvent });
MessageTextBox.Focus();
}
}
Expand Down Expand Up @@ -1109,7 +1113,8 @@ private void RunGCRelease()
private async void TypingUsers_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
List<DiscordUser> tempUsers = new();
foreach (var user in TypingUsers.ToList()) {
foreach (var user in TypingUsers.ToList())
{
if (!Discord.Client.TryGetCachedUser(user.Id, out DiscordUser discordUser))
{
// I believe this is fully safe since it'll only occur in a server context,
Expand Down Expand Up @@ -1419,7 +1424,8 @@ private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
if (hiddenItems)
{
expandBtn.Visibility = Visibility.Visible;
} else
}
else
{
expandBtn.Visibility = Visibility.Collapsed;
}
Expand Down Expand Up @@ -1547,7 +1553,26 @@ private async void ItemClick(object sender, MouseButtonEventArgs e)
}
try
{
await VoiceManager.Instance.JoinVoiceChannel(channel);
await VoiceManager.Instance.JoinVoiceChannel(channel, (e) =>
{
var castedItem = (HomeListItemViewModel)item;
var channelID = castedItem.Id;
Dispatcher.InvokeAsync(() =>
{
// FIXME: this code sucks
var category = ViewModel.Categories.ToList().Find(f => f.Items.Any(f => f.Id == channelID));
if (category == null) return;
var channel = category.Items.ToList().Find(f => f.Id == channelID);
if (channel == null) return;
ulong userID = 0;
VoiceManager.Instance.VoiceSocket?.UserSSRCMap.TryGetValue(e.SSRC, out userID);
var user = castedItem.ConnectedUsers.FirstOrDefault(u => u.Id == userID, null!);
if (user == null) return;
var index = castedItem.ConnectedUsers.IndexOf(user);
if (index == -1) return;
channel.ConnectedUsers[index].IsSpeaking = e.Speaking;
});
});
}
catch (Exception ex)
{
Expand Down Expand Up @@ -1617,38 +1642,38 @@ private async void MessageParser_HyperlinkClicked(object sender, Controls.Hyperl
switch (e.Type)
{
case Controls.HyperlinkType.WebLink:
{
string? uri = (string)e.AssociatedObject;
{
string? uri = (string)e.AssociatedObject;

if (uri is null)
return;
if (uri is null)
return;

OpenExternalUrl(uri);
break;
}
OpenExternalUrl(uri);
break;
}

case Controls.HyperlinkType.Channel:
{
var channel = (DiscordChannel)e.AssociatedObject;
ChannelId = channel.Id;
foreach (var category in ViewModel.Categories)
{
foreach (var item in category.Items)
var channel = (DiscordChannel)e.AssociatedObject;
ChannelId = channel.Id;
foreach (var category in ViewModel.Categories)
{
if (item.Id == channel.Id)
foreach (var item in category.Items)
{
item.IsSelected = true;
}
else
{
item.IsSelected = false;
if (item.Id == channel.Id)
{
item.IsSelected = true;
}
else
{
item.IsSelected = false;
}
}
}
await OnChannelChange().ConfigureAwait(false);
// find the item in the list
break;
}
await OnChannelChange().ConfigureAwait(false);
// find the item in the list
break;
}
}
}

Expand Down Expand Up @@ -1788,7 +1813,7 @@ private async void CanvasButton_Click(object sender, RoutedEventArgs e)
}
}


private int _drawingHeight = 120;
private int _writingHeight = 64;

Expand Down Expand Up @@ -1900,7 +1925,7 @@ private void ShowColorMenu(object sender, MouseButtonEventArgs e)
private string _lastValue = "";

Timer typingTimer = new(1000)
{
{
AutoReset = false
};

Expand Down Expand Up @@ -1930,7 +1955,8 @@ private void MessageTextBox_TextChanged(object sender, TextChangedEventArgs e)
_isTyping = true;
TypingTimer_Elapsed(null, null!);
typingTimer.Start();
};
}
;
}

private void OnMessageContextMenuOpening(object senderRaw, ContextMenuEventArgs e)
Expand Down
4 changes: 4 additions & 0 deletions Aerochat/Windows/Home.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ public Home()

// Subscribe to changes in the DisplayAds property
SettingsManager.Instance.PropertyChanged += OnSettingsChange;

await Task.Delay(1000);
Chat chat = new(1287027740452716606);
chat.Show();
});
}

Expand Down
Loading