diff --git a/api/client/EchoHub.Client.AppOrchestrator.html b/api/client/EchoHub.Client.AppOrchestrator.html index 9f447a7..688bf5b 100644 --- a/api/client/EchoHub.Client.AppOrchestrator.html +++ b/api/client/EchoHub.Client.AppOrchestrator.html @@ -225,6 +225,39 @@ Wires UI events to service calls and connection events to UI updates.

+ + +

+ PendingUpdate + +

+ +

Set when the user confirms an update. The host must run this after the Terminal.Gui main +loop exits (console restored), so the updater's in-place restart doesn't fight the TUI.

+
+
+ +
+
public Func<Task>? PendingUpdate { get; }
+
+ + + + + +

Property Value

+
+
Func<Task>
+
+
+ + + + + + + +

Methods

diff --git a/api/client/EchoHub.Client.Commands.CommandHandler.html b/api/client/EchoHub.Client.Commands.CommandHandler.html index 7acdbbb..0c1c5b7 100644 --- a/api/client/EchoHub.Client.Commands.CommandHandler.html +++ b/api/client/EchoHub.Client.Commands.CommandHandler.html @@ -679,6 +679,36 @@ Class CommandHandler + OnRoomInfo + + + +
+
+ +
+
public event Func<Task>? OnRoomInfo
+
+ + + + + + +

Event Type

+
+
Func<Task>
+
+
+ + + + + + + +

OnSendFile diff --git a/api/client/EchoHub.Client.Config.SavedServer.html b/api/client/EchoHub.Client.Config.SavedServer.html index c9c5d00..f1fc0f4 100644 --- a/api/client/EchoHub.Client.Config.SavedServer.html +++ b/api/client/EchoHub.Client.Config.SavedServer.html @@ -247,6 +247,72 @@ user's machine — the server never sees them.

+ + +

+ LastReadMessages + +

+ +

Last message the user has read per channel (message id as string), persisted so +unread counts, @mention highlights, and the "new messages" marker survive restarts.

+
+
+ +
+
public Dictionary<string, string> LastReadMessages { get; set; }
+
+ + + + + +

Property Value

+
+
Dictionary<string, string>
+
+
+ + + + + + + + + + +

+ LeftChannels + +

+ +

Channels the user explicitly left with /leave. Excluded from the automatic +join-all-channels pass at connect until the user joins them again.

+
+
+ +
+
public List<string> LeftChannels { get; set; }
+
+ + + + + +

Property Value

+
+
List<string>
+
+
+ + + + + + + +

diff --git a/api/client/EchoHub.Client.Services.ApiClient.html b/api/client/EchoHub.Client.Services.ApiClient.html index eb82300..6285e97 100644 --- a/api/client/EchoHub.Client.Services.ApiClient.html +++ b/api/client/EchoHub.Client.Services.ApiClient.html @@ -583,6 +583,44 @@ key-derivation salt). Returns null when the channel doesn't exist.

+ + +

+ GetChannelMetaAsync(string) + +

+ +

Fetches a channel's human-facing metadata (message count, unique posters, estimated +size, created date, room id) for the /meta command. Returns null if it doesn't exist.

+
+
+ +
+
public Task<ChannelMetaDto?> GetChannelMetaAsync(string channelName)
+
+ +

Parameters

+
+
channelName string
+
+
+ +

Returns

+
+
Task<ChannelMetaDto>
+
+
+ + + + + + + + + + +

diff --git a/api/client/EchoHub.Client.Services.UpdateChecker.html b/api/client/EchoHub.Client.Services.UpdateChecker.html index d9dbc80..cc02760 100644 --- a/api/client/EchoHub.Client.Services.UpdateChecker.html +++ b/api/client/EchoHub.Client.Services.UpdateChecker.html @@ -221,6 +221,40 @@ Class UpdateChecker + +

+ PendingUpdate + +

+ +

Set when the user confirms an update. The host runs this after the Terminal.Gui +main loop has exited and the console is restored, so the library's in-place restart doesn't +deadlock against a TUI that still owns the console.

+
+
+ +
+
public Func<Task>? PendingUpdate { get; }
+
+ + + + + +

Property Value

+
+
Func<Task>
+
+
+ + + + + + + +

Methods

diff --git a/api/client/EchoHub.Client.Themes.Theme.html b/api/client/EchoHub.Client.Themes.Theme.html index 3f0f42e..6e13b66 100644 --- a/api/client/EchoHub.Client.Themes.Theme.html +++ b/api/client/EchoHub.Client.Themes.Theme.html @@ -213,6 +213,41 @@ Class Theme + +

+ Border + +

+ +

Colors for the main-window frame borders (and their titles). Null falls back +to Base. Lets themes tone borders down independently of text — +e.g. the transparent themes use a dim gray for a subtler, glassy look. +Supports hex values ("#6E6E6E") as well as named colors.

+
+
+ +
+
public ThemeColors? Border { get; set; }
+
+ + + + + +

Property Value

+
+
ThemeColors
+
+
+ + + + + + + +

diff --git a/api/client/EchoHub.Client.UI.Chat.ChatColors.html b/api/client/EchoHub.Client.UI.Chat.ChatColors.html index 3df7e9f..7fc2800 100644 --- a/api/client/EchoHub.Client.UI.Chat.ChatColors.html +++ b/api/client/EchoHub.Client.UI.Chat.ChatColors.html @@ -214,6 +214,37 @@ Class ChatColors + DateRuleAttr + +

+ +

Horizontal date-separator rules (── Wed, Jul 16 ──…).

+
+
+ +
+
public static readonly Attribute DateRuleAttr
+
+ + + + +

Field Value

+
+
Attribute
+
+
+ + + + + + + + + +

EmbedBorderAttr @@ -424,6 +455,37 @@ Class ChatColors + RailAttr + +

+ +

The dim vertical rail (│) separating the nick column from message text.

+
+
+ +
+
public static readonly Attribute RailAttr
+
+ + + + +

Field Value

+
+
Attribute
+
+
+ + + + + + + + + +

SystemAttr @@ -483,6 +545,37 @@ Class ChatColors + UnreadMarkerAttr + +

+ +

The irssi-style "new messages" unread marker rule.

+
+
+ +
+
public static readonly Attribute UnreadMarkerAttr
+
+ + + + +

Field Value

+
+
Attribute
+
+
+ + + + + + + + +

Methods

diff --git a/api/client/EchoHub.Client.UI.Chat.ChatLine.html b/api/client/EchoHub.Client.UI.Chat.ChatLine.html index 4fd62a6..4892807 100644 --- a/api/client/EchoHub.Client.UI.Chat.ChatLine.html +++ b/api/client/EchoHub.Client.UI.Chat.ChatLine.html @@ -341,6 +341,40 @@ Class ChatLine + +

+ ContinuationPrefixSegments + +

+ +

Colored segments to prepend on continuation lines instead of plain spaces +(e.g. the nick-column rail " │ "). When set, takes +precedence over ContinuationIndent.

+
+
+ +
+
public List<ChatSegment>? ContinuationPrefixSegments { get; set; }
+
+ + + + + +

Property Value

+
+
List<ChatSegment>
+
+
+ + + + + + + +

@@ -372,6 +406,38 @@ Class ChatLine + +

+ IsUnreadMarker + +

+ +

True for the "new messages" unread-marker rule so it can be removed on channel switch.

+
+
+ +
+
public bool IsUnreadMarker { get; set; }
+
+ + + + + +

Property Value

+
+
bool
+
+
+ + + + + + + +

@@ -403,6 +469,71 @@ Class ChatLine + +

+ RuleAttr + +

+ +

Color for a rule line; null falls back to DateRuleAttr.

+
+
+ +
+
public Attribute? RuleAttr { get; set; }
+
+ + + + + +

Property Value

+
+
Attribute?
+
+
+ + + + + + + + + + +

+ RuleLabel + +

+ +

When set, this line is a horizontal separator rule (date change, unread marker). +The view regenerates it to the current viewport width instead of word-wrapping.

+
+
+ +
+
public string? RuleLabel { get; set; }
+
+ + + + + +

Property Value

+
+
string
+
+
+ + + + + + + +

diff --git a/api/client/EchoHub.Client.UI.Chat.ChatMessageManager.html b/api/client/EchoHub.Client.UI.Chat.ChatMessageManager.html index a266eb2..7fbe773 100644 --- a/api/client/EchoHub.Client.UI.Chat.ChatMessageManager.html +++ b/api/client/EchoHub.Client.UI.Chat.ChatMessageManager.html @@ -178,6 +178,72 @@ so the UI layer can refresh.

+

Fields +

+ + + +

+ ContentIndentCols + +

+ +

Columns before message text starts: "HH:mm " + nick column + " │ ".

+
+
+ +
+
public const int ContentIndentCols = 21
+
+ + + + +

Field Value

+
+
int
+
+
+ + + + + + + + + + +

+ NickColWidth + +

+ +

Columns reserved for the right-aligned nick column (WeeChat-style).

+
+
+ +
+
public const int NickColWidth = 12
+
+ + + + +

Field Value

+
+
int
+
+
+ + + + + + + + +

Properties

@@ -245,6 +311,71 @@ so the UI layer can refresh.

+ + +

+ LastReadIds + +

+ +

Last message the user has read per channel — persisted by the orchestrator so +unread/mention state can be seeded from history on the next connect.

+
+
+ +
+
public IReadOnlyDictionary<string, Guid> LastReadIds { get; }
+
+ + + + + +

Property Value

+
+
IReadOnlyDictionary<string, Guid>
+
+
+ + + + + + + + + + +

+ MentionChannels + +

+ +

Channels with an unread @mention of the current user (cleared by ClearUnread(string)).

+
+
+ +
+
public IReadOnlySet<string> MentionChannels { get; }
+
+ + + + + +

Property Value

+
+
IReadOnlySet<string>
+
+
+ + + + + + + +

Methods

@@ -515,17 +646,20 @@ so the UI layer can refresh.

-

- LoadHistory(string, List<MessageDto>) +

+ LoadHistory(string, List<MessageDto>, Guid?)

-

Load historical messages into a channel, replacing any existing messages.

+

Load historical messages into a channel, replacing any existing messages. +When lastReadId is given (persisted from a previous session), +messages after it seed the unread count, @mention highlight, and the +"new messages" marker — so activity that happened while offline still lights up.

-
public void LoadHistory(string channelName, List<MessageDto> messages)
+
public void LoadHistory(string channelName, List<MessageDto> messages, Guid? lastReadId = null)

Parameters

@@ -534,6 +668,8 @@ so the UI layer can refresh.

messages List<MessageDto>
+
lastReadId Guid?
+
diff --git a/api/client/EchoHub.Client.UI.Dialogs.html b/api/client/EchoHub.Client.UI.Dialogs.html index c8098fa..dafb08b 100644 --- a/api/client/EchoHub.Client.UI.Dialogs.html +++ b/api/client/EchoHub.Client.UI.Dialogs.html @@ -162,10 +162,6 @@ Shows Edit Profile / Set Status buttons when viewing own profile.

UpdateConfirmDialog
-
-
UpdateProgressDialog
-
-

Enums

diff --git a/api/client/EchoHub.Client.UI.Dialogs.UpdateProgressDialog.html b/api/client/EchoHub.Client.UI.Helpers.NickColorHelper.html similarity index 60% rename from api/client/EchoHub.Client.UI.Dialogs.UpdateProgressDialog.html rename to api/client/EchoHub.Client.UI.Helpers.NickColorHelper.html index bbfe54d..93cbe48 100644 --- a/api/client/EchoHub.Client.UI.Dialogs.UpdateProgressDialog.html +++ b/api/client/EchoHub.Client.UI.Helpers.NickColorHelper.html @@ -2,11 +2,11 @@ - Class UpdateProgressDialog | EchoHub Documentation + Class NickColorHelper | EchoHub Documentation - - + + @@ -16,7 +16,7 @@ - + @@ -84,24 +84,27 @@
-
+
-

-Class UpdateProgressDialog +

+Class NickColorHelper

-
Namespace
EchoHub.Client.UI.Dialogs
+
Namespace
EchoHub.Client.UI.Helpers
Assembly
EchoHub.Client.dll
-
+

Deterministic per-nick colors for users who haven't picked a nickname color. +The same nick always maps to the same palette entry (classic IRC client behavior), +so a busy channel stays scannable without any configuration.

+
-
public sealed class UpdateProgressDialog
+
public static class NickColorHelper
@@ -111,7 +114,7 @@ Class UpdateProgressDialog object -
UpdateProgressDialog
+
NickColorHelper
@@ -123,6 +126,9 @@ Class UpdateProgressDialog object.GetType() +
+ object.MemberwiseClone() +
object.ToString()
@@ -145,121 +151,78 @@ Class UpdateProgressDialog Constructors - - - - - -

- UpdateProgressDialog(IApplication, string) - -

- -
-
- -
-
public UpdateProgressDialog(IApplication app, string newVersion)
-
- -

Parameters

-
-
app IApplication
-
-
newVersion string
-
-
- - - - - - - - - - - -

Methods

- + -

- Close() - +

+ GetAttribute(string) +

-
+

The color attribute for a nick. Used as a fallback when the user has no +explicit nickname color set.

+
-
public void Close()
-
- - - - - - - - - - - - - - - -

- Show() - -

- -
-
- -
-
public void Show()
-
- - - - - - - - - - - - - - - -

- UpdateProgress(float, string) - -

- -
-
- -
-
public void UpdateProgress(float fraction, string statusText)
+
public static Attribute GetAttribute(string nick)

Parameters

-
fraction float
-
-
statusText string
+
nick string
+

Returns

+
+
Attribute
+
+
+ + + + + + + + + + + + + +

+ GetPaletteIndex(string, int) + +

+ +

Stable palette index for a nick: case-insensitive FNV-1a over the nick, +reduced modulo paletteSize. Pure function (no Terminal.Gui +types) so it is unit-testable without a display driver.

+
+
+ +
+
public static int GetPaletteIndex(string nick, int paletteSize)
+
+ +

Parameters

+
+
nick string
+
+
paletteSize int
+
+
+ +

Returns

+
+
int
+
+
@@ -275,7 +238,7 @@ Class UpdateProgressDialog - Edit this page + Edit this page diff --git a/api/client/EchoHub.Client.UI.Helpers.html b/api/client/EchoHub.Client.UI.Helpers.html index c9f23d0..c672aa3 100644 --- a/api/client/EchoHub.Client.UI.Helpers.html +++ b/api/client/EchoHub.Client.UI.Helpers.html @@ -111,6 +111,13 @@ so we replace them with fixed-width ASCII shortcodes for display only.

HexColorHelper

Helper to parse hex colors to Terminal.Gui Attributes.

+
+
+
+
NickColorHelper
+

Deterministic per-nick colors for users who haven't picked a nickname color. +The same nick always maps to the same palette entry (classic IRC client behavior), +so a busy channel stays scannable without any configuration.

diff --git a/api/client/EchoHub.Client.UI.ListSources.ChannelListSource.html b/api/client/EchoHub.Client.UI.ListSources.ChannelListSource.html index 91e77d9..8267cfd 100644 --- a/api/client/EchoHub.Client.UI.ListSources.ChannelListSource.html +++ b/api/client/EchoHub.Client.UI.ListSources.ChannelListSource.html @@ -459,8 +459,8 @@ Active channel gets a > indicator, unread channels are bright with a count ba -

- Update(List<string>, Dictionary<string, int>, string, IReadOnlySet<string>?) +

+ Update(List<string>, Dictionary<string, int>, string, IReadOnlySet<string>?, IReadOnlySet<string>?)

@@ -468,7 +468,7 @@ Active channel gets a > indicator, unread channels are bright with a count ba
-
public void Update(List<string> channels, Dictionary<string, int> unread, string activeChannel, IReadOnlySet<string>? protectedChannels = null)
+
public void Update(List<string> channels, Dictionary<string, int> unread, string activeChannel, IReadOnlySet<string>? protectedChannels = null, IReadOnlySet<string>? mentionChannels = null)

Parameters

@@ -481,6 +481,8 @@ Active channel gets a > indicator, unread channels are bright with a count ba
protectedChannels IReadOnlySet<string>
+
mentionChannels IReadOnlySet<string>
+
diff --git a/api/core/EchoHub.Core.Contracts.IChannelService.html b/api/core/EchoHub.Core.Contracts.IChannelService.html index 9eb6fe7..c529e2e 100644 --- a/api/core/EchoHub.Core.Contracts.IChannelService.html +++ b/api/core/EchoHub.Core.Contracts.IChannelService.html @@ -385,6 +385,42 @@ Interface IChannelService + +

+ GetChannelMetaAsync(string) + +

+ +
+
+ +
+
Task<ChannelMetaDto?> GetChannelMetaAsync(string channelName)
+
+ +

Parameters

+
+
channelName string
+
+
+ +

Returns

+
+
Task<ChannelMetaDto>
+
+
+ + + + + + + + + + +

diff --git a/api/core/EchoHub.Core.Contracts.IMessageEncryptionService.html b/api/core/EchoHub.Core.Contracts.IMessageEncryptionService.html index 9075f28..f7ef036 100644 --- a/api/core/EchoHub.Core.Contracts.IMessageEncryptionService.html +++ b/api/core/EchoHub.Core.Contracts.IMessageEncryptionService.html @@ -116,6 +116,42 @@ Interface IMessageEncryptionService Fields +

+ + + +

+ CiphertextPrefix + +

+ +

Prefix marking transport/at-rest encrypted content. Decrypt(string) is a +pass-through for values without it.

+
+
+ +
+
public const string CiphertextPrefix = "$ENC$v1$"
+
+ + + + +

Field Value

+
+
string
+
+
+ + + + + + + + +

Properties

diff --git a/api/core/EchoHub.Core.DTOs.ChannelMetaDto.html b/api/core/EchoHub.Core.DTOs.ChannelMetaDto.html new file mode 100644 index 0000000..f59398d --- /dev/null +++ b/api/core/EchoHub.Core.DTOs.ChannelMetaDto.html @@ -0,0 +1,878 @@ + + + + + Class ChannelMetaDto | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ + + +

+Class ChannelMetaDto +

+ +
+
Namespace
EchoHub.Core.DTOs
+
Assembly
EchoHub.Core.dll
+
+ +

Human-facing summary of a channel (the /meta command). For encrypted channels the +server still knows these figures — count, timestamps, and stored blob sizes — even though it +cannot read the content itself. EstimatedSizeBytes is the sum of stored +attachment blob sizes plus message text length, so it is an estimate, not an exact on-disk total.

+
+
+ +
+
public record ChannelMetaDto : IEquatable<ChannelMetaDto>
+
+ + + + +
+
Inheritance
+
+ +
ChannelMetaDto
+
+
+ +
+
Implements
+
+ +
+
+ + +
+
Inherited Members
+
+ + + + +
+ + + + + + +

Constructors +

+ + + + +

+ ChannelMetaDto(ChannelMetaDto) + +

+ +
+
+ +
+
protected ChannelMetaDto(ChannelMetaDto original)
+
+ +

Parameters

+
+
original ChannelMetaDto
+
+
+ + + + + + + + + + + + + + +

+ ChannelMetaDto(Guid, string, string?, bool, bool, int, int, long, DateTimeOffset) + +

+ +

Human-facing summary of a channel (the /meta command). For encrypted channels the +server still knows these figures — count, timestamps, and stored blob sizes — even though it +cannot read the content itself. EstimatedSizeBytes is the sum of stored +attachment blob sizes plus message text length, so it is an estimate, not an exact on-disk total.

+
+
+ +
+
public ChannelMetaDto(Guid Id, string Name, string? Topic, bool IsEncrypted, bool IsProtected, int MessageCount, int UniqueUserCount, long EstimatedSizeBytes, DateTimeOffset CreatedAt)
+
+ +

Parameters

+
+
Id Guid
+
+
Name string
+
+
Topic string
+
+
IsEncrypted bool
+
+
IsProtected bool
+
+
MessageCount int
+
+
UniqueUserCount int
+
+
EstimatedSizeBytes long
+
+
CreatedAt DateTimeOffset
+
+
+ + + + + + + + + + + + +

Properties +

+ + + + +

+ CreatedAt + +

+ +
+
+ +
+
public DateTimeOffset CreatedAt { get; init; }
+
+ + + + + +

Property Value

+
+
DateTimeOffset
+
+
+ + + + + + + + + + +

+ EqualityContract + +

+ +
+
+ +
+
protected virtual Type EqualityContract { get; }
+
+ + + + + +

Property Value

+
+
Type
+
+
+ + + + + + + + + + +

+ EstimatedSizeBytes + +

+ +
+
+ +
+
public long EstimatedSizeBytes { get; init; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ Id + +

+ +
+
+ +
+
public Guid Id { get; init; }
+
+ + + + + +

Property Value

+
+
Guid
+
+
+ + + + + + + + + + +

+ IsEncrypted + +

+ +
+
+ +
+
public bool IsEncrypted { get; init; }
+
+ + + + + +

Property Value

+
+
bool
+
+
+ + + + + + + + + + +

+ IsProtected + +

+ +
+
+ +
+
public bool IsProtected { get; init; }
+
+ + + + + +

Property Value

+
+
bool
+
+
+ + + + + + + + + + +

+ MessageCount + +

+ +
+
+ +
+
public int MessageCount { get; init; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ Name + +

+ +
+
+ +
+
public string Name { get; init; }
+
+ + + + + +

Property Value

+
+
string
+
+
+ + + + + + + + + + +

+ Topic + +

+ +
+
+ +
+
public string? Topic { get; init; }
+
+ + + + + +

Property Value

+
+
string
+
+
+ + + + + + + + + + +

+ UniqueUserCount + +

+ +
+
+ +
+
public int UniqueUserCount { get; init; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + +

Methods +

+ + + + +

+ Deconstruct(out Guid, out string, out string?, out bool, out bool, out int, out int, out long, out DateTimeOffset) + +

+ +
+
+ +
+
public void Deconstruct(out Guid Id, out string Name, out string? Topic, out bool IsEncrypted, out bool IsProtected, out int MessageCount, out int UniqueUserCount, out long EstimatedSizeBytes, out DateTimeOffset CreatedAt)
+
+ +

Parameters

+
+
Id Guid
+
+
Name string
+
+
Topic string
+
+
IsEncrypted bool
+
+
IsProtected bool
+
+
MessageCount int
+
+
UniqueUserCount int
+
+
EstimatedSizeBytes long
+
+
CreatedAt DateTimeOffset
+
+
+ + + + + + + + + + + + + + +

+ Equals(ChannelMetaDto?) + +

+ +
+
+ +
+
public virtual bool Equals(ChannelMetaDto? other)
+
+ +

Parameters

+
+
other ChannelMetaDto
+
+
+ +

Returns

+
+
bool
+
+
+ + + + + + + + + + + + + +

+ Equals(object?) + +

+ +
+
+ +
+
public override bool Equals(object? obj)
+
+ +

Parameters

+
+
obj object
+
+
+ +

Returns

+
+
bool
+
+
+ + + + + + + + + + + + + +

+ GetHashCode() + +

+ +
+
+ +
+
public override int GetHashCode()
+
+ + +

Returns

+
+
int
+
+
+ + + + + + + + + + + + + +

+ PrintMembers(StringBuilder) + +

+ +
+
+ +
+
protected virtual bool PrintMembers(StringBuilder builder)
+
+ +

Parameters

+
+
builder StringBuilder
+
+
+ +

Returns

+
+
bool
+
+
+ + + + + + + + + + + + + +

+ ToString() + +

+ +
+
+ +
+
public override string ToString()
+
+ + +

Returns

+
+
string
+
+
+ + + + + + + + + + + +

Operators +

+ + + + +

+ operator ==(ChannelMetaDto?, ChannelMetaDto?) + +

+ +
+
+ +
+
public static bool operator ==(ChannelMetaDto? left, ChannelMetaDto? right)
+
+ +

Parameters

+
+
left ChannelMetaDto
+
+
right ChannelMetaDto
+
+
+ +

Returns

+
+
bool
+
+
+ + + + + + + + + + + + + +

+ operator !=(ChannelMetaDto?, ChannelMetaDto?) + +

+ +
+
+ +
+
public static bool operator !=(ChannelMetaDto? left, ChannelMetaDto? right)
+
+ +

Parameters

+
+
left ChannelMetaDto
+
+
right ChannelMetaDto
+
+
+ +

Returns

+
+
bool
+
+
+ + + + + + + + + + + + +
+ + + + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/core/EchoHub.Core.DTOs.html b/api/core/EchoHub.Core.DTOs.html index 4944bb3..4692b85 100644 --- a/api/core/EchoHub.Core.DTOs.html +++ b/api/core/EchoHub.Core.DTOs.html @@ -131,6 +131,14 @@ credential from a passphrase. Never includes the wrapped room key.

ChannelDto
+
+
ChannelMetaDto
+

Human-facing summary of a channel (the /meta command). For encrypted channels the +server still knows these figures — count, timestamps, and stored blob sizes — even though it +cannot read the content itself. EstimatedSizeBytes is the sum of stored +attachment blob sizes plus message text length, so it is an estimate, not an exact on-disk total.

+
+
ChannelOperationResult
diff --git a/api/server/EchoHub.Server.Config.UploadLimits.html b/api/server/EchoHub.Server.Config.UploadLimits.html new file mode 100644 index 0000000..69864cc --- /dev/null +++ b/api/server/EchoHub.Server.Config.UploadLimits.html @@ -0,0 +1,564 @@ + + + + + Class UploadLimits | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ + + +

+Class UploadLimits +

+ +
+
Namespace
EchoHub.Server.Config
+
Assembly
EchoHub.Server.dll
+
+ +

Admin-configurable upload limits, bound from the Uploads configuration section. +Sizes are expressed in megabytes in configuration; the *Bytes accessors convert them +for enforcement. Every default mirrors HubConstants so an absent or partial +Uploads section preserves the historical built-in limits.

+
+
+ +
+
public sealed class UploadLimits
+
+ + + + +
+
Inheritance
+
+ +
UploadLimits
+
+
+ + + +
+
Inherited Members
+
+ + + + + + +
+ + + + + + +

Constructors +

+ + + + +

+ UploadLimits() + +

+ +
+
+ +
+
public UploadLimits()
+
+ + + + + + + + + + + + + +

Properties +

+ + + + +

+ MaxAttachmentsPerMessage + +

+ +
+
+ +
+
public int MaxAttachmentsPerMessage { get; init; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ MaxAudioSizeBytes + +

+ +
+
+ +
+
public long MaxAudioSizeBytes { get; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ MaxAudioSizeMB + +

+ +
+
+ +
+
public int MaxAudioSizeMB { get; init; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ MaxAvatarSizeBytes + +

+ +
+
+ +
+
public long MaxAvatarSizeBytes { get; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ MaxAvatarSizeMB + +

+ +
+
+ +
+
public int MaxAvatarSizeMB { get; init; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ MaxFileSizeBytes + +

+ +
+
+ +
+
public long MaxFileSizeBytes { get; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ MaxFileSizeMB + +

+ +
+
+ +
+
public int MaxFileSizeMB { get; init; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ MaxImageSizeBytes + +

+ +
+
+ +
+
public long MaxImageSizeBytes { get; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + + + +

+ MaxImageSizeMB + +

+ +
+
+ +
+
public int MaxImageSizeMB { get; init; }
+
+ + + + + +

Property Value

+
+
int
+
+
+ + + + + + + + + + +

+ MaxRequestBodyBytes + +

+ +

Absolute ceiling for one message request body (largest file × the attachment cap). Used to +size the request-body and multipart limits so a configured increase actually takes effect.

+
+
+ +
+
public long MaxRequestBodyBytes { get; }
+
+ + + + + +

Property Value

+
+
long
+
+
+ + + + + + + + +

Methods +

+ + + + +

+ MaxForKind(AttachmentKind) + +

+ +

Maximum accepted size for a single attachment of the given kind.

+
+
+ +
+
public long MaxForKind(AttachmentKind kind)
+
+ +

Parameters

+
+
kind AttachmentKind
+
+
+ +

Returns

+
+
long
+
+
+ + + + + + + + + + + + +
+ + + + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/server/EchoHub.Server.Config.html b/api/server/EchoHub.Server.Config.html new file mode 100644 index 0000000..544abc8 --- /dev/null +++ b/api/server/EchoHub.Server.Config.html @@ -0,0 +1,130 @@ + + + + + Namespace EchoHub.Server.Config | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+
+
+
Table of Contents
+ +
+
+ +
+
+
+ +
+
+ + + +
+ +
+ +

Namespace EchoHub.Server.Config

+
+
+
+ +

+Classes +

+
+
UploadLimits
+

Admin-configurable upload limits, bound from the Uploads configuration section. +Sizes are expressed in megabytes in configuration; the *Bytes accessors convert them +for enforcement. Every default mirrors HubConstants so an absent or partial +Uploads section preserves the historical built-in limits.

+
+
+ + +
+ +
+
+ + +
+ +
+ +
+
+ +
+ + + + diff --git a/api/server/EchoHub.Server.Controllers.ChannelsController.html b/api/server/EchoHub.Server.Controllers.ChannelsController.html index b951f2b..4212b3c 100644 --- a/api/server/EchoHub.Server.Controllers.ChannelsController.html +++ b/api/server/EchoHub.Server.Controllers.ChannelsController.html @@ -159,8 +159,8 @@ public class ChannelsController : ControllerBase -

- ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService) +

+ ChannelsController(IChannelService, EchoHubDbContext, FileStorageService, ImageToAsciiService, IHttpClientFactory, IChatService, IMessageEncryptionService, UploadLimits)

@@ -168,7 +168,7 @@ public class ChannelsController : ControllerBase
-
public ChannelsController(IChannelService channelService, EchoHubDbContext db, FileStorageService fileStorage, ImageToAsciiService asciiService, IHttpClientFactory httpClientFactory, IChatService chatService, IMessageEncryptionService encryption)
+
public ChannelsController(IChannelService channelService, EchoHubDbContext db, FileStorageService fileStorage, ImageToAsciiService asciiService, IHttpClientFactory httpClientFactory, IChatService chatService, IMessageEncryptionService encryption, UploadLimits uploadLimits)

Parameters

@@ -187,6 +187,8 @@ public class ChannelsController : ControllerBase
encryption IMessageEncryptionService
+
uploadLimits UploadLimits
+
@@ -318,6 +320,46 @@ public Task<IActionResult> GetChannelCrypto(string channel) + + +

+ GetChannelMeta(string) + +

+ +

Human-facing summary of a channel (message count, unique posters, estimated size, +created date, room id). Available for encrypted channels too — these are metadata the +server tracks even though it cannot read the messages themselves.

+
+
+ +
+
[HttpGet("{channel}/meta")]
+public Task<IActionResult> GetChannelMeta(string channel)
+
+ +

Parameters

+
+
channel string
+
+
+ +

Returns

+
+
Task<IActionResult>
+
+
+ + + + + + + + + + +

@@ -417,8 +459,6 @@ room-encrypted preview (preview), aligned by file order — the ser
[HttpPost("{channel}/messages")]
 [EnableRateLimiting("upload")]
-[RequestSizeLimit(1048576000)]
-[RequestFormLimits(MultipartBodyLengthLimit = 1048576000)]
 public Task<IActionResult> SendMessageWithAttachments(string channel, string? size = null)
diff --git a/api/server/EchoHub.Server.Controllers.UsersController.html b/api/server/EchoHub.Server.Controllers.UsersController.html index 969d230..59588f2 100644 --- a/api/server/EchoHub.Server.Controllers.UsersController.html +++ b/api/server/EchoHub.Server.Controllers.UsersController.html @@ -159,8 +159,8 @@ public class UsersController : ControllerBase -

- UsersController(IUserService, ImageToAsciiService) +

+ UsersController(IUserService, ImageToAsciiService, UploadLimits)

@@ -168,7 +168,7 @@ public class UsersController : ControllerBase
-
public UsersController(IUserService userService, ImageToAsciiService asciiService)
+
public UsersController(IUserService userService, ImageToAsciiService asciiService, UploadLimits uploadLimits)

Parameters

@@ -177,6 +177,8 @@ public class UsersController : ControllerBase
asciiService ImageToAsciiService
+
uploadLimits UploadLimits
+
diff --git a/api/server/EchoHub.Server.Services.ChannelService.html b/api/server/EchoHub.Server.Services.ChannelService.html index 3230cbe..f9768dc 100644 --- a/api/server/EchoHub.Server.Services.ChannelService.html +++ b/api/server/EchoHub.Server.Services.ChannelService.html @@ -462,6 +462,42 @@ Class ChannelService + +

+ GetChannelMetaAsync(string) + +

+ +
+
+ +
+
public Task<ChannelMetaDto?> GetChannelMetaAsync(string channelName)
+
+ +

Parameters

+
+
channelName string
+
+
+ +

Returns

+
+
Task<ChannelMetaDto>
+
+
+ + + + + + + + + + +

diff --git a/api/toc.html b/api/toc.html index e3066f2..7dad86e 100644 --- a/api/toc.html +++ b/api/toc.html @@ -229,9 +229,6 @@
  • UpdateConfirmDialog
  • -
  • - UpdateProgressDialog -
  • @@ -248,6 +245,9 @@
  • HexColorHelper
  • +
  • + NickColorHelper +
  • @@ -363,6 +363,9 @@
  • ChannelError
  • +
  • + ChannelMetaDto +
  • ChannelOperationResult
  • @@ -540,6 +543,16 @@ +
  • + + EchoHub.Server.Config + + +
  • EchoHub.Server.Controllers diff --git a/api/toc.json b/api/toc.json index c755f2b..9cce285 100644 --- a/api/toc.json +++ b/api/toc.json @@ -1,2 +1,2 @@ -{"items":[{"name":"Client","items":[{"name":"API Reference","includedFrom":"~/_api_meta/client/toc.yml","items":[{"name":"EchoHub.Client","href":"client/EchoHub.Client.html","topicHref":"client/EchoHub.Client.html","topicUid":"EchoHub.Client","type":"Namespace","items":[{"name":"AppOrchestrator","href":"client/EchoHub.Client.AppOrchestrator.html","topicHref":"client/EchoHub.Client.AppOrchestrator.html","topicUid":"EchoHub.Client.AppOrchestrator","type":"Class"}]},{"name":"EchoHub.Client.Commands","href":"client/EchoHub.Client.Commands.html","topicHref":"client/EchoHub.Client.Commands.html","topicUid":"EchoHub.Client.Commands","type":"Namespace","items":[{"name":"CommandHandler","href":"client/EchoHub.Client.Commands.CommandHandler.html","topicHref":"client/EchoHub.Client.Commands.CommandHandler.html","topicUid":"EchoHub.Client.Commands.CommandHandler","type":"Class"},{"name":"CommandResult","href":"client/EchoHub.Client.Commands.CommandResult.html","topicHref":"client/EchoHub.Client.Commands.CommandResult.html","topicUid":"EchoHub.Client.Commands.CommandResult","type":"Class"}]},{"name":"EchoHub.Client.Config","href":"client/EchoHub.Client.Config.html","topicHref":"client/EchoHub.Client.Config.html","topicUid":"EchoHub.Client.Config","type":"Namespace","items":[{"name":"AccountPreset","href":"client/EchoHub.Client.Config.AccountPreset.html","topicHref":"client/EchoHub.Client.Config.AccountPreset.html","topicUid":"EchoHub.Client.Config.AccountPreset","type":"Class"},{"name":"ClientConfig","href":"client/EchoHub.Client.Config.ClientConfig.html","topicHref":"client/EchoHub.Client.Config.ClientConfig.html","topicUid":"EchoHub.Client.Config.ClientConfig","type":"Class"},{"name":"ConfigManager","href":"client/EchoHub.Client.Config.ConfigManager.html","topicHref":"client/EchoHub.Client.Config.ConfigManager.html","topicUid":"EchoHub.Client.Config.ConfigManager","type":"Class"},{"name":"NotificationConfig","href":"client/EchoHub.Client.Config.NotificationConfig.html","topicHref":"client/EchoHub.Client.Config.NotificationConfig.html","topicUid":"EchoHub.Client.Config.NotificationConfig","type":"Class"},{"name":"SavedServer","href":"client/EchoHub.Client.Config.SavedServer.html","topicHref":"client/EchoHub.Client.Config.SavedServer.html","topicUid":"EchoHub.Client.Config.SavedServer","type":"Class"}]},{"name":"EchoHub.Client.Services","href":"client/EchoHub.Client.Services.html","topicHref":"client/EchoHub.Client.Services.html","topicUid":"EchoHub.Client.Services","type":"Namespace","items":[{"name":"ApiClient","href":"client/EchoHub.Client.Services.ApiClient.html","topicHref":"client/EchoHub.Client.Services.ApiClient.html","topicUid":"EchoHub.Client.Services.ApiClient","type":"Class"},{"name":"AsyncRunner","href":"client/EchoHub.Client.Services.AsyncRunner.html","topicHref":"client/EchoHub.Client.Services.AsyncRunner.html","topicUid":"EchoHub.Client.Services.AsyncRunner","type":"Class"},{"name":"AudioPlaybackService","href":"client/EchoHub.Client.Services.AudioPlaybackService.html","topicHref":"client/EchoHub.Client.Services.AudioPlaybackService.html","topicUid":"EchoHub.Client.Services.AudioPlaybackService","type":"Class"},{"name":"BackupInfo","href":"client/EchoHub.Client.Services.BackupInfo.html","topicHref":"client/EchoHub.Client.Services.BackupInfo.html","topicUid":"EchoHub.Client.Services.BackupInfo","type":"Class"},{"name":"ChannelPasswordRequiredException","href":"client/EchoHub.Client.Services.ChannelPasswordRequiredException.html","topicHref":"client/EchoHub.Client.Services.ChannelPasswordRequiredException.html","topicUid":"EchoHub.Client.Services.ChannelPasswordRequiredException","type":"Class"},{"name":"ClientEncryptionService","href":"client/EchoHub.Client.Services.ClientEncryptionService.html","topicHref":"client/EchoHub.Client.Services.ClientEncryptionService.html","topicUid":"EchoHub.Client.Services.ClientEncryptionService","type":"Class"},{"name":"ClipboardFiles","href":"client/EchoHub.Client.Services.ClipboardFiles.html","topicHref":"client/EchoHub.Client.Services.ClipboardFiles.html","topicUid":"EchoHub.Client.Services.ClipboardFiles","type":"Class"},{"name":"EchoHubConnection","href":"client/EchoHub.Client.Services.EchoHubConnection.html","topicHref":"client/EchoHub.Client.Services.EchoHubConnection.html","topicUid":"EchoHub.Client.Services.EchoHubConnection","type":"Class"},{"name":"FolderPickResult","href":"client/EchoHub.Client.Services.FolderPickResult.html","topicHref":"client/EchoHub.Client.Services.FolderPickResult.html","topicUid":"EchoHub.Client.Services.FolderPickResult","type":"Class"},{"name":"JoinOutcome","href":"client/EchoHub.Client.Services.JoinOutcome.html","topicHref":"client/EchoHub.Client.Services.JoinOutcome.html","topicUid":"EchoHub.Client.Services.JoinOutcome","type":"Class"},{"name":"NativeFolderPicker","href":"client/EchoHub.Client.Services.NativeFolderPicker.html","topicHref":"client/EchoHub.Client.Services.NativeFolderPicker.html","topicUid":"EchoHub.Client.Services.NativeFolderPicker","type":"Class"},{"name":"NotificationSoundService","href":"client/EchoHub.Client.Services.NotificationSoundService.html","topicHref":"client/EchoHub.Client.Services.NotificationSoundService.html","topicUid":"EchoHub.Client.Services.NotificationSoundService","type":"Class"},{"name":"OutgoingAttachment","href":"client/EchoHub.Client.Services.OutgoingAttachment.html","topicHref":"client/EchoHub.Client.Services.OutgoingAttachment.html","topicUid":"EchoHub.Client.Services.OutgoingAttachment","type":"Class"},{"name":"PathSetup","href":"client/EchoHub.Client.Services.PathSetup.html","topicHref":"client/EchoHub.Client.Services.PathSetup.html","topicUid":"EchoHub.Client.Services.PathSetup","type":"Class"},{"name":"PickerOutcome","href":"client/EchoHub.Client.Services.PickerOutcome.html","topicHref":"client/EchoHub.Client.Services.PickerOutcome.html","topicUid":"EchoHub.Client.Services.PickerOutcome","type":"Enum"},{"name":"RoomKeyStore","href":"client/EchoHub.Client.Services.RoomKeyStore.html","topicHref":"client/EchoHub.Client.Services.RoomKeyStore.html","topicUid":"EchoHub.Client.Services.RoomKeyStore","type":"Class"},{"name":"UpdateBackupService","href":"client/EchoHub.Client.Services.UpdateBackupService.html","topicHref":"client/EchoHub.Client.Services.UpdateBackupService.html","topicUid":"EchoHub.Client.Services.UpdateBackupService","type":"Class"},{"name":"UpdateChecker","href":"client/EchoHub.Client.Services.UpdateChecker.html","topicHref":"client/EchoHub.Client.Services.UpdateChecker.html","topicUid":"EchoHub.Client.Services.UpdateChecker","type":"Class"}]},{"name":"EchoHub.Client.Themes","href":"client/EchoHub.Client.Themes.html","topicHref":"client/EchoHub.Client.Themes.html","topicUid":"EchoHub.Client.Themes","type":"Namespace","items":[{"name":"Theme","href":"client/EchoHub.Client.Themes.Theme.html","topicHref":"client/EchoHub.Client.Themes.Theme.html","topicUid":"EchoHub.Client.Themes.Theme","type":"Class"},{"name":"ThemeColors","href":"client/EchoHub.Client.Themes.ThemeColors.html","topicHref":"client/EchoHub.Client.Themes.ThemeColors.html","topicUid":"EchoHub.Client.Themes.ThemeColors","type":"Class"},{"name":"ThemeManager","href":"client/EchoHub.Client.Themes.ThemeManager.html","topicHref":"client/EchoHub.Client.Themes.ThemeManager.html","topicUid":"EchoHub.Client.Themes.ThemeManager","type":"Class"}]},{"name":"EchoHub.Client.UI","href":"client/EchoHub.Client.UI.html","topicHref":"client/EchoHub.Client.UI.html","topicUid":"EchoHub.Client.UI","type":"Namespace","items":[{"name":"MainWindow","href":"client/EchoHub.Client.UI.MainWindow.html","topicHref":"client/EchoHub.Client.UI.MainWindow.html","topicUid":"EchoHub.Client.UI.MainWindow","type":"Class"}]},{"name":"EchoHub.Client.UI.Chat","href":"client/EchoHub.Client.UI.Chat.html","topicHref":"client/EchoHub.Client.UI.Chat.html","topicUid":"EchoHub.Client.UI.Chat","type":"Namespace","items":[{"name":"ChatColors","href":"client/EchoHub.Client.UI.Chat.ChatColors.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatColors.html","topicUid":"EchoHub.Client.UI.Chat.ChatColors","type":"Class"},{"name":"ChatLine","href":"client/EchoHub.Client.UI.Chat.ChatLine.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatLine.html","topicUid":"EchoHub.Client.UI.Chat.ChatLine","type":"Class"},{"name":"ChatListSource","href":"client/EchoHub.Client.UI.Chat.ChatListSource.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatListSource.html","topicUid":"EchoHub.Client.UI.Chat.ChatListSource","type":"Class"},{"name":"ChatMessageManager","href":"client/EchoHub.Client.UI.Chat.ChatMessageManager.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatMessageManager.html","topicUid":"EchoHub.Client.UI.Chat.ChatMessageManager","type":"Class"},{"name":"ChatSegment","href":"client/EchoHub.Client.UI.Chat.ChatSegment.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatSegment.html","topicUid":"EchoHub.Client.UI.Chat.ChatSegment","type":"Class"}]},{"name":"EchoHub.Client.UI.Dialogs","href":"client/EchoHub.Client.UI.Dialogs.html","topicHref":"client/EchoHub.Client.UI.Dialogs.html","topicUid":"EchoHub.Client.UI.Dialogs","type":"Namespace","items":[{"name":"AudioPlayerDialog","href":"client/EchoHub.Client.UI.Dialogs.AudioPlayerDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.AudioPlayerDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.AudioPlayerDialog","type":"Class"},{"name":"ChannelPasswordDialog","href":"client/EchoHub.Client.UI.Dialogs.ChannelPasswordDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ChannelPasswordDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ChannelPasswordDialog","type":"Class"},{"name":"ConnectDialog","href":"client/EchoHub.Client.UI.Dialogs.ConnectDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ConnectDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ConnectDialog","type":"Class"},{"name":"ConnectDialogResult","href":"client/EchoHub.Client.UI.Dialogs.ConnectDialogResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ConnectDialogResult.html","topicUid":"EchoHub.Client.UI.Dialogs.ConnectDialogResult","type":"Class"},{"name":"CreateChannelDialog","href":"client/EchoHub.Client.UI.Dialogs.CreateChannelDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.CreateChannelDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.CreateChannelDialog","type":"Class"},{"name":"CreateChannelResult","href":"client/EchoHub.Client.UI.Dialogs.CreateChannelResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.CreateChannelResult.html","topicUid":"EchoHub.Client.UI.Dialogs.CreateChannelResult","type":"Class"},{"name":"ProfileAction","href":"client/EchoHub.Client.UI.Dialogs.ProfileAction.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileAction.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileAction","type":"Enum"},{"name":"ProfileEditDialog","href":"client/EchoHub.Client.UI.Dialogs.ProfileEditDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileEditDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileEditDialog","type":"Class"},{"name":"ProfileEditResult","href":"client/EchoHub.Client.UI.Dialogs.ProfileEditResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileEditResult.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileEditResult","type":"Class"},{"name":"ProfileViewDialog","href":"client/EchoHub.Client.UI.Dialogs.ProfileViewDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileViewDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileViewDialog","type":"Class"},{"name":"SearchDialog","href":"client/EchoHub.Client.UI.Dialogs.SearchDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchDialog","type":"Class"},{"name":"SearchResult","href":"client/EchoHub.Client.UI.Dialogs.SearchResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchResult.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchResult","type":"Class"},{"name":"SearchResultType","href":"client/EchoHub.Client.UI.Dialogs.SearchResultType.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchResultType.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchResultType","type":"Enum"},{"name":"StatusDialog","href":"client/EchoHub.Client.UI.Dialogs.StatusDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.StatusDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.StatusDialog","type":"Class"},{"name":"StatusDialogResult","href":"client/EchoHub.Client.UI.Dialogs.StatusDialogResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.StatusDialogResult.html","topicUid":"EchoHub.Client.UI.Dialogs.StatusDialogResult","type":"Class"},{"name":"UpdateConfirmDialog","href":"client/EchoHub.Client.UI.Dialogs.UpdateConfirmDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.UpdateConfirmDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.UpdateConfirmDialog","type":"Class"},{"name":"UpdateProgressDialog","href":"client/EchoHub.Client.UI.Dialogs.UpdateProgressDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.UpdateProgressDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.UpdateProgressDialog","type":"Class"}]},{"name":"EchoHub.Client.UI.Helpers","href":"client/EchoHub.Client.UI.Helpers.html","topicHref":"client/EchoHub.Client.UI.Helpers.html","topicUid":"EchoHub.Client.UI.Helpers","type":"Namespace","items":[{"name":"DroppedFileParser","href":"client/EchoHub.Client.UI.Helpers.DroppedFileParser.html","topicHref":"client/EchoHub.Client.UI.Helpers.DroppedFileParser.html","topicUid":"EchoHub.Client.UI.Helpers.DroppedFileParser","type":"Class"},{"name":"EmojiHelper","href":"client/EchoHub.Client.UI.Helpers.EmojiHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.EmojiHelper.html","topicUid":"EchoHub.Client.UI.Helpers.EmojiHelper","type":"Class"},{"name":"HexColorHelper","href":"client/EchoHub.Client.UI.Helpers.HexColorHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.HexColorHelper.html","topicUid":"EchoHub.Client.UI.Helpers.HexColorHelper","type":"Class"}]},{"name":"EchoHub.Client.UI.ListSources","href":"client/EchoHub.Client.UI.ListSources.html","topicHref":"client/EchoHub.Client.UI.ListSources.html","topicUid":"EchoHub.Client.UI.ListSources","type":"Namespace","items":[{"name":"ChannelListSource","href":"client/EchoHub.Client.UI.ListSources.ChannelListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.ChannelListSource.html","topicUid":"EchoHub.Client.UI.ListSources.ChannelListSource","type":"Class"},{"name":"SearchListSource","href":"client/EchoHub.Client.UI.ListSources.SearchListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.SearchListSource.html","topicUid":"EchoHub.Client.UI.ListSources.SearchListSource","type":"Class"},{"name":"UserListSource","href":"client/EchoHub.Client.UI.ListSources.UserListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.UserListSource.html","topicUid":"EchoHub.Client.UI.ListSources.UserListSource","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/client-articles/toc.yml","items":[{"name":"Overview","href":"client-articles/index.html","topicHref":"client-articles/index.html"}]}]},{"name":"Core","items":[{"name":"API Reference","includedFrom":"~/_api_meta/core/toc.yml","items":[{"name":"EchoHub.Core.Constants","href":"core/EchoHub.Core.Constants.html","topicHref":"core/EchoHub.Core.Constants.html","topicUid":"EchoHub.Core.Constants","type":"Namespace","items":[{"name":"HubConstants","href":"core/EchoHub.Core.Constants.HubConstants.html","topicHref":"core/EchoHub.Core.Constants.HubConstants.html","topicUid":"EchoHub.Core.Constants.HubConstants","type":"Class"},{"name":"ValidationConstants","href":"core/EchoHub.Core.Constants.ValidationConstants.html","topicHref":"core/EchoHub.Core.Constants.ValidationConstants.html","topicUid":"EchoHub.Core.Constants.ValidationConstants","type":"Class"}]},{"name":"EchoHub.Core.Contracts","href":"core/EchoHub.Core.Contracts.html","topicHref":"core/EchoHub.Core.Contracts.html","topicUid":"EchoHub.Core.Contracts","type":"Namespace","items":[{"name":"ChannelListItem","href":"core/EchoHub.Core.Contracts.ChannelListItem.html","topicHref":"core/EchoHub.Core.Contracts.ChannelListItem.html","topicUid":"EchoHub.Core.Contracts.ChannelListItem","type":"Class"},{"name":"IChannelService","href":"core/EchoHub.Core.Contracts.IChannelService.html","topicHref":"core/EchoHub.Core.Contracts.IChannelService.html","topicUid":"EchoHub.Core.Contracts.IChannelService","type":"Interface"},{"name":"IChatBroadcaster","href":"core/EchoHub.Core.Contracts.IChatBroadcaster.html","topicHref":"core/EchoHub.Core.Contracts.IChatBroadcaster.html","topicUid":"EchoHub.Core.Contracts.IChatBroadcaster","type":"Interface"},{"name":"IChatService","href":"core/EchoHub.Core.Contracts.IChatService.html","topicHref":"core/EchoHub.Core.Contracts.IChatService.html","topicUid":"EchoHub.Core.Contracts.IChatService","type":"Interface"},{"name":"IEchoHubClient","href":"core/EchoHub.Core.Contracts.IEchoHubClient.html","topicHref":"core/EchoHub.Core.Contracts.IEchoHubClient.html","topicUid":"EchoHub.Core.Contracts.IEchoHubClient","type":"Interface"},{"name":"IMessageEncryptionService","href":"core/EchoHub.Core.Contracts.IMessageEncryptionService.html","topicHref":"core/EchoHub.Core.Contracts.IMessageEncryptionService.html","topicUid":"EchoHub.Core.Contracts.IMessageEncryptionService","type":"Interface"},{"name":"IUserService","href":"core/EchoHub.Core.Contracts.IUserService.html","topicHref":"core/EchoHub.Core.Contracts.IUserService.html","topicUid":"EchoHub.Core.Contracts.IUserService","type":"Interface"}]},{"name":"EchoHub.Core.DTOs","href":"core/EchoHub.Core.DTOs.html","topicHref":"core/EchoHub.Core.DTOs.html","topicUid":"EchoHub.Core.DTOs","type":"Namespace","items":[{"name":"ApiResponse","href":"core/EchoHub.Core.DTOs.ApiResponse.html","topicHref":"core/EchoHub.Core.DTOs.ApiResponse.html","topicUid":"EchoHub.Core.DTOs.ApiResponse","type":"Class"},{"name":"ApiResponse","href":"core/EchoHub.Core.DTOs.ApiResponse-1.html","topicHref":"core/EchoHub.Core.DTOs.ApiResponse-1.html","topicUid":"EchoHub.Core.DTOs.ApiResponse`1","type":"Class"},{"name":"AssignRoleRequest","href":"core/EchoHub.Core.DTOs.AssignRoleRequest.html","topicHref":"core/EchoHub.Core.DTOs.AssignRoleRequest.html","topicUid":"EchoHub.Core.DTOs.AssignRoleRequest","type":"Class"},{"name":"AttachmentDto","href":"core/EchoHub.Core.DTOs.AttachmentDto.html","topicHref":"core/EchoHub.Core.DTOs.AttachmentDto.html","topicUid":"EchoHub.Core.DTOs.AttachmentDto","type":"Class"},{"name":"AvatarUploadResponse","href":"core/EchoHub.Core.DTOs.AvatarUploadResponse.html","topicHref":"core/EchoHub.Core.DTOs.AvatarUploadResponse.html","topicUid":"EchoHub.Core.DTOs.AvatarUploadResponse","type":"Class"},{"name":"BanRequest","href":"core/EchoHub.Core.DTOs.BanRequest.html","topicHref":"core/EchoHub.Core.DTOs.BanRequest.html","topicUid":"EchoHub.Core.DTOs.BanRequest","type":"Class"},{"name":"ChannelCryptoDto","href":"core/EchoHub.Core.DTOs.ChannelCryptoDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelCryptoDto.html","topicUid":"EchoHub.Core.DTOs.ChannelCryptoDto","type":"Class"},{"name":"ChannelDto","href":"core/EchoHub.Core.DTOs.ChannelDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelDto.html","topicUid":"EchoHub.Core.DTOs.ChannelDto","type":"Class"},{"name":"ChannelError","href":"core/EchoHub.Core.DTOs.ChannelError.html","topicHref":"core/EchoHub.Core.DTOs.ChannelError.html","topicUid":"EchoHub.Core.DTOs.ChannelError","type":"Enum"},{"name":"ChannelOperationResult","href":"core/EchoHub.Core.DTOs.ChannelOperationResult.html","topicHref":"core/EchoHub.Core.DTOs.ChannelOperationResult.html","topicUid":"EchoHub.Core.DTOs.ChannelOperationResult","type":"Class"},{"name":"CreateChannelRequest","href":"core/EchoHub.Core.DTOs.CreateChannelRequest.html","topicHref":"core/EchoHub.Core.DTOs.CreateChannelRequest.html","topicUid":"EchoHub.Core.DTOs.CreateChannelRequest","type":"Class"},{"name":"EmbedDto","href":"core/EchoHub.Core.DTOs.EmbedDto.html","topicHref":"core/EchoHub.Core.DTOs.EmbedDto.html","topicUid":"EchoHub.Core.DTOs.EmbedDto","type":"Class"},{"name":"EncryptionKeyResponse","href":"core/EchoHub.Core.DTOs.EncryptionKeyResponse.html","topicHref":"core/EchoHub.Core.DTOs.EncryptionKeyResponse.html","topicUid":"EchoHub.Core.DTOs.EncryptionKeyResponse","type":"Class"},{"name":"ErrorResponse","href":"core/EchoHub.Core.DTOs.ErrorResponse.html","topicHref":"core/EchoHub.Core.DTOs.ErrorResponse.html","topicUid":"EchoHub.Core.DTOs.ErrorResponse","type":"Class"},{"name":"JoinChannelResult","href":"core/EchoHub.Core.DTOs.JoinChannelResult.html","topicHref":"core/EchoHub.Core.DTOs.JoinChannelResult.html","topicUid":"EchoHub.Core.DTOs.JoinChannelResult","type":"Class"},{"name":"KickRequest","href":"core/EchoHub.Core.DTOs.KickRequest.html","topicHref":"core/EchoHub.Core.DTOs.KickRequest.html","topicUid":"EchoHub.Core.DTOs.KickRequest","type":"Class"},{"name":"LoginRequest","href":"core/EchoHub.Core.DTOs.LoginRequest.html","topicHref":"core/EchoHub.Core.DTOs.LoginRequest.html","topicUid":"EchoHub.Core.DTOs.LoginRequest","type":"Class"},{"name":"LoginResponse","href":"core/EchoHub.Core.DTOs.LoginResponse.html","topicHref":"core/EchoHub.Core.DTOs.LoginResponse.html","topicUid":"EchoHub.Core.DTOs.LoginResponse","type":"Class"},{"name":"MessageDto","href":"core/EchoHub.Core.DTOs.MessageDto.html","topicHref":"core/EchoHub.Core.DTOs.MessageDto.html","topicUid":"EchoHub.Core.DTOs.MessageDto","type":"Class"},{"name":"MuteRequest","href":"core/EchoHub.Core.DTOs.MuteRequest.html","topicHref":"core/EchoHub.Core.DTOs.MuteRequest.html","topicUid":"EchoHub.Core.DTOs.MuteRequest","type":"Class"},{"name":"PaginatedResponse","href":"core/EchoHub.Core.DTOs.PaginatedResponse-1.html","topicHref":"core/EchoHub.Core.DTOs.PaginatedResponse-1.html","topicUid":"EchoHub.Core.DTOs.PaginatedResponse`1","type":"Class"},{"name":"RefreshRequest","href":"core/EchoHub.Core.DTOs.RefreshRequest.html","topicHref":"core/EchoHub.Core.DTOs.RefreshRequest.html","topicUid":"EchoHub.Core.DTOs.RefreshRequest","type":"Class"},{"name":"RegisterRequest","href":"core/EchoHub.Core.DTOs.RegisterRequest.html","topicHref":"core/EchoHub.Core.DTOs.RegisterRequest.html","topicUid":"EchoHub.Core.DTOs.RegisterRequest","type":"Class"},{"name":"RekeyChannelRequest","href":"core/EchoHub.Core.DTOs.RekeyChannelRequest.html","topicHref":"core/EchoHub.Core.DTOs.RekeyChannelRequest.html","topicUid":"EchoHub.Core.DTOs.RekeyChannelRequest","type":"Class"},{"name":"SendMessageRequest","href":"core/EchoHub.Core.DTOs.SendMessageRequest.html","topicHref":"core/EchoHub.Core.DTOs.SendMessageRequest.html","topicUid":"EchoHub.Core.DTOs.SendMessageRequest","type":"Class"},{"name":"SendUrlRequest","href":"core/EchoHub.Core.DTOs.SendUrlRequest.html","topicHref":"core/EchoHub.Core.DTOs.SendUrlRequest.html","topicUid":"EchoHub.Core.DTOs.SendUrlRequest","type":"Class"},{"name":"ServerStatusDto","href":"core/EchoHub.Core.DTOs.ServerStatusDto.html","topicHref":"core/EchoHub.Core.DTOs.ServerStatusDto.html","topicUid":"EchoHub.Core.DTOs.ServerStatusDto","type":"Class"},{"name":"UpdateProfileRequest","href":"core/EchoHub.Core.DTOs.UpdateProfileRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateProfileRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateProfileRequest","type":"Class"},{"name":"UpdateStatusRequest","href":"core/EchoHub.Core.DTOs.UpdateStatusRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateStatusRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateStatusRequest","type":"Class"},{"name":"UpdateTopicRequest","href":"core/EchoHub.Core.DTOs.UpdateTopicRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateTopicRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateTopicRequest","type":"Class"},{"name":"UserDto","href":"core/EchoHub.Core.DTOs.UserDto.html","topicHref":"core/EchoHub.Core.DTOs.UserDto.html","topicUid":"EchoHub.Core.DTOs.UserDto","type":"Class"},{"name":"UserError","href":"core/EchoHub.Core.DTOs.UserError.html","topicHref":"core/EchoHub.Core.DTOs.UserError.html","topicUid":"EchoHub.Core.DTOs.UserError","type":"Enum"},{"name":"UserOperationResult","href":"core/EchoHub.Core.DTOs.UserOperationResult.html","topicHref":"core/EchoHub.Core.DTOs.UserOperationResult.html","topicUid":"EchoHub.Core.DTOs.UserOperationResult","type":"Class"},{"name":"UserPresenceDto","href":"core/EchoHub.Core.DTOs.UserPresenceDto.html","topicHref":"core/EchoHub.Core.DTOs.UserPresenceDto.html","topicUid":"EchoHub.Core.DTOs.UserPresenceDto","type":"Class"},{"name":"UserProfileDto","href":"core/EchoHub.Core.DTOs.UserProfileDto.html","topicHref":"core/EchoHub.Core.DTOs.UserProfileDto.html","topicUid":"EchoHub.Core.DTOs.UserProfileDto","type":"Class"}]},{"name":"EchoHub.Core.Models","href":"core/EchoHub.Core.Models.html","topicHref":"core/EchoHub.Core.Models.html","topicUid":"EchoHub.Core.Models","type":"Namespace","items":[{"name":"Attachment","href":"core/EchoHub.Core.Models.Attachment.html","topicHref":"core/EchoHub.Core.Models.Attachment.html","topicUid":"EchoHub.Core.Models.Attachment","type":"Class"},{"name":"AttachmentKind","href":"core/EchoHub.Core.Models.AttachmentKind.html","topicHref":"core/EchoHub.Core.Models.AttachmentKind.html","topicUid":"EchoHub.Core.Models.AttachmentKind","type":"Enum"},{"name":"Channel","href":"core/EchoHub.Core.Models.Channel.html","topicHref":"core/EchoHub.Core.Models.Channel.html","topicUid":"EchoHub.Core.Models.Channel","type":"Class"},{"name":"ChannelMembership","href":"core/EchoHub.Core.Models.ChannelMembership.html","topicHref":"core/EchoHub.Core.Models.ChannelMembership.html","topicUid":"EchoHub.Core.Models.ChannelMembership","type":"Class"},{"name":"Message","href":"core/EchoHub.Core.Models.Message.html","topicHref":"core/EchoHub.Core.Models.Message.html","topicUid":"EchoHub.Core.Models.Message","type":"Class"},{"name":"MessageType","href":"core/EchoHub.Core.Models.MessageType.html","topicHref":"core/EchoHub.Core.Models.MessageType.html","topicUid":"EchoHub.Core.Models.MessageType","type":"Enum"},{"name":"RefreshToken","href":"core/EchoHub.Core.Models.RefreshToken.html","topicHref":"core/EchoHub.Core.Models.RefreshToken.html","topicUid":"EchoHub.Core.Models.RefreshToken","type":"Class"},{"name":"ServerRole","href":"core/EchoHub.Core.Models.ServerRole.html","topicHref":"core/EchoHub.Core.Models.ServerRole.html","topicUid":"EchoHub.Core.Models.ServerRole","type":"Enum"},{"name":"User","href":"core/EchoHub.Core.Models.User.html","topicHref":"core/EchoHub.Core.Models.User.html","topicUid":"EchoHub.Core.Models.User","type":"Class"},{"name":"UserStatus","href":"core/EchoHub.Core.Models.UserStatus.html","topicHref":"core/EchoHub.Core.Models.UserStatus.html","topicUid":"EchoHub.Core.Models.UserStatus","type":"Enum"}]},{"name":"EchoHub.Core.Security","href":"core/EchoHub.Core.Security.html","topicHref":"core/EchoHub.Core.Security.html","topicUid":"EchoHub.Core.Security","type":"Namespace","items":[{"name":"RoomCrypto","href":"core/EchoHub.Core.Security.RoomCrypto.html","topicHref":"core/EchoHub.Core.Security.RoomCrypto.html","topicUid":"EchoHub.Core.Security.RoomCrypto","type":"Class"},{"name":"RoomCrypto.DerivedKeys","href":"core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html","topicHref":"core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html","topicUid":"EchoHub.Core.Security.RoomCrypto.DerivedKeys","type":"Class"}]},{"name":"EchoHub.Core.Services","href":"core/EchoHub.Core.Services.html","topicHref":"core/EchoHub.Core.Services.html","topicUid":"EchoHub.Core.Services","type":"Namespace","items":[{"name":"FileValidationHelper","href":"core/EchoHub.Core.Services.FileValidationHelper.html","topicHref":"core/EchoHub.Core.Services.FileValidationHelper.html","topicUid":"EchoHub.Core.Services.FileValidationHelper","type":"Class"},{"name":"ImageToAsciiService","href":"core/EchoHub.Core.Services.ImageToAsciiService.html","topicHref":"core/EchoHub.Core.Services.ImageToAsciiService.html","topicUid":"EchoHub.Core.Services.ImageToAsciiService","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/core-articles/toc.yml","items":[{"name":"Overview","href":"core-articles/index.html","topicHref":"core-articles/index.html"}]}]},{"name":"Server","items":[{"name":"API Reference","includedFrom":"~/_api_meta/server/toc.yml","items":[{"name":"EchoHub.Server.Auth","href":"server/EchoHub.Server.Auth.html","topicHref":"server/EchoHub.Server.Auth.html","topicUid":"EchoHub.Server.Auth","type":"Namespace","items":[{"name":"JwtTokenService","href":"server/EchoHub.Server.Auth.JwtTokenService.html","topicHref":"server/EchoHub.Server.Auth.JwtTokenService.html","topicUid":"EchoHub.Server.Auth.JwtTokenService","type":"Class"}]},{"name":"EchoHub.Server.Controllers","href":"server/EchoHub.Server.Controllers.html","topicHref":"server/EchoHub.Server.Controllers.html","topicUid":"EchoHub.Server.Controllers","type":"Namespace","items":[{"name":"AuthController","href":"server/EchoHub.Server.Controllers.AuthController.html","topicHref":"server/EchoHub.Server.Controllers.AuthController.html","topicUid":"EchoHub.Server.Controllers.AuthController","type":"Class"},{"name":"ChannelsController","href":"server/EchoHub.Server.Controllers.ChannelsController.html","topicHref":"server/EchoHub.Server.Controllers.ChannelsController.html","topicUid":"EchoHub.Server.Controllers.ChannelsController","type":"Class"},{"name":"FilesController","href":"server/EchoHub.Server.Controllers.FilesController.html","topicHref":"server/EchoHub.Server.Controllers.FilesController.html","topicUid":"EchoHub.Server.Controllers.FilesController","type":"Class"},{"name":"ModerationController","href":"server/EchoHub.Server.Controllers.ModerationController.html","topicHref":"server/EchoHub.Server.Controllers.ModerationController.html","topicUid":"EchoHub.Server.Controllers.ModerationController","type":"Class"},{"name":"ServerController","href":"server/EchoHub.Server.Controllers.ServerController.html","topicHref":"server/EchoHub.Server.Controllers.ServerController.html","topicUid":"EchoHub.Server.Controllers.ServerController","type":"Class"},{"name":"UsersController","href":"server/EchoHub.Server.Controllers.UsersController.html","topicHref":"server/EchoHub.Server.Controllers.UsersController.html","topicUid":"EchoHub.Server.Controllers.UsersController","type":"Class"}]},{"name":"EchoHub.Server.Data","href":"server/EchoHub.Server.Data.html","topicHref":"server/EchoHub.Server.Data.html","topicUid":"EchoHub.Server.Data","type":"Namespace","items":[{"name":"EchoHubDbContext","href":"server/EchoHub.Server.Data.EchoHubDbContext.html","topicHref":"server/EchoHub.Server.Data.EchoHubDbContext.html","topicUid":"EchoHub.Server.Data.EchoHubDbContext","type":"Class"}]},{"name":"EchoHub.Server.Data.Migrations","href":"server/EchoHub.Server.Data.Migrations.html","topicHref":"server/EchoHub.Server.Data.Migrations.html","topicUid":"EchoHub.Server.Data.Migrations","type":"Namespace","items":[{"name":"AddAttachmentFileSize","href":"server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html","topicUid":"EchoHub.Server.Data.Migrations.AddAttachmentFileSize","type":"Class"},{"name":"AddChannelEncryptionEnvelope","href":"server/EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope","type":"Class"},{"name":"AddChannelIsPublic","href":"server/EchoHub.Server.Data.Migrations.AddChannelIsPublic.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelIsPublic.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelIsPublic","type":"Class"},{"name":"AddChannelMembership","href":"server/EchoHub.Server.Data.Migrations.AddChannelMembership.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelMembership.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelMembership","type":"Class"},{"name":"AddChannelPasswordHash","href":"server/EchoHub.Server.Data.Migrations.AddChannelPasswordHash.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelPasswordHash.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelPasswordHash","type":"Class"},{"name":"AddEncryptionSupport","href":"server/EchoHub.Server.Data.Migrations.AddEncryptionSupport.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddEncryptionSupport.html","topicUid":"EchoHub.Server.Data.Migrations.AddEncryptionSupport","type":"Class"},{"name":"AddMessageAttachments","href":"server/EchoHub.Server.Data.Migrations.AddMessageAttachments.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddMessageAttachments.html","topicUid":"EchoHub.Server.Data.Migrations.AddMessageAttachments","type":"Class"},{"name":"AddMessageEmbed","href":"server/EchoHub.Server.Data.Migrations.AddMessageEmbed.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddMessageEmbed.html","topicUid":"EchoHub.Server.Data.Migrations.AddMessageEmbed","type":"Class"},{"name":"AddModerationRoles","href":"server/EchoHub.Server.Data.Migrations.AddModerationRoles.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddModerationRoles.html","topicUid":"EchoHub.Server.Data.Migrations.AddModerationRoles","type":"Class"},{"name":"InitialCreate","href":"server/EchoHub.Server.Data.Migrations.InitialCreate.html","topicHref":"server/EchoHub.Server.Data.Migrations.InitialCreate.html","topicUid":"EchoHub.Server.Data.Migrations.InitialCreate","type":"Class"}]},{"name":"EchoHub.Server.Hubs","href":"server/EchoHub.Server.Hubs.html","topicHref":"server/EchoHub.Server.Hubs.html","topicUid":"EchoHub.Server.Hubs","type":"Namespace","items":[{"name":"ChatHub","href":"server/EchoHub.Server.Hubs.ChatHub.html","topicHref":"server/EchoHub.Server.Hubs.ChatHub.html","topicUid":"EchoHub.Server.Hubs.ChatHub","type":"Class"}]},{"name":"EchoHub.Server.Services","href":"server/EchoHub.Server.Services.html","topicHref":"server/EchoHub.Server.Services.html","topicUid":"EchoHub.Server.Services","type":"Namespace","items":[{"name":"ChannelService","href":"server/EchoHub.Server.Services.ChannelService.html","topicHref":"server/EchoHub.Server.Services.ChannelService.html","topicUid":"EchoHub.Server.Services.ChannelService","type":"Class"},{"name":"ChatService","href":"server/EchoHub.Server.Services.ChatService.html","topicHref":"server/EchoHub.Server.Services.ChatService.html","topicUid":"EchoHub.Server.Services.ChatService","type":"Class"},{"name":"DirectoryClaimStore","href":"server/EchoHub.Server.Services.DirectoryClaimStore.html","topicHref":"server/EchoHub.Server.Services.DirectoryClaimStore.html","topicUid":"EchoHub.Server.Services.DirectoryClaimStore","type":"Class"},{"name":"FileCleanupService","href":"server/EchoHub.Server.Services.FileCleanupService.html","topicHref":"server/EchoHub.Server.Services.FileCleanupService.html","topicUid":"EchoHub.Server.Services.FileCleanupService","type":"Class"},{"name":"FileStorageService","href":"server/EchoHub.Server.Services.FileStorageService.html","topicHref":"server/EchoHub.Server.Services.FileStorageService.html","topicUid":"EchoHub.Server.Services.FileStorageService","type":"Class"},{"name":"LinkEmbedService","href":"server/EchoHub.Server.Services.LinkEmbedService.html","topicHref":"server/EchoHub.Server.Services.LinkEmbedService.html","topicUid":"EchoHub.Server.Services.LinkEmbedService","type":"Class"},{"name":"MessageEncryptionService","href":"server/EchoHub.Server.Services.MessageEncryptionService.html","topicHref":"server/EchoHub.Server.Services.MessageEncryptionService.html","topicUid":"EchoHub.Server.Services.MessageEncryptionService","type":"Class"},{"name":"MuteExpirationService","href":"server/EchoHub.Server.Services.MuteExpirationService.html","topicHref":"server/EchoHub.Server.Services.MuteExpirationService.html","topicUid":"EchoHub.Server.Services.MuteExpirationService","type":"Class"},{"name":"PresenceTracker","href":"server/EchoHub.Server.Services.PresenceTracker.html","topicHref":"server/EchoHub.Server.Services.PresenceTracker.html","topicUid":"EchoHub.Server.Services.PresenceTracker","type":"Class"},{"name":"RegistrationStatus","href":"server/EchoHub.Server.Services.RegistrationStatus.html","topicHref":"server/EchoHub.Server.Services.RegistrationStatus.html","topicUid":"EchoHub.Server.Services.RegistrationStatus","type":"Class"},{"name":"ServerDirectoryService","href":"server/EchoHub.Server.Services.ServerDirectoryService.html","topicHref":"server/EchoHub.Server.Services.ServerDirectoryService.html","topicUid":"EchoHub.Server.Services.ServerDirectoryService","type":"Class"},{"name":"SignalRBroadcaster","href":"server/EchoHub.Server.Services.SignalRBroadcaster.html","topicHref":"server/EchoHub.Server.Services.SignalRBroadcaster.html","topicUid":"EchoHub.Server.Services.SignalRBroadcaster","type":"Class"},{"name":"UserService","href":"server/EchoHub.Server.Services.UserService.html","topicHref":"server/EchoHub.Server.Services.UserService.html","topicUid":"EchoHub.Server.Services.UserService","type":"Class"}]},{"name":"EchoHub.Server.Setup","href":"server/EchoHub.Server.Setup.html","topicHref":"server/EchoHub.Server.Setup.html","topicUid":"EchoHub.Server.Setup","type":"Namespace","items":[{"name":"DataMigrationService","href":"server/EchoHub.Server.Setup.DataMigrationService.html","topicHref":"server/EchoHub.Server.Setup.DataMigrationService.html","topicUid":"EchoHub.Server.Setup.DataMigrationService","type":"Class"},{"name":"DatabaseSetup","href":"server/EchoHub.Server.Setup.DatabaseSetup.html","topicHref":"server/EchoHub.Server.Setup.DatabaseSetup.html","topicUid":"EchoHub.Server.Setup.DatabaseSetup","type":"Class"},{"name":"FirstRunSetup","href":"server/EchoHub.Server.Setup.FirstRunSetup.html","topicHref":"server/EchoHub.Server.Setup.FirstRunSetup.html","topicUid":"EchoHub.Server.Setup.FirstRunSetup","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/server-articles/toc.yml","items":[{"name":"Overview","href":"server-articles/index.html","topicHref":"server-articles/index.html"}]}]},{"name":"Server.Irc","items":[{"name":"API Reference","includedFrom":"~/_api_meta/server-irc/toc.yml","items":[{"name":"EchoHub.Server.Irc","href":"server-irc/EchoHub.Server.Irc.html","topicHref":"server-irc/EchoHub.Server.Irc.html","topicUid":"EchoHub.Server.Irc","type":"Namespace","items":[{"name":"IrcBroadcaster","href":"server-irc/EchoHub.Server.Irc.IrcBroadcaster.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcBroadcaster.html","topicUid":"EchoHub.Server.Irc.IrcBroadcaster","type":"Class"},{"name":"IrcClientConnection","href":"server-irc/EchoHub.Server.Irc.IrcClientConnection.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcClientConnection.html","topicUid":"EchoHub.Server.Irc.IrcClientConnection","type":"Class"},{"name":"IrcCommandHandler","href":"server-irc/EchoHub.Server.Irc.IrcCommandHandler.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcCommandHandler.html","topicUid":"EchoHub.Server.Irc.IrcCommandHandler","type":"Class"},{"name":"IrcGatewayService","href":"server-irc/EchoHub.Server.Irc.IrcGatewayService.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcGatewayService.html","topicUid":"EchoHub.Server.Irc.IrcGatewayService","type":"Class"},{"name":"IrcMessage","href":"server-irc/EchoHub.Server.Irc.IrcMessage.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcMessage.html","topicUid":"EchoHub.Server.Irc.IrcMessage","type":"Class"},{"name":"IrcMessageFormatter","href":"server-irc/EchoHub.Server.Irc.IrcMessageFormatter.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcMessageFormatter.html","topicUid":"EchoHub.Server.Irc.IrcMessageFormatter","type":"Class"},{"name":"IrcNumericReply","href":"server-irc/EchoHub.Server.Irc.IrcNumericReply.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcNumericReply.html","topicUid":"EchoHub.Server.Irc.IrcNumericReply","type":"Class"},{"name":"IrcOptions","href":"server-irc/EchoHub.Server.Irc.IrcOptions.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcOptions.html","topicUid":"EchoHub.Server.Irc.IrcOptions","type":"Class"},{"name":"IrcServiceExtensions","href":"server-irc/EchoHub.Server.Irc.IrcServiceExtensions.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcServiceExtensions.html","topicUid":"EchoHub.Server.Irc.IrcServiceExtensions","type":"Class"}]}]}]}]} +{"items":[{"name":"Client","items":[{"name":"API Reference","includedFrom":"~/_api_meta/client/toc.yml","items":[{"name":"EchoHub.Client","href":"client/EchoHub.Client.html","topicHref":"client/EchoHub.Client.html","topicUid":"EchoHub.Client","type":"Namespace","items":[{"name":"AppOrchestrator","href":"client/EchoHub.Client.AppOrchestrator.html","topicHref":"client/EchoHub.Client.AppOrchestrator.html","topicUid":"EchoHub.Client.AppOrchestrator","type":"Class"}]},{"name":"EchoHub.Client.Commands","href":"client/EchoHub.Client.Commands.html","topicHref":"client/EchoHub.Client.Commands.html","topicUid":"EchoHub.Client.Commands","type":"Namespace","items":[{"name":"CommandHandler","href":"client/EchoHub.Client.Commands.CommandHandler.html","topicHref":"client/EchoHub.Client.Commands.CommandHandler.html","topicUid":"EchoHub.Client.Commands.CommandHandler","type":"Class"},{"name":"CommandResult","href":"client/EchoHub.Client.Commands.CommandResult.html","topicHref":"client/EchoHub.Client.Commands.CommandResult.html","topicUid":"EchoHub.Client.Commands.CommandResult","type":"Class"}]},{"name":"EchoHub.Client.Config","href":"client/EchoHub.Client.Config.html","topicHref":"client/EchoHub.Client.Config.html","topicUid":"EchoHub.Client.Config","type":"Namespace","items":[{"name":"AccountPreset","href":"client/EchoHub.Client.Config.AccountPreset.html","topicHref":"client/EchoHub.Client.Config.AccountPreset.html","topicUid":"EchoHub.Client.Config.AccountPreset","type":"Class"},{"name":"ClientConfig","href":"client/EchoHub.Client.Config.ClientConfig.html","topicHref":"client/EchoHub.Client.Config.ClientConfig.html","topicUid":"EchoHub.Client.Config.ClientConfig","type":"Class"},{"name":"ConfigManager","href":"client/EchoHub.Client.Config.ConfigManager.html","topicHref":"client/EchoHub.Client.Config.ConfigManager.html","topicUid":"EchoHub.Client.Config.ConfigManager","type":"Class"},{"name":"NotificationConfig","href":"client/EchoHub.Client.Config.NotificationConfig.html","topicHref":"client/EchoHub.Client.Config.NotificationConfig.html","topicUid":"EchoHub.Client.Config.NotificationConfig","type":"Class"},{"name":"SavedServer","href":"client/EchoHub.Client.Config.SavedServer.html","topicHref":"client/EchoHub.Client.Config.SavedServer.html","topicUid":"EchoHub.Client.Config.SavedServer","type":"Class"}]},{"name":"EchoHub.Client.Services","href":"client/EchoHub.Client.Services.html","topicHref":"client/EchoHub.Client.Services.html","topicUid":"EchoHub.Client.Services","type":"Namespace","items":[{"name":"ApiClient","href":"client/EchoHub.Client.Services.ApiClient.html","topicHref":"client/EchoHub.Client.Services.ApiClient.html","topicUid":"EchoHub.Client.Services.ApiClient","type":"Class"},{"name":"AsyncRunner","href":"client/EchoHub.Client.Services.AsyncRunner.html","topicHref":"client/EchoHub.Client.Services.AsyncRunner.html","topicUid":"EchoHub.Client.Services.AsyncRunner","type":"Class"},{"name":"AudioPlaybackService","href":"client/EchoHub.Client.Services.AudioPlaybackService.html","topicHref":"client/EchoHub.Client.Services.AudioPlaybackService.html","topicUid":"EchoHub.Client.Services.AudioPlaybackService","type":"Class"},{"name":"BackupInfo","href":"client/EchoHub.Client.Services.BackupInfo.html","topicHref":"client/EchoHub.Client.Services.BackupInfo.html","topicUid":"EchoHub.Client.Services.BackupInfo","type":"Class"},{"name":"ChannelPasswordRequiredException","href":"client/EchoHub.Client.Services.ChannelPasswordRequiredException.html","topicHref":"client/EchoHub.Client.Services.ChannelPasswordRequiredException.html","topicUid":"EchoHub.Client.Services.ChannelPasswordRequiredException","type":"Class"},{"name":"ClientEncryptionService","href":"client/EchoHub.Client.Services.ClientEncryptionService.html","topicHref":"client/EchoHub.Client.Services.ClientEncryptionService.html","topicUid":"EchoHub.Client.Services.ClientEncryptionService","type":"Class"},{"name":"ClipboardFiles","href":"client/EchoHub.Client.Services.ClipboardFiles.html","topicHref":"client/EchoHub.Client.Services.ClipboardFiles.html","topicUid":"EchoHub.Client.Services.ClipboardFiles","type":"Class"},{"name":"EchoHubConnection","href":"client/EchoHub.Client.Services.EchoHubConnection.html","topicHref":"client/EchoHub.Client.Services.EchoHubConnection.html","topicUid":"EchoHub.Client.Services.EchoHubConnection","type":"Class"},{"name":"FolderPickResult","href":"client/EchoHub.Client.Services.FolderPickResult.html","topicHref":"client/EchoHub.Client.Services.FolderPickResult.html","topicUid":"EchoHub.Client.Services.FolderPickResult","type":"Class"},{"name":"JoinOutcome","href":"client/EchoHub.Client.Services.JoinOutcome.html","topicHref":"client/EchoHub.Client.Services.JoinOutcome.html","topicUid":"EchoHub.Client.Services.JoinOutcome","type":"Class"},{"name":"NativeFolderPicker","href":"client/EchoHub.Client.Services.NativeFolderPicker.html","topicHref":"client/EchoHub.Client.Services.NativeFolderPicker.html","topicUid":"EchoHub.Client.Services.NativeFolderPicker","type":"Class"},{"name":"NotificationSoundService","href":"client/EchoHub.Client.Services.NotificationSoundService.html","topicHref":"client/EchoHub.Client.Services.NotificationSoundService.html","topicUid":"EchoHub.Client.Services.NotificationSoundService","type":"Class"},{"name":"OutgoingAttachment","href":"client/EchoHub.Client.Services.OutgoingAttachment.html","topicHref":"client/EchoHub.Client.Services.OutgoingAttachment.html","topicUid":"EchoHub.Client.Services.OutgoingAttachment","type":"Class"},{"name":"PathSetup","href":"client/EchoHub.Client.Services.PathSetup.html","topicHref":"client/EchoHub.Client.Services.PathSetup.html","topicUid":"EchoHub.Client.Services.PathSetup","type":"Class"},{"name":"PickerOutcome","href":"client/EchoHub.Client.Services.PickerOutcome.html","topicHref":"client/EchoHub.Client.Services.PickerOutcome.html","topicUid":"EchoHub.Client.Services.PickerOutcome","type":"Enum"},{"name":"RoomKeyStore","href":"client/EchoHub.Client.Services.RoomKeyStore.html","topicHref":"client/EchoHub.Client.Services.RoomKeyStore.html","topicUid":"EchoHub.Client.Services.RoomKeyStore","type":"Class"},{"name":"UpdateBackupService","href":"client/EchoHub.Client.Services.UpdateBackupService.html","topicHref":"client/EchoHub.Client.Services.UpdateBackupService.html","topicUid":"EchoHub.Client.Services.UpdateBackupService","type":"Class"},{"name":"UpdateChecker","href":"client/EchoHub.Client.Services.UpdateChecker.html","topicHref":"client/EchoHub.Client.Services.UpdateChecker.html","topicUid":"EchoHub.Client.Services.UpdateChecker","type":"Class"}]},{"name":"EchoHub.Client.Themes","href":"client/EchoHub.Client.Themes.html","topicHref":"client/EchoHub.Client.Themes.html","topicUid":"EchoHub.Client.Themes","type":"Namespace","items":[{"name":"Theme","href":"client/EchoHub.Client.Themes.Theme.html","topicHref":"client/EchoHub.Client.Themes.Theme.html","topicUid":"EchoHub.Client.Themes.Theme","type":"Class"},{"name":"ThemeColors","href":"client/EchoHub.Client.Themes.ThemeColors.html","topicHref":"client/EchoHub.Client.Themes.ThemeColors.html","topicUid":"EchoHub.Client.Themes.ThemeColors","type":"Class"},{"name":"ThemeManager","href":"client/EchoHub.Client.Themes.ThemeManager.html","topicHref":"client/EchoHub.Client.Themes.ThemeManager.html","topicUid":"EchoHub.Client.Themes.ThemeManager","type":"Class"}]},{"name":"EchoHub.Client.UI","href":"client/EchoHub.Client.UI.html","topicHref":"client/EchoHub.Client.UI.html","topicUid":"EchoHub.Client.UI","type":"Namespace","items":[{"name":"MainWindow","href":"client/EchoHub.Client.UI.MainWindow.html","topicHref":"client/EchoHub.Client.UI.MainWindow.html","topicUid":"EchoHub.Client.UI.MainWindow","type":"Class"}]},{"name":"EchoHub.Client.UI.Chat","href":"client/EchoHub.Client.UI.Chat.html","topicHref":"client/EchoHub.Client.UI.Chat.html","topicUid":"EchoHub.Client.UI.Chat","type":"Namespace","items":[{"name":"ChatColors","href":"client/EchoHub.Client.UI.Chat.ChatColors.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatColors.html","topicUid":"EchoHub.Client.UI.Chat.ChatColors","type":"Class"},{"name":"ChatLine","href":"client/EchoHub.Client.UI.Chat.ChatLine.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatLine.html","topicUid":"EchoHub.Client.UI.Chat.ChatLine","type":"Class"},{"name":"ChatListSource","href":"client/EchoHub.Client.UI.Chat.ChatListSource.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatListSource.html","topicUid":"EchoHub.Client.UI.Chat.ChatListSource","type":"Class"},{"name":"ChatMessageManager","href":"client/EchoHub.Client.UI.Chat.ChatMessageManager.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatMessageManager.html","topicUid":"EchoHub.Client.UI.Chat.ChatMessageManager","type":"Class"},{"name":"ChatSegment","href":"client/EchoHub.Client.UI.Chat.ChatSegment.html","topicHref":"client/EchoHub.Client.UI.Chat.ChatSegment.html","topicUid":"EchoHub.Client.UI.Chat.ChatSegment","type":"Class"}]},{"name":"EchoHub.Client.UI.Dialogs","href":"client/EchoHub.Client.UI.Dialogs.html","topicHref":"client/EchoHub.Client.UI.Dialogs.html","topicUid":"EchoHub.Client.UI.Dialogs","type":"Namespace","items":[{"name":"AudioPlayerDialog","href":"client/EchoHub.Client.UI.Dialogs.AudioPlayerDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.AudioPlayerDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.AudioPlayerDialog","type":"Class"},{"name":"ChannelPasswordDialog","href":"client/EchoHub.Client.UI.Dialogs.ChannelPasswordDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ChannelPasswordDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ChannelPasswordDialog","type":"Class"},{"name":"ConnectDialog","href":"client/EchoHub.Client.UI.Dialogs.ConnectDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ConnectDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ConnectDialog","type":"Class"},{"name":"ConnectDialogResult","href":"client/EchoHub.Client.UI.Dialogs.ConnectDialogResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ConnectDialogResult.html","topicUid":"EchoHub.Client.UI.Dialogs.ConnectDialogResult","type":"Class"},{"name":"CreateChannelDialog","href":"client/EchoHub.Client.UI.Dialogs.CreateChannelDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.CreateChannelDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.CreateChannelDialog","type":"Class"},{"name":"CreateChannelResult","href":"client/EchoHub.Client.UI.Dialogs.CreateChannelResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.CreateChannelResult.html","topicUid":"EchoHub.Client.UI.Dialogs.CreateChannelResult","type":"Class"},{"name":"ProfileAction","href":"client/EchoHub.Client.UI.Dialogs.ProfileAction.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileAction.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileAction","type":"Enum"},{"name":"ProfileEditDialog","href":"client/EchoHub.Client.UI.Dialogs.ProfileEditDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileEditDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileEditDialog","type":"Class"},{"name":"ProfileEditResult","href":"client/EchoHub.Client.UI.Dialogs.ProfileEditResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileEditResult.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileEditResult","type":"Class"},{"name":"ProfileViewDialog","href":"client/EchoHub.Client.UI.Dialogs.ProfileViewDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.ProfileViewDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.ProfileViewDialog","type":"Class"},{"name":"SearchDialog","href":"client/EchoHub.Client.UI.Dialogs.SearchDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchDialog","type":"Class"},{"name":"SearchResult","href":"client/EchoHub.Client.UI.Dialogs.SearchResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchResult.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchResult","type":"Class"},{"name":"SearchResultType","href":"client/EchoHub.Client.UI.Dialogs.SearchResultType.html","topicHref":"client/EchoHub.Client.UI.Dialogs.SearchResultType.html","topicUid":"EchoHub.Client.UI.Dialogs.SearchResultType","type":"Enum"},{"name":"StatusDialog","href":"client/EchoHub.Client.UI.Dialogs.StatusDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.StatusDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.StatusDialog","type":"Class"},{"name":"StatusDialogResult","href":"client/EchoHub.Client.UI.Dialogs.StatusDialogResult.html","topicHref":"client/EchoHub.Client.UI.Dialogs.StatusDialogResult.html","topicUid":"EchoHub.Client.UI.Dialogs.StatusDialogResult","type":"Class"},{"name":"UpdateConfirmDialog","href":"client/EchoHub.Client.UI.Dialogs.UpdateConfirmDialog.html","topicHref":"client/EchoHub.Client.UI.Dialogs.UpdateConfirmDialog.html","topicUid":"EchoHub.Client.UI.Dialogs.UpdateConfirmDialog","type":"Class"}]},{"name":"EchoHub.Client.UI.Helpers","href":"client/EchoHub.Client.UI.Helpers.html","topicHref":"client/EchoHub.Client.UI.Helpers.html","topicUid":"EchoHub.Client.UI.Helpers","type":"Namespace","items":[{"name":"DroppedFileParser","href":"client/EchoHub.Client.UI.Helpers.DroppedFileParser.html","topicHref":"client/EchoHub.Client.UI.Helpers.DroppedFileParser.html","topicUid":"EchoHub.Client.UI.Helpers.DroppedFileParser","type":"Class"},{"name":"EmojiHelper","href":"client/EchoHub.Client.UI.Helpers.EmojiHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.EmojiHelper.html","topicUid":"EchoHub.Client.UI.Helpers.EmojiHelper","type":"Class"},{"name":"HexColorHelper","href":"client/EchoHub.Client.UI.Helpers.HexColorHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.HexColorHelper.html","topicUid":"EchoHub.Client.UI.Helpers.HexColorHelper","type":"Class"},{"name":"NickColorHelper","href":"client/EchoHub.Client.UI.Helpers.NickColorHelper.html","topicHref":"client/EchoHub.Client.UI.Helpers.NickColorHelper.html","topicUid":"EchoHub.Client.UI.Helpers.NickColorHelper","type":"Class"}]},{"name":"EchoHub.Client.UI.ListSources","href":"client/EchoHub.Client.UI.ListSources.html","topicHref":"client/EchoHub.Client.UI.ListSources.html","topicUid":"EchoHub.Client.UI.ListSources","type":"Namespace","items":[{"name":"ChannelListSource","href":"client/EchoHub.Client.UI.ListSources.ChannelListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.ChannelListSource.html","topicUid":"EchoHub.Client.UI.ListSources.ChannelListSource","type":"Class"},{"name":"SearchListSource","href":"client/EchoHub.Client.UI.ListSources.SearchListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.SearchListSource.html","topicUid":"EchoHub.Client.UI.ListSources.SearchListSource","type":"Class"},{"name":"UserListSource","href":"client/EchoHub.Client.UI.ListSources.UserListSource.html","topicHref":"client/EchoHub.Client.UI.ListSources.UserListSource.html","topicUid":"EchoHub.Client.UI.ListSources.UserListSource","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/client-articles/toc.yml","items":[{"name":"Overview","href":"client-articles/index.html","topicHref":"client-articles/index.html"}]}]},{"name":"Core","items":[{"name":"API Reference","includedFrom":"~/_api_meta/core/toc.yml","items":[{"name":"EchoHub.Core.Constants","href":"core/EchoHub.Core.Constants.html","topicHref":"core/EchoHub.Core.Constants.html","topicUid":"EchoHub.Core.Constants","type":"Namespace","items":[{"name":"HubConstants","href":"core/EchoHub.Core.Constants.HubConstants.html","topicHref":"core/EchoHub.Core.Constants.HubConstants.html","topicUid":"EchoHub.Core.Constants.HubConstants","type":"Class"},{"name":"ValidationConstants","href":"core/EchoHub.Core.Constants.ValidationConstants.html","topicHref":"core/EchoHub.Core.Constants.ValidationConstants.html","topicUid":"EchoHub.Core.Constants.ValidationConstants","type":"Class"}]},{"name":"EchoHub.Core.Contracts","href":"core/EchoHub.Core.Contracts.html","topicHref":"core/EchoHub.Core.Contracts.html","topicUid":"EchoHub.Core.Contracts","type":"Namespace","items":[{"name":"ChannelListItem","href":"core/EchoHub.Core.Contracts.ChannelListItem.html","topicHref":"core/EchoHub.Core.Contracts.ChannelListItem.html","topicUid":"EchoHub.Core.Contracts.ChannelListItem","type":"Class"},{"name":"IChannelService","href":"core/EchoHub.Core.Contracts.IChannelService.html","topicHref":"core/EchoHub.Core.Contracts.IChannelService.html","topicUid":"EchoHub.Core.Contracts.IChannelService","type":"Interface"},{"name":"IChatBroadcaster","href":"core/EchoHub.Core.Contracts.IChatBroadcaster.html","topicHref":"core/EchoHub.Core.Contracts.IChatBroadcaster.html","topicUid":"EchoHub.Core.Contracts.IChatBroadcaster","type":"Interface"},{"name":"IChatService","href":"core/EchoHub.Core.Contracts.IChatService.html","topicHref":"core/EchoHub.Core.Contracts.IChatService.html","topicUid":"EchoHub.Core.Contracts.IChatService","type":"Interface"},{"name":"IEchoHubClient","href":"core/EchoHub.Core.Contracts.IEchoHubClient.html","topicHref":"core/EchoHub.Core.Contracts.IEchoHubClient.html","topicUid":"EchoHub.Core.Contracts.IEchoHubClient","type":"Interface"},{"name":"IMessageEncryptionService","href":"core/EchoHub.Core.Contracts.IMessageEncryptionService.html","topicHref":"core/EchoHub.Core.Contracts.IMessageEncryptionService.html","topicUid":"EchoHub.Core.Contracts.IMessageEncryptionService","type":"Interface"},{"name":"IUserService","href":"core/EchoHub.Core.Contracts.IUserService.html","topicHref":"core/EchoHub.Core.Contracts.IUserService.html","topicUid":"EchoHub.Core.Contracts.IUserService","type":"Interface"}]},{"name":"EchoHub.Core.DTOs","href":"core/EchoHub.Core.DTOs.html","topicHref":"core/EchoHub.Core.DTOs.html","topicUid":"EchoHub.Core.DTOs","type":"Namespace","items":[{"name":"ApiResponse","href":"core/EchoHub.Core.DTOs.ApiResponse.html","topicHref":"core/EchoHub.Core.DTOs.ApiResponse.html","topicUid":"EchoHub.Core.DTOs.ApiResponse","type":"Class"},{"name":"ApiResponse","href":"core/EchoHub.Core.DTOs.ApiResponse-1.html","topicHref":"core/EchoHub.Core.DTOs.ApiResponse-1.html","topicUid":"EchoHub.Core.DTOs.ApiResponse`1","type":"Class"},{"name":"AssignRoleRequest","href":"core/EchoHub.Core.DTOs.AssignRoleRequest.html","topicHref":"core/EchoHub.Core.DTOs.AssignRoleRequest.html","topicUid":"EchoHub.Core.DTOs.AssignRoleRequest","type":"Class"},{"name":"AttachmentDto","href":"core/EchoHub.Core.DTOs.AttachmentDto.html","topicHref":"core/EchoHub.Core.DTOs.AttachmentDto.html","topicUid":"EchoHub.Core.DTOs.AttachmentDto","type":"Class"},{"name":"AvatarUploadResponse","href":"core/EchoHub.Core.DTOs.AvatarUploadResponse.html","topicHref":"core/EchoHub.Core.DTOs.AvatarUploadResponse.html","topicUid":"EchoHub.Core.DTOs.AvatarUploadResponse","type":"Class"},{"name":"BanRequest","href":"core/EchoHub.Core.DTOs.BanRequest.html","topicHref":"core/EchoHub.Core.DTOs.BanRequest.html","topicUid":"EchoHub.Core.DTOs.BanRequest","type":"Class"},{"name":"ChannelCryptoDto","href":"core/EchoHub.Core.DTOs.ChannelCryptoDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelCryptoDto.html","topicUid":"EchoHub.Core.DTOs.ChannelCryptoDto","type":"Class"},{"name":"ChannelDto","href":"core/EchoHub.Core.DTOs.ChannelDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelDto.html","topicUid":"EchoHub.Core.DTOs.ChannelDto","type":"Class"},{"name":"ChannelError","href":"core/EchoHub.Core.DTOs.ChannelError.html","topicHref":"core/EchoHub.Core.DTOs.ChannelError.html","topicUid":"EchoHub.Core.DTOs.ChannelError","type":"Enum"},{"name":"ChannelMetaDto","href":"core/EchoHub.Core.DTOs.ChannelMetaDto.html","topicHref":"core/EchoHub.Core.DTOs.ChannelMetaDto.html","topicUid":"EchoHub.Core.DTOs.ChannelMetaDto","type":"Class"},{"name":"ChannelOperationResult","href":"core/EchoHub.Core.DTOs.ChannelOperationResult.html","topicHref":"core/EchoHub.Core.DTOs.ChannelOperationResult.html","topicUid":"EchoHub.Core.DTOs.ChannelOperationResult","type":"Class"},{"name":"CreateChannelRequest","href":"core/EchoHub.Core.DTOs.CreateChannelRequest.html","topicHref":"core/EchoHub.Core.DTOs.CreateChannelRequest.html","topicUid":"EchoHub.Core.DTOs.CreateChannelRequest","type":"Class"},{"name":"EmbedDto","href":"core/EchoHub.Core.DTOs.EmbedDto.html","topicHref":"core/EchoHub.Core.DTOs.EmbedDto.html","topicUid":"EchoHub.Core.DTOs.EmbedDto","type":"Class"},{"name":"EncryptionKeyResponse","href":"core/EchoHub.Core.DTOs.EncryptionKeyResponse.html","topicHref":"core/EchoHub.Core.DTOs.EncryptionKeyResponse.html","topicUid":"EchoHub.Core.DTOs.EncryptionKeyResponse","type":"Class"},{"name":"ErrorResponse","href":"core/EchoHub.Core.DTOs.ErrorResponse.html","topicHref":"core/EchoHub.Core.DTOs.ErrorResponse.html","topicUid":"EchoHub.Core.DTOs.ErrorResponse","type":"Class"},{"name":"JoinChannelResult","href":"core/EchoHub.Core.DTOs.JoinChannelResult.html","topicHref":"core/EchoHub.Core.DTOs.JoinChannelResult.html","topicUid":"EchoHub.Core.DTOs.JoinChannelResult","type":"Class"},{"name":"KickRequest","href":"core/EchoHub.Core.DTOs.KickRequest.html","topicHref":"core/EchoHub.Core.DTOs.KickRequest.html","topicUid":"EchoHub.Core.DTOs.KickRequest","type":"Class"},{"name":"LoginRequest","href":"core/EchoHub.Core.DTOs.LoginRequest.html","topicHref":"core/EchoHub.Core.DTOs.LoginRequest.html","topicUid":"EchoHub.Core.DTOs.LoginRequest","type":"Class"},{"name":"LoginResponse","href":"core/EchoHub.Core.DTOs.LoginResponse.html","topicHref":"core/EchoHub.Core.DTOs.LoginResponse.html","topicUid":"EchoHub.Core.DTOs.LoginResponse","type":"Class"},{"name":"MessageDto","href":"core/EchoHub.Core.DTOs.MessageDto.html","topicHref":"core/EchoHub.Core.DTOs.MessageDto.html","topicUid":"EchoHub.Core.DTOs.MessageDto","type":"Class"},{"name":"MuteRequest","href":"core/EchoHub.Core.DTOs.MuteRequest.html","topicHref":"core/EchoHub.Core.DTOs.MuteRequest.html","topicUid":"EchoHub.Core.DTOs.MuteRequest","type":"Class"},{"name":"PaginatedResponse","href":"core/EchoHub.Core.DTOs.PaginatedResponse-1.html","topicHref":"core/EchoHub.Core.DTOs.PaginatedResponse-1.html","topicUid":"EchoHub.Core.DTOs.PaginatedResponse`1","type":"Class"},{"name":"RefreshRequest","href":"core/EchoHub.Core.DTOs.RefreshRequest.html","topicHref":"core/EchoHub.Core.DTOs.RefreshRequest.html","topicUid":"EchoHub.Core.DTOs.RefreshRequest","type":"Class"},{"name":"RegisterRequest","href":"core/EchoHub.Core.DTOs.RegisterRequest.html","topicHref":"core/EchoHub.Core.DTOs.RegisterRequest.html","topicUid":"EchoHub.Core.DTOs.RegisterRequest","type":"Class"},{"name":"RekeyChannelRequest","href":"core/EchoHub.Core.DTOs.RekeyChannelRequest.html","topicHref":"core/EchoHub.Core.DTOs.RekeyChannelRequest.html","topicUid":"EchoHub.Core.DTOs.RekeyChannelRequest","type":"Class"},{"name":"SendMessageRequest","href":"core/EchoHub.Core.DTOs.SendMessageRequest.html","topicHref":"core/EchoHub.Core.DTOs.SendMessageRequest.html","topicUid":"EchoHub.Core.DTOs.SendMessageRequest","type":"Class"},{"name":"SendUrlRequest","href":"core/EchoHub.Core.DTOs.SendUrlRequest.html","topicHref":"core/EchoHub.Core.DTOs.SendUrlRequest.html","topicUid":"EchoHub.Core.DTOs.SendUrlRequest","type":"Class"},{"name":"ServerStatusDto","href":"core/EchoHub.Core.DTOs.ServerStatusDto.html","topicHref":"core/EchoHub.Core.DTOs.ServerStatusDto.html","topicUid":"EchoHub.Core.DTOs.ServerStatusDto","type":"Class"},{"name":"UpdateProfileRequest","href":"core/EchoHub.Core.DTOs.UpdateProfileRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateProfileRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateProfileRequest","type":"Class"},{"name":"UpdateStatusRequest","href":"core/EchoHub.Core.DTOs.UpdateStatusRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateStatusRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateStatusRequest","type":"Class"},{"name":"UpdateTopicRequest","href":"core/EchoHub.Core.DTOs.UpdateTopicRequest.html","topicHref":"core/EchoHub.Core.DTOs.UpdateTopicRequest.html","topicUid":"EchoHub.Core.DTOs.UpdateTopicRequest","type":"Class"},{"name":"UserDto","href":"core/EchoHub.Core.DTOs.UserDto.html","topicHref":"core/EchoHub.Core.DTOs.UserDto.html","topicUid":"EchoHub.Core.DTOs.UserDto","type":"Class"},{"name":"UserError","href":"core/EchoHub.Core.DTOs.UserError.html","topicHref":"core/EchoHub.Core.DTOs.UserError.html","topicUid":"EchoHub.Core.DTOs.UserError","type":"Enum"},{"name":"UserOperationResult","href":"core/EchoHub.Core.DTOs.UserOperationResult.html","topicHref":"core/EchoHub.Core.DTOs.UserOperationResult.html","topicUid":"EchoHub.Core.DTOs.UserOperationResult","type":"Class"},{"name":"UserPresenceDto","href":"core/EchoHub.Core.DTOs.UserPresenceDto.html","topicHref":"core/EchoHub.Core.DTOs.UserPresenceDto.html","topicUid":"EchoHub.Core.DTOs.UserPresenceDto","type":"Class"},{"name":"UserProfileDto","href":"core/EchoHub.Core.DTOs.UserProfileDto.html","topicHref":"core/EchoHub.Core.DTOs.UserProfileDto.html","topicUid":"EchoHub.Core.DTOs.UserProfileDto","type":"Class"}]},{"name":"EchoHub.Core.Models","href":"core/EchoHub.Core.Models.html","topicHref":"core/EchoHub.Core.Models.html","topicUid":"EchoHub.Core.Models","type":"Namespace","items":[{"name":"Attachment","href":"core/EchoHub.Core.Models.Attachment.html","topicHref":"core/EchoHub.Core.Models.Attachment.html","topicUid":"EchoHub.Core.Models.Attachment","type":"Class"},{"name":"AttachmentKind","href":"core/EchoHub.Core.Models.AttachmentKind.html","topicHref":"core/EchoHub.Core.Models.AttachmentKind.html","topicUid":"EchoHub.Core.Models.AttachmentKind","type":"Enum"},{"name":"Channel","href":"core/EchoHub.Core.Models.Channel.html","topicHref":"core/EchoHub.Core.Models.Channel.html","topicUid":"EchoHub.Core.Models.Channel","type":"Class"},{"name":"ChannelMembership","href":"core/EchoHub.Core.Models.ChannelMembership.html","topicHref":"core/EchoHub.Core.Models.ChannelMembership.html","topicUid":"EchoHub.Core.Models.ChannelMembership","type":"Class"},{"name":"Message","href":"core/EchoHub.Core.Models.Message.html","topicHref":"core/EchoHub.Core.Models.Message.html","topicUid":"EchoHub.Core.Models.Message","type":"Class"},{"name":"MessageType","href":"core/EchoHub.Core.Models.MessageType.html","topicHref":"core/EchoHub.Core.Models.MessageType.html","topicUid":"EchoHub.Core.Models.MessageType","type":"Enum"},{"name":"RefreshToken","href":"core/EchoHub.Core.Models.RefreshToken.html","topicHref":"core/EchoHub.Core.Models.RefreshToken.html","topicUid":"EchoHub.Core.Models.RefreshToken","type":"Class"},{"name":"ServerRole","href":"core/EchoHub.Core.Models.ServerRole.html","topicHref":"core/EchoHub.Core.Models.ServerRole.html","topicUid":"EchoHub.Core.Models.ServerRole","type":"Enum"},{"name":"User","href":"core/EchoHub.Core.Models.User.html","topicHref":"core/EchoHub.Core.Models.User.html","topicUid":"EchoHub.Core.Models.User","type":"Class"},{"name":"UserStatus","href":"core/EchoHub.Core.Models.UserStatus.html","topicHref":"core/EchoHub.Core.Models.UserStatus.html","topicUid":"EchoHub.Core.Models.UserStatus","type":"Enum"}]},{"name":"EchoHub.Core.Security","href":"core/EchoHub.Core.Security.html","topicHref":"core/EchoHub.Core.Security.html","topicUid":"EchoHub.Core.Security","type":"Namespace","items":[{"name":"RoomCrypto","href":"core/EchoHub.Core.Security.RoomCrypto.html","topicHref":"core/EchoHub.Core.Security.RoomCrypto.html","topicUid":"EchoHub.Core.Security.RoomCrypto","type":"Class"},{"name":"RoomCrypto.DerivedKeys","href":"core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html","topicHref":"core/EchoHub.Core.Security.RoomCrypto.DerivedKeys.html","topicUid":"EchoHub.Core.Security.RoomCrypto.DerivedKeys","type":"Class"}]},{"name":"EchoHub.Core.Services","href":"core/EchoHub.Core.Services.html","topicHref":"core/EchoHub.Core.Services.html","topicUid":"EchoHub.Core.Services","type":"Namespace","items":[{"name":"FileValidationHelper","href":"core/EchoHub.Core.Services.FileValidationHelper.html","topicHref":"core/EchoHub.Core.Services.FileValidationHelper.html","topicUid":"EchoHub.Core.Services.FileValidationHelper","type":"Class"},{"name":"ImageToAsciiService","href":"core/EchoHub.Core.Services.ImageToAsciiService.html","topicHref":"core/EchoHub.Core.Services.ImageToAsciiService.html","topicUid":"EchoHub.Core.Services.ImageToAsciiService","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/core-articles/toc.yml","items":[{"name":"Overview","href":"core-articles/index.html","topicHref":"core-articles/index.html"}]}]},{"name":"Server","items":[{"name":"API Reference","includedFrom":"~/_api_meta/server/toc.yml","items":[{"name":"EchoHub.Server.Auth","href":"server/EchoHub.Server.Auth.html","topicHref":"server/EchoHub.Server.Auth.html","topicUid":"EchoHub.Server.Auth","type":"Namespace","items":[{"name":"JwtTokenService","href":"server/EchoHub.Server.Auth.JwtTokenService.html","topicHref":"server/EchoHub.Server.Auth.JwtTokenService.html","topicUid":"EchoHub.Server.Auth.JwtTokenService","type":"Class"}]},{"name":"EchoHub.Server.Config","href":"server/EchoHub.Server.Config.html","topicHref":"server/EchoHub.Server.Config.html","topicUid":"EchoHub.Server.Config","type":"Namespace","items":[{"name":"UploadLimits","href":"server/EchoHub.Server.Config.UploadLimits.html","topicHref":"server/EchoHub.Server.Config.UploadLimits.html","topicUid":"EchoHub.Server.Config.UploadLimits","type":"Class"}]},{"name":"EchoHub.Server.Controllers","href":"server/EchoHub.Server.Controllers.html","topicHref":"server/EchoHub.Server.Controllers.html","topicUid":"EchoHub.Server.Controllers","type":"Namespace","items":[{"name":"AuthController","href":"server/EchoHub.Server.Controllers.AuthController.html","topicHref":"server/EchoHub.Server.Controllers.AuthController.html","topicUid":"EchoHub.Server.Controllers.AuthController","type":"Class"},{"name":"ChannelsController","href":"server/EchoHub.Server.Controllers.ChannelsController.html","topicHref":"server/EchoHub.Server.Controllers.ChannelsController.html","topicUid":"EchoHub.Server.Controllers.ChannelsController","type":"Class"},{"name":"FilesController","href":"server/EchoHub.Server.Controllers.FilesController.html","topicHref":"server/EchoHub.Server.Controllers.FilesController.html","topicUid":"EchoHub.Server.Controllers.FilesController","type":"Class"},{"name":"ModerationController","href":"server/EchoHub.Server.Controllers.ModerationController.html","topicHref":"server/EchoHub.Server.Controllers.ModerationController.html","topicUid":"EchoHub.Server.Controllers.ModerationController","type":"Class"},{"name":"ServerController","href":"server/EchoHub.Server.Controllers.ServerController.html","topicHref":"server/EchoHub.Server.Controllers.ServerController.html","topicUid":"EchoHub.Server.Controllers.ServerController","type":"Class"},{"name":"UsersController","href":"server/EchoHub.Server.Controllers.UsersController.html","topicHref":"server/EchoHub.Server.Controllers.UsersController.html","topicUid":"EchoHub.Server.Controllers.UsersController","type":"Class"}]},{"name":"EchoHub.Server.Data","href":"server/EchoHub.Server.Data.html","topicHref":"server/EchoHub.Server.Data.html","topicUid":"EchoHub.Server.Data","type":"Namespace","items":[{"name":"EchoHubDbContext","href":"server/EchoHub.Server.Data.EchoHubDbContext.html","topicHref":"server/EchoHub.Server.Data.EchoHubDbContext.html","topicUid":"EchoHub.Server.Data.EchoHubDbContext","type":"Class"}]},{"name":"EchoHub.Server.Data.Migrations","href":"server/EchoHub.Server.Data.Migrations.html","topicHref":"server/EchoHub.Server.Data.Migrations.html","topicUid":"EchoHub.Server.Data.Migrations","type":"Namespace","items":[{"name":"AddAttachmentFileSize","href":"server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddAttachmentFileSize.html","topicUid":"EchoHub.Server.Data.Migrations.AddAttachmentFileSize","type":"Class"},{"name":"AddChannelEncryptionEnvelope","href":"server/EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelEncryptionEnvelope","type":"Class"},{"name":"AddChannelIsPublic","href":"server/EchoHub.Server.Data.Migrations.AddChannelIsPublic.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelIsPublic.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelIsPublic","type":"Class"},{"name":"AddChannelMembership","href":"server/EchoHub.Server.Data.Migrations.AddChannelMembership.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelMembership.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelMembership","type":"Class"},{"name":"AddChannelPasswordHash","href":"server/EchoHub.Server.Data.Migrations.AddChannelPasswordHash.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddChannelPasswordHash.html","topicUid":"EchoHub.Server.Data.Migrations.AddChannelPasswordHash","type":"Class"},{"name":"AddEncryptionSupport","href":"server/EchoHub.Server.Data.Migrations.AddEncryptionSupport.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddEncryptionSupport.html","topicUid":"EchoHub.Server.Data.Migrations.AddEncryptionSupport","type":"Class"},{"name":"AddMessageAttachments","href":"server/EchoHub.Server.Data.Migrations.AddMessageAttachments.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddMessageAttachments.html","topicUid":"EchoHub.Server.Data.Migrations.AddMessageAttachments","type":"Class"},{"name":"AddMessageEmbed","href":"server/EchoHub.Server.Data.Migrations.AddMessageEmbed.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddMessageEmbed.html","topicUid":"EchoHub.Server.Data.Migrations.AddMessageEmbed","type":"Class"},{"name":"AddModerationRoles","href":"server/EchoHub.Server.Data.Migrations.AddModerationRoles.html","topicHref":"server/EchoHub.Server.Data.Migrations.AddModerationRoles.html","topicUid":"EchoHub.Server.Data.Migrations.AddModerationRoles","type":"Class"},{"name":"InitialCreate","href":"server/EchoHub.Server.Data.Migrations.InitialCreate.html","topicHref":"server/EchoHub.Server.Data.Migrations.InitialCreate.html","topicUid":"EchoHub.Server.Data.Migrations.InitialCreate","type":"Class"}]},{"name":"EchoHub.Server.Hubs","href":"server/EchoHub.Server.Hubs.html","topicHref":"server/EchoHub.Server.Hubs.html","topicUid":"EchoHub.Server.Hubs","type":"Namespace","items":[{"name":"ChatHub","href":"server/EchoHub.Server.Hubs.ChatHub.html","topicHref":"server/EchoHub.Server.Hubs.ChatHub.html","topicUid":"EchoHub.Server.Hubs.ChatHub","type":"Class"}]},{"name":"EchoHub.Server.Services","href":"server/EchoHub.Server.Services.html","topicHref":"server/EchoHub.Server.Services.html","topicUid":"EchoHub.Server.Services","type":"Namespace","items":[{"name":"ChannelService","href":"server/EchoHub.Server.Services.ChannelService.html","topicHref":"server/EchoHub.Server.Services.ChannelService.html","topicUid":"EchoHub.Server.Services.ChannelService","type":"Class"},{"name":"ChatService","href":"server/EchoHub.Server.Services.ChatService.html","topicHref":"server/EchoHub.Server.Services.ChatService.html","topicUid":"EchoHub.Server.Services.ChatService","type":"Class"},{"name":"DirectoryClaimStore","href":"server/EchoHub.Server.Services.DirectoryClaimStore.html","topicHref":"server/EchoHub.Server.Services.DirectoryClaimStore.html","topicUid":"EchoHub.Server.Services.DirectoryClaimStore","type":"Class"},{"name":"FileCleanupService","href":"server/EchoHub.Server.Services.FileCleanupService.html","topicHref":"server/EchoHub.Server.Services.FileCleanupService.html","topicUid":"EchoHub.Server.Services.FileCleanupService","type":"Class"},{"name":"FileStorageService","href":"server/EchoHub.Server.Services.FileStorageService.html","topicHref":"server/EchoHub.Server.Services.FileStorageService.html","topicUid":"EchoHub.Server.Services.FileStorageService","type":"Class"},{"name":"LinkEmbedService","href":"server/EchoHub.Server.Services.LinkEmbedService.html","topicHref":"server/EchoHub.Server.Services.LinkEmbedService.html","topicUid":"EchoHub.Server.Services.LinkEmbedService","type":"Class"},{"name":"MessageEncryptionService","href":"server/EchoHub.Server.Services.MessageEncryptionService.html","topicHref":"server/EchoHub.Server.Services.MessageEncryptionService.html","topicUid":"EchoHub.Server.Services.MessageEncryptionService","type":"Class"},{"name":"MuteExpirationService","href":"server/EchoHub.Server.Services.MuteExpirationService.html","topicHref":"server/EchoHub.Server.Services.MuteExpirationService.html","topicUid":"EchoHub.Server.Services.MuteExpirationService","type":"Class"},{"name":"PresenceTracker","href":"server/EchoHub.Server.Services.PresenceTracker.html","topicHref":"server/EchoHub.Server.Services.PresenceTracker.html","topicUid":"EchoHub.Server.Services.PresenceTracker","type":"Class"},{"name":"RegistrationStatus","href":"server/EchoHub.Server.Services.RegistrationStatus.html","topicHref":"server/EchoHub.Server.Services.RegistrationStatus.html","topicUid":"EchoHub.Server.Services.RegistrationStatus","type":"Class"},{"name":"ServerDirectoryService","href":"server/EchoHub.Server.Services.ServerDirectoryService.html","topicHref":"server/EchoHub.Server.Services.ServerDirectoryService.html","topicUid":"EchoHub.Server.Services.ServerDirectoryService","type":"Class"},{"name":"SignalRBroadcaster","href":"server/EchoHub.Server.Services.SignalRBroadcaster.html","topicHref":"server/EchoHub.Server.Services.SignalRBroadcaster.html","topicUid":"EchoHub.Server.Services.SignalRBroadcaster","type":"Class"},{"name":"UserService","href":"server/EchoHub.Server.Services.UserService.html","topicHref":"server/EchoHub.Server.Services.UserService.html","topicUid":"EchoHub.Server.Services.UserService","type":"Class"}]},{"name":"EchoHub.Server.Setup","href":"server/EchoHub.Server.Setup.html","topicHref":"server/EchoHub.Server.Setup.html","topicUid":"EchoHub.Server.Setup","type":"Namespace","items":[{"name":"DataMigrationService","href":"server/EchoHub.Server.Setup.DataMigrationService.html","topicHref":"server/EchoHub.Server.Setup.DataMigrationService.html","topicUid":"EchoHub.Server.Setup.DataMigrationService","type":"Class"},{"name":"DatabaseSetup","href":"server/EchoHub.Server.Setup.DatabaseSetup.html","topicHref":"server/EchoHub.Server.Setup.DatabaseSetup.html","topicUid":"EchoHub.Server.Setup.DatabaseSetup","type":"Class"},{"name":"FirstRunSetup","href":"server/EchoHub.Server.Setup.FirstRunSetup.html","topicHref":"server/EchoHub.Server.Setup.FirstRunSetup.html","topicUid":"EchoHub.Server.Setup.FirstRunSetup","type":"Class"}]}]},{"name":"Articles","includedFrom":"~/api/server-articles/toc.yml","items":[{"name":"Overview","href":"server-articles/index.html","topicHref":"server-articles/index.html"}]}]},{"name":"Server.Irc","items":[{"name":"API Reference","includedFrom":"~/_api_meta/server-irc/toc.yml","items":[{"name":"EchoHub.Server.Irc","href":"server-irc/EchoHub.Server.Irc.html","topicHref":"server-irc/EchoHub.Server.Irc.html","topicUid":"EchoHub.Server.Irc","type":"Namespace","items":[{"name":"IrcBroadcaster","href":"server-irc/EchoHub.Server.Irc.IrcBroadcaster.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcBroadcaster.html","topicUid":"EchoHub.Server.Irc.IrcBroadcaster","type":"Class"},{"name":"IrcClientConnection","href":"server-irc/EchoHub.Server.Irc.IrcClientConnection.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcClientConnection.html","topicUid":"EchoHub.Server.Irc.IrcClientConnection","type":"Class"},{"name":"IrcCommandHandler","href":"server-irc/EchoHub.Server.Irc.IrcCommandHandler.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcCommandHandler.html","topicUid":"EchoHub.Server.Irc.IrcCommandHandler","type":"Class"},{"name":"IrcGatewayService","href":"server-irc/EchoHub.Server.Irc.IrcGatewayService.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcGatewayService.html","topicUid":"EchoHub.Server.Irc.IrcGatewayService","type":"Class"},{"name":"IrcMessage","href":"server-irc/EchoHub.Server.Irc.IrcMessage.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcMessage.html","topicUid":"EchoHub.Server.Irc.IrcMessage","type":"Class"},{"name":"IrcMessageFormatter","href":"server-irc/EchoHub.Server.Irc.IrcMessageFormatter.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcMessageFormatter.html","topicUid":"EchoHub.Server.Irc.IrcMessageFormatter","type":"Class"},{"name":"IrcNumericReply","href":"server-irc/EchoHub.Server.Irc.IrcNumericReply.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcNumericReply.html","topicUid":"EchoHub.Server.Irc.IrcNumericReply","type":"Class"},{"name":"IrcOptions","href":"server-irc/EchoHub.Server.Irc.IrcOptions.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcOptions.html","topicUid":"EchoHub.Server.Irc.IrcOptions","type":"Class"},{"name":"IrcServiceExtensions","href":"server-irc/EchoHub.Server.Irc.IrcServiceExtensions.html","topicHref":"server-irc/EchoHub.Server.Irc.IrcServiceExtensions.html","topicUid":"EchoHub.Server.Irc.IrcServiceExtensions","type":"Class"}]}]}]}]} diff --git a/articles/encrypted-rooms.html b/articles/encrypted-rooms.html new file mode 100644 index 0000000..7f258ff --- /dev/null +++ b/articles/encrypted-rooms.html @@ -0,0 +1,271 @@ + + + + + Encrypted Rooms (Password-Protected Channels) | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    +
    +
    +
    Table of Contents
    + +
    +
    + +
    +
    +
    + +
    +
    + + + +
    + +
    +

    Encrypted Rooms (Password-Protected Channels)

    + +

    An encrypted room is a channel whose entire content — every message and every file — is +end-to-end encrypted with a key derived from a shared passphrase. Only people who know the +passphrase can read the room. Not even the server owner can read the content, yet the server +can still gate who joins, and it can count and measure what's stored (message count, file sizes, +timestamps) without ever seeing the plaintext.

    +

    This is a stronger guarantee than the transport and at-rest encryption described +elsewhere, where the server decrypts every message to process it. Here the server is treated as +untrusted for content: it holds only ciphertext and wrapped keys.

    +
    +

    The passphrase is the only key. There is no recovery. If everyone who knows a room's +passphrase forgets it, that room's history is permanently unreadable — by design.

    +
    +

    What the server can and cannot see

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    The server can seeThe server cannot see
    That the channel is encryptedMessage text
    Message count and timestampsFile contents
    Who sent each message (sender identity)Image previews (ASCII art)
    Each attachment's file name and byte sizeThe passphrase, the room key, or the key-encryption key
    The estimated total size (via /meta)Anything that would let it decrypt the above
    +

    File names are stored in plaintext so the file list stays usable — treat a file name itself as +non-secret. Everything inside the file is encrypted.

    +

    Key hierarchy

    +

    Three keys are derived from one passphrase. The passphrase, the key-encryption key, and the room +content key never leave the client.

    +
    flowchart TD
    +    P[Passphrase] -->|PBKDF2-SHA256, 210k iterations, per-room salt| OKM[64-byte output]
    +    OKM --> AK["Auth key (first 32 bytes)"]
    +    OKM --> KEK["Key-encryption key / KEK (last 32 bytes)"]
    +    AK -->|sent as lowercase hex| SRV1["Server: BCrypt-hash as the join gate"]
    +    RCK["Room Content Key (random 256-bit)"] -->|encrypts all content| CONTENT[Messages + files + previews]
    +    RCK -->|AES-256-GCM wrap under KEK| WRAP["Wrapped room key"]
    +    WRAP -->|stored| SRV2["Server: stores wrapped key + salt only"]
    +
    +
      +
    • Auth key — the join credential. Derived from the passphrase, sent to the server as hex, and +stored only as a BCrypt hash. Proving knowledge of it is what lets you join; it reveals +nothing about the content key.
    • +
    • Key-encryption key (KEK) — never sent. Used locally to wrap (encrypt) and unwrap the room +content key.
    • +
    • Room Content Key (RCK) — a random 256-bit key generated once, at room creation. It encrypts +every message and file. The server stores it only in wrapped form, so it can hand the wrapped key +to a joiner but can never unwrap it itself.
    • +
    +

    All content encryption is AES-256-GCM with a random 12-byte nonce and a 16-byte authentication +tag per item, so identical inputs never produce identical ciphertext, and any tampering is detected.

    +

    Room-encrypted text carries a self-describing prefix so clients and the server can tell it apart +from plaintext:

    +
    $RC1$base64(nonce || tag || ciphertext)
    +
    +

    Creating a room

    +

    The client does all the cryptography locally, then hands the server only what it needs to gate joins +and store (but not read) the content.

    +
    sequenceDiagram
    +    participant Client
    +    participant Server
    +
    +    Client->>Client: generate salt + random Room Content Key (RCK)
    +    Client->>Client: DeriveKeys(passphrase, salt) → auth key + KEK
    +    Client->>Client: wrap RCK under KEK
    +    Client->>Server: create channel { authKey(hex), salt, wrappedRoomKey }
    +    Server->>Server: BCrypt-hash auth key, store salt + wrapped key
    +    Note over Server: Server never receives passphrase, KEK, or RCK
    +
    +

    Joining a room

    +
    sequenceDiagram
    +    participant Client
    +    participant Server
    +
    +    Client->>Server: GET /crypto → { isEncrypted, salt }
    +    Client->>Client: DeriveKeys(passphrase, salt) → auth key + KEK
    +    Client->>Server: join { authKey(hex) }
    +    Server->>Server: BCrypt-verify against stored hash
    +    alt correct passphrase
    +        Server->>Client: history (ciphertext) + wrapped room key
    +        Client->>Client: unwrap RCK with KEK, then decrypt everything locally
    +    else wrong passphrase
    +        Server->>Client: rejected (join gate fails)
    +    end
    +
    +

    A wrong passphrase fails the BCrypt gate, so the server never even hands out the wrapped key. Even if +it did, an attacker without the KEK cannot unwrap it.

    +

    What gets encrypted

    +

    When you send a message or attach files to an encrypted room, the client encrypts each part with the +room content key before uploading:

    +
      +
    • Message text$RC1$… ciphertext.
    • +
    • Files (any kind) → the whole blob is AES-256-GCM encrypted client-side; the server stores an +opaque ciphertext blob.
    • +
    • Image ASCII previews → rendered on the client, then room-encrypted. The server never sees the +rendered art.
    • +
    +

    The server records each attachment's kind, file name, and byte size (of the ciphertext +blob) as metadata, and broadcasts the ciphertext to other members, who decrypt locally.

    +

    Changing the passphrase

    +

    /passwd <old> <new> rotates the passphrase. Because only the wrapping of the room content key +changes — not the RCK itself — all existing history stays readable:

    +
      +
    1. The client proves knowledge of the old passphrase (old auth key).
    2. +
    3. It unwraps the RCK with the old KEK, then re-wraps it under the new KEK (new salt).
    4. +
    5. It uploads the new auth key + salt + re-wrapped key. The content is never re-encrypted.
    6. +
    +

    Inspecting a room

    +

    Use /meta in any channel to see what the server knows about it, including encrypted rooms:

    +
    Room info for #private-room:
    +  Room ID       3f2a…-…-…
    +  Created       7/16/2026 2:31 PM
    +  Messages      128
    +  Unique users  4
    +  Est. size     42.5 MB
    +  Protection    end-to-end encrypted
    +
    +

    Est. size is the sum of stored attachment blob sizes plus message text length — an estimate of the +room's footprint, computed entirely from metadata the server holds without reading any content.

    +

    Limitations & security notes

    +
      +
    • No recovery. A lost passphrase means unrecoverable history. Keep it safe; there is no reset.
    • +
    • File names are plaintext. They stay readable so the file list works — don't put secrets in a +file name.
    • +
    • IRC is disabled for encrypted rooms. The IRC gateway forwards plaintext and cannot participate +in the room's key scheme, so encrypted channels are not bridged to IRC.
    • +
    • Metadata is visible. Message counts, timestamps, sender identities, file names, and sizes are +intentionally readable so the server can moderate at the metadata level and report /meta.
    • +
    • Endpoint trust. End-to-end encryption protects content from the server and the network, not +from a compromised client device that already holds the passphrase.
    • +
    + +
      +
    • Message Encryption — transport ($ENC$v1$) and optional at-rest database +encryption, where the server does decrypt content for processing. Encrypted rooms are a separate, +stronger layer that sits on top.
    • +
    + +
    + + + + + +
    + +
    + +
    +
    + +
    + + + + diff --git a/articles/encryption.html b/articles/encryption.html index 14307d9..e678055 100644 --- a/articles/encryption.html +++ b/articles/encryption.html @@ -197,7 +197,7 @@

    Limitations

    • TLS-inspecting proxies — if a corporate proxy terminates TLS with a trusted root CA, it can intercept the key exchange (GET /api/server/encryption-key) and read all traffic. A future upgrade to ECDH key exchange would address this.
    • -
    • Server has full access — the server decrypts all messages for processing. This is not end-to-end encryption between users; it's transport encryption between client and server.
    • +
    • Server has full access — the server decrypts all messages for processing. This is not end-to-end encryption between users; it's transport encryption between client and server. For true end-to-end encryption where the server cannot read content, use encrypted rooms.
    • IRC clients receive plaintext — IRC is an open protocol and third-party clients cannot participate in the encryption scheme.

    Troubleshooting

    diff --git a/articles/toc.html b/articles/toc.html index dc29b5a..25dea6e 100644 --- a/articles/toc.html +++ b/articles/toc.html @@ -32,6 +32,9 @@
  • Encryption
  • +
  • + Encrypted Rooms +
  • Notification Sounds
  • diff --git a/articles/toc.json b/articles/toc.json index 81e02ea..5189fb1 100644 --- a/articles/toc.json +++ b/articles/toc.json @@ -1,2 +1,2 @@ -{"items":[{"name":"Guides","items":[{"name":"Getting Started","href":"getting-started.html","topicHref":"getting-started.html"},{"name":"Docker","href":"docker.html","topicHref":"docker.html"},{"name":"Architecture","href":"architecture.html","topicHref":"architecture.html"},{"name":"Configuration","href":"configuration.html","topicHref":"configuration.html"},{"name":"Encryption","href":"encryption.html","topicHref":"encryption.html"},{"name":"Notification Sounds","href":"notification-sounds.html","topicHref":"notification-sounds.html"}]},{"name":"Flows","includedFrom":"~/flows/toc.yml","items":[{"name":"Authentication","href":"../flows/authentication.html","topicHref":"../flows/authentication.html"},{"name":"Connection","href":"../flows/connection.html","topicHref":"../flows/connection.html"},{"name":"Messaging","href":"../flows/messaging.html","topicHref":"../flows/messaging.html"},{"name":"Channels","href":"../flows/channels.html","topicHref":"../flows/channels.html"},{"name":"Moderation","href":"../flows/moderation.html","topicHref":"../flows/moderation.html"},{"name":"Media & Services","href":"../flows/media.html","topicHref":"../flows/media.html"}]}]} +{"items":[{"name":"Guides","items":[{"name":"Getting Started","href":"getting-started.html","topicHref":"getting-started.html"},{"name":"Docker","href":"docker.html","topicHref":"docker.html"},{"name":"Architecture","href":"architecture.html","topicHref":"architecture.html"},{"name":"Configuration","href":"configuration.html","topicHref":"configuration.html"},{"name":"Encryption","href":"encryption.html","topicHref":"encryption.html"},{"name":"Encrypted Rooms","href":"encrypted-rooms.html","topicHref":"encrypted-rooms.html"},{"name":"Notification Sounds","href":"notification-sounds.html","topicHref":"notification-sounds.html"}]},{"name":"Flows","includedFrom":"~/flows/toc.yml","items":[{"name":"Authentication","href":"../flows/authentication.html","topicHref":"../flows/authentication.html"},{"name":"Connection","href":"../flows/connection.html","topicHref":"../flows/connection.html"},{"name":"Messaging","href":"../flows/messaging.html","topicHref":"../flows/messaging.html"},{"name":"Channels","href":"../flows/channels.html","topicHref":"../flows/channels.html"},{"name":"Moderation","href":"../flows/moderation.html","topicHref":"../flows/moderation.html"},{"name":"Media & Services","href":"../flows/media.html","topicHref":"../flows/media.html"}]}]} diff --git a/changelog/index.html b/changelog/index.html index ca8ee1d..12f86ef 100644 --- a/changelog/index.html +++ b/changelog/index.html @@ -90,6 +90,7 @@

    Release history for EchoHub.

    Releases

    Bug Fixes

    API Changes