mirror of
https://github.com/Stone-Red-Code/Decho.git
synced 2026-09-04 08:56:14 +02:00
Patch for EchoHub v0.2.17
This commit is contained in:
@@ -2,7 +2,7 @@ using System.Collections.ObjectModel;
|
||||
|
||||
namespace Decho.Models;
|
||||
|
||||
public sealed class ChannelModel(string id, string name, ObservableCollection<MessageModel> messages, string? topic = null, bool isPublic = true, bool isProtected = false)
|
||||
public sealed class ChannelModel(string id, string name, ObservableCollection<MessageModel> messages, string? topic = null, bool isPublic = true, bool isProtected = false, bool isEncrypted = false, bool isSystem = false)
|
||||
{
|
||||
public string Id { get; } = id;
|
||||
|
||||
@@ -14,5 +14,9 @@ public sealed class ChannelModel(string id, string name, ObservableCollection<Me
|
||||
|
||||
public bool IsProtected { get; } = isProtected;
|
||||
|
||||
public bool IsEncrypted { get; } = isEncrypted;
|
||||
|
||||
public bool IsSystem { get; } = isSystem;
|
||||
|
||||
public ObservableCollection<MessageModel> Messages { get; } = messages;
|
||||
}
|
||||
@@ -205,7 +205,9 @@ internal sealed class ChannelService : IChannelService
|
||||
[],
|
||||
channelDto.Topic,
|
||||
channelDto.IsPublic,
|
||||
channelDto.IsProtected);
|
||||
channelDto.IsProtected,
|
||||
channelDto.IsEncrypted,
|
||||
channelDto.IsSystem);
|
||||
entry.Server.Channels.Add(channel);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
|
||||
using Decho.Models;
|
||||
|
||||
using EchoHub.Client.Config;
|
||||
@@ -5,8 +8,10 @@ using EchoHub.Client.Services;
|
||||
using EchoHub.Client.UI.Dialogs;
|
||||
using EchoHub.Core.Constants;
|
||||
using EchoHub.Core.DTOs;
|
||||
using EchoHub.Core.Models;
|
||||
using EchoHub.Core.Services;
|
||||
|
||||
using MsBox.Avalonia;
|
||||
using MsBox.Avalonia.Base;
|
||||
using MsBox.Avalonia.Enums;
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
@@ -140,7 +145,9 @@ public sealed class ConnectionService : IConnectionService
|
||||
[],
|
||||
dto.Topic,
|
||||
dto.IsPublic,
|
||||
dto.IsProtected);
|
||||
dto.IsProtected,
|
||||
dto.IsEncrypted,
|
||||
dto.IsSystem);
|
||||
}
|
||||
|
||||
internal static MessageModel MessageModelFromDto(MessageDto dto, ServerConnection entry)
|
||||
@@ -219,11 +226,37 @@ public sealed class ConnectionService : IConnectionService
|
||||
SaveRefreshToken(dialogResult.ServerUrl, dialogResult.RememberMe);
|
||||
ServerAdded?.Invoke(serverModel);
|
||||
|
||||
// Check for version mismatch
|
||||
//if (result.ServerInfo is not null && !string.IsNullOrEmpty(result.ServerInfo.Version)
|
||||
// && result.ServerInfo.Version != App.AppVersion)
|
||||
//{
|
||||
// await ShowVersionMismatchDialogAsync(dialogResult.ServerUrl, result.ServerInfo.Version);
|
||||
//}
|
||||
|
||||
AutoJoinRemainingChannels(dialogResult.ServerUrl, result.Channels);
|
||||
|
||||
return serverModel;
|
||||
}
|
||||
|
||||
//private async Task ShowVersionMismatchDialogAsync(string serverUrl, string serverVersion)
|
||||
//{
|
||||
// await Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
// {
|
||||
// IMsBox<ButtonResult> box = MessageBoxManager.GetMessageBoxStandard(
|
||||
// "Version Mismatch",
|
||||
// $"Server version {serverVersion} does not match client version {App.AppVersion}.\n\nSome features may not work correctly. Consider updating both to the same version.",
|
||||
// ButtonEnum.YesNo);
|
||||
//
|
||||
// ButtonResult result = await box.ShowWindowDialogAsync(
|
||||
// (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow);
|
||||
//
|
||||
// if (result == ButtonResult.No)
|
||||
// {
|
||||
// _ = DisconnectAsync(serverUrl);
|
||||
// }
|
||||
// });
|
||||
//}
|
||||
|
||||
private async void AutoJoinRemainingChannels(string serverUrl, List<ChannelDto> channels)
|
||||
{
|
||||
ClientConfig config = ConfigManager.Load();
|
||||
@@ -342,7 +375,9 @@ public sealed class ConnectionService : IConnectionService
|
||||
[],
|
||||
channel.Topic,
|
||||
channel.IsPublic,
|
||||
channel.IsProtected);
|
||||
channel.IsProtected,
|
||||
channel.IsEncrypted,
|
||||
channel.IsSystem);
|
||||
entry.Server.Channels.Add(model);
|
||||
ChannelAdded?.Invoke(entry.Server.ServerUrl, model);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,18 @@ public sealed class ChannelViewModel(ChannelModel model) : ViewModelBase
|
||||
|
||||
public bool IsNotProtected => !Model.IsProtected;
|
||||
|
||||
public bool IsSystem => Model.IsSystem;
|
||||
|
||||
public bool IsNotSystem => !Model.IsSystem;
|
||||
|
||||
public bool ShowLockIcon => Model.IsProtected && IsLocked;
|
||||
|
||||
public bool ShowUnlockIcon => Model.IsProtected && !IsLocked;
|
||||
|
||||
public bool ShowServerIcon => Model.IsSystem && !Model.IsProtected;
|
||||
|
||||
public bool ShowHashtagIcon => !Model.IsProtected && !Model.IsSystem;
|
||||
|
||||
public bool IsLocked
|
||||
{
|
||||
get;
|
||||
|
||||
@@ -892,7 +892,7 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
ChannelJoinResult joinResult = await ChannelService.JoinChannelAsync(server.ServerUrl, channel.Name);
|
||||
|
||||
ChannelModel channelModel = new ChannelModel(
|
||||
channel.Id.ToString(), channel.Name, [], channel.Topic, channel.IsPublic, channel.IsProtected);
|
||||
channel.Id.ToString(), channel.Name, [], channel.Topic, channel.IsPublic, channel.IsProtected, channel.IsEncrypted, channel.IsSystem);
|
||||
|
||||
ServerViewModel? serverVm = Sidebar.GetServer(server.ServerUrl);
|
||||
if (serverVm is not null)
|
||||
@@ -1040,10 +1040,18 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
{
|
||||
Chat.Composer.SetCommandHandler(new CommandHandler());
|
||||
|
||||
if (channel.IsProtected && channel.Messages.Count == 0)
|
||||
if (channel.IsSystem)
|
||||
{
|
||||
Chat.Composer.IsReadOnly = true;
|
||||
}
|
||||
else if (channel.IsProtected && channel.Messages.Count == 0)
|
||||
{
|
||||
channel.IsLocked = true;
|
||||
Chat.Composer.IsConnected = false;
|
||||
Chat.Composer.IsReadOnly = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Chat.Composer.IsReadOnly = false;
|
||||
}
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
@@ -1064,7 +1072,7 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
channel.IsLocked = true;
|
||||
Chat.Composer.IsConnected = false;
|
||||
Chat.Composer.IsReadOnly = true;
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -1078,6 +1086,11 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
channel.IsLocked = false;
|
||||
Chat.Composer.IsConnected = isServerConnected;
|
||||
|
||||
if (channel.IsProtected)
|
||||
{
|
||||
Chat.Composer.IsReadOnly = false;
|
||||
}
|
||||
|
||||
if (!channel.Messages.Any(m => m.AuthorName != "System"))
|
||||
{
|
||||
foreach (MessageModel msg in joinResult.History)
|
||||
@@ -1090,7 +1103,7 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
_ = RefreshOnlineUsersAsync(serverUrl, channel.Name);
|
||||
return;
|
||||
}
|
||||
catch (EchoHub.Client.Services.ChannelPasswordRequiredException)
|
||||
catch (ChannelPasswordRequiredException)
|
||||
{
|
||||
string? pwd = await Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
@@ -1242,7 +1255,11 @@ public sealed class MainWindowViewModel : ViewModelBase
|
||||
ChannelModel channelModel = new ChannelModel(
|
||||
Guid.NewGuid().ToString("N"),
|
||||
channelName,
|
||||
[]);
|
||||
[],
|
||||
isPublic: true,
|
||||
isProtected: false,
|
||||
isEncrypted: false,
|
||||
isSystem: false);
|
||||
ChannelViewModel channelVm = new ChannelViewModel(channelModel);
|
||||
serverVm.Channels.Add(channelVm);
|
||||
}
|
||||
|
||||
@@ -39,9 +39,25 @@ public sealed class MessageComposerViewModel : ViewModelBase
|
||||
public bool IsConnected
|
||||
{
|
||||
get;
|
||||
set => this.RaiseAndSetIfChanged(ref field, value);
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref field, value);
|
||||
this.RaisePropertyChanged(nameof(IsEditable));
|
||||
}
|
||||
} = true;
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref field, value);
|
||||
this.RaisePropertyChanged(nameof(IsEditable));
|
||||
}
|
||||
} = false;
|
||||
|
||||
public bool IsEditable => !IsReadOnly && IsConnected;
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SendCommand { get; }
|
||||
|
||||
public bool HasCommandHandler => _commandHandler is not null;
|
||||
@@ -84,10 +100,11 @@ public sealed class MessageComposerViewModel : ViewModelBase
|
||||
Autocomplete = new AutocompleteController([mentionProvider, channelProvider]);
|
||||
|
||||
IObservable<bool> canSend = this.WhenAnyValue(
|
||||
x => x.Draft,
|
||||
x => x.HasStagedFiles,
|
||||
(draft, hasFiles) =>
|
||||
!string.IsNullOrWhiteSpace(draft) || hasFiles);
|
||||
x => x.Draft,
|
||||
x => x.HasStagedFiles,
|
||||
x => x.IsReadOnly,
|
||||
(draft, hasFiles, isReadOnly) =>
|
||||
(!string.IsNullOrWhiteSpace(draft) || hasFiles) && !isReadOnly);
|
||||
SendCommand = ReactiveCommand.Create(Send, canSend);
|
||||
|
||||
_ = this.WhenAnyValue(x => x.Draft).Subscribe(OnDraftChanged);
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
<DataTemplate x:DataType="vm:ChannelViewModel">
|
||||
<Grid ColumnDefinitions="Auto, *, Auto" Margin="2 0">
|
||||
<Grid Grid.Column="0" Margin="0 0 4 0">
|
||||
<i:Icon Value="fa-hashtag" FontWeight="Bold" VerticalAlignment="Center" IsVisible="{Binding IsNotProtected}" />
|
||||
<i:Icon Value="fa-lock" FontWeight="Bold" VerticalAlignment="Center" IsVisible="{Binding IsProtected}" />
|
||||
<i:Icon Value="fa-lock" FontWeight="Bold" VerticalAlignment="Center" IsVisible="{Binding ShowLockIcon}" />
|
||||
<i:Icon Value="fa-lock-open" FontWeight="Bold" VerticalAlignment="Center" IsVisible="{Binding ShowUnlockIcon}" />
|
||||
<i:Icon Value="fa-server" FontWeight="Bold" VerticalAlignment="Center" IsVisible="{Binding ShowServerIcon}" />
|
||||
<i:Icon Value="fa-hashtag" FontWeight="Bold" VerticalAlignment="Center" IsVisible="{Binding ShowHashtagIcon}" />
|
||||
</Grid>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Name}" TextTrimming="CharacterEllipsis" VerticalAlignment="Center" />
|
||||
<Border Grid.Column="2"
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
|
||||
<CheckBox x:Name="RememberCheck" Content="Remember me" IsChecked="True" />
|
||||
|
||||
<TextBlock Text="Display Name (optional):" FontWeight="SemiBold" />
|
||||
<TextBox x:Name="DisplayNameBox" Watermark="Display name" />
|
||||
|
||||
<TextBlock Text="Invite Code (optional):" FontWeight="SemiBold" />
|
||||
<TextBox x:Name="InviteCodeBox" Watermark="Invite code" />
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"
|
||||
Spacing="10"
|
||||
|
||||
@@ -100,6 +100,8 @@ public sealed partial class ConnectDialogWindow : Window
|
||||
string url = UrlBox.Text?.Trim() ?? "";
|
||||
string user = UserBox.Text?.Trim() ?? "";
|
||||
string pass = PassBox.Text ?? "";
|
||||
string displayName = DisplayNameBox.Text?.Trim() ?? "";
|
||||
string inviteCode = InviteCodeBox.Text?.Trim() ?? "";
|
||||
|
||||
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(user) || string.IsNullOrEmpty(pass))
|
||||
{
|
||||
@@ -108,7 +110,9 @@ public sealed partial class ConnectDialogWindow : Window
|
||||
return;
|
||||
}
|
||||
|
||||
Close(new ConnectDialogResult(url, user, pass, true, RememberCheck.IsChecked ?? false, null));
|
||||
Close(new ConnectDialogResult(url, user, pass, true, RememberCheck.IsChecked ?? false, null,
|
||||
string.IsNullOrEmpty(displayName) ? null : displayName,
|
||||
string.IsNullOrEmpty(inviteCode) ? null : inviteCode));
|
||||
}
|
||||
|
||||
private void OnCancelClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:vm="using:Decho.ViewModels"
|
||||
xmlns:models="using:Decho.Models"
|
||||
xmlns:i="https://github.com/projektanker/icons.avalonia"
|
||||
xmlns:converters="using:Avalonia.Data.Converters"
|
||||
x:Class="Decho.Views.MessageComposerView"
|
||||
x:DataType="vm:MessageComposerViewModel">
|
||||
<Grid RowDefinitions="Auto,Auto,*">
|
||||
@@ -78,7 +79,7 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
Margin="0 0 5 0"
|
||||
Text="{Binding Draft, Mode=TwoWay}"
|
||||
IsEnabled="{Binding IsConnected}"
|
||||
IsEnabled="{Binding IsEditable}"
|
||||
AcceptsReturn="False"
|
||||
TextWrapping="Wrap"
|
||||
KeyDown="OnTextBoxKeyDown" />
|
||||
@@ -119,7 +120,7 @@
|
||||
VerticalAlignment="Top"
|
||||
i:Attached.Icon="fa-paper-plane"
|
||||
Command="{Binding SendCommand}"
|
||||
IsEnabled="{Binding IsConnected}" />
|
||||
IsEnabled="{Binding IsEditable}" />
|
||||
<Button Grid.Column="2"
|
||||
Height="33"
|
||||
Width="33"
|
||||
@@ -127,7 +128,7 @@
|
||||
Click="OnFileUploadClicked"
|
||||
VerticalAlignment="Top"
|
||||
i:Attached.Icon="fa-paperclip"
|
||||
IsEnabled="{Binding IsConnected}" />
|
||||
IsEnabled="{Binding IsEditable}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
+1
-1
Submodule src/EchoHub updated: ef42c42736...e335790aab
Reference in New Issue
Block a user