Skip to content

Commit

Permalink
channel list ordering
Browse files Browse the repository at this point in the history
-also fixes ordering for non TEXT channels (e.g. announcement) in comparison to VOICE channels
  • Loading branch information
exp111 committed Nov 20, 2023
1 parent 9115ac5 commit 8aa155b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 39 deletions.
114 changes: 77 additions & 37 deletions Turbulence.Core/ViewModels/ChannelListViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.Messaging;
using Turbulence.Discord;
using Turbulence.Discord.Models;
using Turbulence.Discord.Models.DiscordChannel;
using Turbulence.Discord.Models.DiscordGuild;
using Turbulence.Discord.Models.DiscordPermissions;

namespace Turbulence.Core.ViewModels;

Expand All @@ -26,55 +29,92 @@ public ChannelListViewModel()

public void Receive(SetChannelsMsg m) => Channels.ReplaceAll(m.Channels);

public async void Receive(ServerSelectedMsg m)
private bool CanSeeChannel(Guild Server, Channel channel, BigInteger perms, List<Role> myRoles)
{
Channels.Clear();

// TODO: Move this to its own method
if (m.Server.OwnerId == _client.CurrentUser?.Id)
if (Server.OwnerId == _client.CurrentUser?.Id)
{
Channels.ReplaceAll(m.Server.Channels);
return true;
}
else

var channelPerms = perms;
if (channel.PermissionOverwrites is { } overwrites)
{
var everyoneRole = m.Server.Roles.First(r => r.Id == m.Server.Id);
// TODO: Get rid of API call
var myGuildMember = await Api.GetCurrentUserGuildMember(_client.HttpClient, m.Server.Id);
var myRoles = m.Server.Roles.Where(r => myGuildMember.Roles.Contains(r.Id)).ToList();
List<Overwrite> toApply = new();
if (overwrites.FirstOrDefault(o => o.Id == Server.Id) is { } everyoneOverwrite)
toApply.Add(everyoneOverwrite);

var perms = BigInteger.Parse(everyoneRole.Permissions);
// Add overwrites for my roles
toApply.AddRange(overwrites.Where(o => o.Type == 0 && myRoles.Exists(r => r.Id == o.Id)));
// Add overwrites for me specifically
toApply.AddRange(overwrites.Where(o => o.Type == 1 && o.Id == _client.CurrentUser?.Id));

foreach (var role in myRoles)
// Then apply
foreach (var overwrite in toApply)
{
perms |= BigInteger.Parse(role.Permissions);
channelPerms |= BigInteger.Parse(overwrite.Allow);
channelPerms &= ~BigInteger.Parse(overwrite.Deny);
}
}

foreach (var channel in m.Server.Channels.Order())
{
var channelPerms = perms;
if (channel.PermissionOverwrites is { } overwrites)
{
List<Overwrite> toApply = new();
if (overwrites.FirstOrDefault(o => o.Id == m.Server.Id) is { } everyoneOverwrite)
toApply.Add(everyoneOverwrite);
// Add to channel list if we have permission to view it
// TODO: Use enum flag here
return (channelPerms & (1 << 10)) != 0;
}

// Add overwrites for my roles
toApply.AddRange(overwrites.Where(o => o.Type == 0 && myRoles.Exists(r => r.Id == o.Id)));
// Add overwrites for me specifically
toApply.AddRange(overwrites.Where(o => o.Type == 1 && o.Id == _client.CurrentUser?.Id));
public async void Receive(ServerSelectedMsg m)
{
Channels.Clear();

// Then apply
foreach (var overwrite in toApply)
{
channelPerms |= BigInteger.Parse(overwrite.Allow);
channelPerms &= ~BigInteger.Parse(overwrite.Deny);
}
}
// Calculate permissions //TODO: move into client
var everyoneRole = m.Server.Roles.First(r => r.Id == m.Server.Id);
// TODO: Get rid of API call
var myGuildMember = await Api.GetCurrentUserGuildMember(_client.HttpClient, m.Server.Id);
var myRoles = m.Server.Roles.Where(r => myGuildMember.Roles.Contains(r.Id)).ToList();
// Parse base permission for everyone
var perms = BigInteger.Parse(everyoneRole.Permissions);
// Add our permission onto it
foreach (var role in myRoles)
{
perms |= BigInteger.Parse(role.Permissions);
}

var topLevel = new List<Channel>();
var subChannels = new Dictionary<Snowflake, List<Channel>>();
// iterate over list
foreach (var channel in m.Server.Channels)
{
//TODO: permission filtering
if (!CanSeeChannel(m.Server, channel, perms, myRoles))
continue;

// Add to channel list if we have permission to view it
// TODO: Use enum flag here
if ((channelPerms & (1 << 10)) != 0)
Channels.Add(channel);
// save top level channels/categories into one list
if (channel.ParentId == null)
{
topLevel.Add(channel);
}
else // save every other channel into a dict<parentid, list>
{
if (!subChannels.TryGetValue(channel.ParentId, out var list))
{
list = new();
subChannels.Add(channel.ParentId, list);
}
list.Add(channel);
}
}
// Sort
topLevel.Sort();
foreach (var l in subChannels.Values)
l.Sort();
// Then add each top level channel
foreach (var cat in topLevel)
{
Channels.Add(cat);
// Add child channels if they exist
if (subChannels.TryGetValue(cat.Id, out var list))
{
foreach (var c in list)
Channels.Add(c);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions Turbulence.Discord/Models/DiscordChannel/Channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,8 @@ public static int ComparePositionTo(this ChannelType type, ChannelType other)
not GUILD_CATEGORY when other is GUILD_CATEGORY => -1,

// Text channels go before voice channels
GUILD_VOICE when other is GUILD_TEXT => 1,
GUILD_TEXT when other is GUILD_VOICE => -1,
GUILD_VOICE when other is not GUILD_VOICE => 1,
not GUILD_VOICE when other is GUILD_VOICE => -1,

// TODO: Implement more cases

Expand Down

0 comments on commit 8aa155b

Please sign in to comment.