feat(windows): UI overhaul -- toolbar, unified log, PM windows, channel counts, output volume
- Voice actions (Join Voice, Share Screen Audio) moved to a ToolStrip toolbar and a new Voice menu in the menu bar; removed from the bottom voice panel - Activity log and chat log collapsed into a single RichTextBox (rtbLog); activity events appear in gray, chat messages in default color - Private messaging reworked: each conversation opens in its own modeless PrivateMessageForm instead of sharing the main chat log via a scope dropdown; cboScope removed; main compose bar always sends to the current channel - New "Messages -> New Private Message..." menu item (Ctrl+P) opens a UserPickerDialog listing all connected server users (not just the current channel) so you can PM anyone on the server - Channel tree now shows live user counts, e.g. "General (3)" -- counts sourced from the existing _users dictionary which already tracks all server users with channel IDs - Global output volume slider (TrackBar, 0-100, default 80) added to the right panel; wired to new vc_set_output_volume C ABI function that applies a master gain multiplier in the audio engine playback callback after mixing all streams - vc_set_output_volume added end-to-end: voicecat.h, audio_engine.h/.cpp, client.h/.cpp, voicecat.cpp, NativeMethods.cs, VoiceCatClient.cs - Documented Windows PowerShell ctest requirement in AGENTS.md and CLAUDE.md: MinGW binaries exit 0xc0000139 in Git Bash; always run ctest/.exe via PowerShell 22/22 ctest green (PowerShell); dotnet build 0 warnings. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
99
clients/windows/VoiceCat.App/Forms/UserPickerDialog.cs
Normal file
99
clients/windows/VoiceCat.App/Forms/UserPickerDialog.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using VoiceCat.Interop;
|
||||
|
||||
namespace VoiceCat.App.Forms;
|
||||
|
||||
/// <summary>
|
||||
/// Simple modal dialog for picking one user from a list of all server users.
|
||||
/// Used by "New Private Message" to let the user send a PM to anyone on the server.
|
||||
/// </summary>
|
||||
public sealed class UserPickerDialog : Form
|
||||
{
|
||||
private readonly ListBox _lstUsers;
|
||||
private readonly Button _btnOk;
|
||||
private readonly Button _btnCancel;
|
||||
|
||||
private readonly List<UserInfo> _users;
|
||||
|
||||
public uint SelectedUserId { get; private set; }
|
||||
|
||||
public UserPickerDialog(List<UserInfo> users)
|
||||
{
|
||||
_users = users;
|
||||
|
||||
Text = "New Private Message";
|
||||
ClientSize = new Size(280, 320);
|
||||
MinimumSize = new Size(220, 240);
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
StartPosition = FormStartPosition.CenterParent;
|
||||
|
||||
var lbl = new Label
|
||||
{
|
||||
Text = "Select a user:",
|
||||
AutoSize = true,
|
||||
Padding = new Padding(6, 6, 6, 2),
|
||||
Dock = DockStyle.Top,
|
||||
};
|
||||
|
||||
_lstUsers = new ListBox
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
AccessibleName = "User list",
|
||||
};
|
||||
foreach (var u in users)
|
||||
_lstUsers.Items.Add(new UserItem(u.Id, u.Nickname));
|
||||
|
||||
var btnPanel = new FlowLayoutPanel
|
||||
{
|
||||
Dock = DockStyle.Bottom,
|
||||
FlowDirection = FlowDirection.RightToLeft,
|
||||
Height = 40,
|
||||
Padding = new Padding(4),
|
||||
AutoSize = false,
|
||||
};
|
||||
|
||||
_btnCancel = new Button
|
||||
{
|
||||
Text = "Cancel",
|
||||
DialogResult = DialogResult.Cancel,
|
||||
AutoSize = true,
|
||||
};
|
||||
_btnOk = new Button
|
||||
{
|
||||
Text = "OK",
|
||||
DialogResult = DialogResult.OK,
|
||||
AutoSize = true,
|
||||
Enabled = false,
|
||||
};
|
||||
AcceptButton = _btnOk;
|
||||
CancelButton = _btnCancel;
|
||||
|
||||
btnPanel.Controls.Add(_btnCancel);
|
||||
btnPanel.Controls.Add(_btnOk);
|
||||
|
||||
Controls.Add(_lstUsers);
|
||||
Controls.Add(lbl);
|
||||
Controls.Add(btnPanel);
|
||||
|
||||
_lstUsers.SelectedIndexChanged += (_, _) =>
|
||||
_btnOk.Enabled = _lstUsers.SelectedItem is UserItem;
|
||||
_lstUsers.DoubleClick += (_, _) =>
|
||||
{
|
||||
if (_lstUsers.SelectedItem is UserItem) DialogResult = DialogResult.OK;
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||
{
|
||||
if (DialogResult == DialogResult.OK && _lstUsers.SelectedItem is UserItem item)
|
||||
SelectedUserId = item.UserId;
|
||||
base.OnFormClosing(e);
|
||||
}
|
||||
|
||||
private sealed class UserItem(uint userId, string nickname)
|
||||
{
|
||||
public uint UserId { get; } = userId;
|
||||
public override string ToString() => nickname;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user