From 3eccedfad41771b49c531444e08c550115994316 Mon Sep 17 00:00:00 2001 From: Andrija Stevanovic Date: Sun, 8 Mar 2026 02:29:39 +0100 Subject: [PATCH] ui polish --- dotnet/AipsRT/Hubs/WhiteboardHub.cs | 46 +++++++++- .../Model/Whiteboard/GetWhiteboardService.cs | 1 + dotnet/AipsRT/Model/Whiteboard/Whiteboard.cs | 6 ++ front/src/assets/scss/_app.scss | 4 + front/src/assets/scss/_variables.scss | 2 - front/src/components/AppTopBar.vue | 49 ++++++++++- .../src/components/RecentWhiteboardsItem.vue | 2 +- .../src/components/RecentWhiteboardsPanel.vue | 2 +- .../src/components/WhiteboardHistoryItem.vue | 2 +- .../components/WhiteboardHistorySidebar.vue | 2 +- .../whiteboard/WhiteboardToolbar.vue | 83 +++++++++++++++++-- front/src/composables/useShapeOwner.ts | 2 +- front/src/router/index.ts | 6 -- front/src/services/whiteboardHubService.ts | 4 +- front/src/stores/whiteboard.ts | 13 ++- front/src/types/whiteboard.ts | 2 + front/src/views/AboutView.vue | 3 - front/src/views/HomeView.vue | 23 ++++- 18 files changed, 217 insertions(+), 35 deletions(-) delete mode 100644 front/src/views/AboutView.vue diff --git a/dotnet/AipsRT/Hubs/WhiteboardHub.cs b/dotnet/AipsRT/Hubs/WhiteboardHub.cs index 2e95221..a94589c 100644 --- a/dotnet/AipsRT/Hubs/WhiteboardHub.cs +++ b/dotnet/AipsRT/Hubs/WhiteboardHub.cs @@ -5,6 +5,7 @@ using AipsCore.Application.Models.Whiteboard.Command.RejectUserRequestToJoin; using AipsCore.Application.Models.Whiteboard.Query.GetMembershipStatus; using AipsCore.Domain.Models.WhiteboardMembership.Enums; using AipsRT.Model.Memberships; +using AipsRT.Model.Users; using AipsRT.Model.Whiteboard; using AipsRT.Model.Whiteboard.Shapes; using AipsRT.Model.Whiteboard.Structs; @@ -28,6 +29,23 @@ public class WhiteboardHub : Hub _membershipService = membershipService; } + public override async Task OnDisconnectedAsync(Exception? exception) + { + var userId = CurrentUserId; + var whiteboard = _whiteboardManager.GetWhiteboardForUser(userId); + + if (whiteboard != null) + { + whiteboard.RemoveActiveUser(userId); + _whiteboardManager.RemoveUserFromWhiteboard(userId); + + await Clients.Group(whiteboard.WhiteboardId.ToString()) + .SendAsync("Leaved", userId.ToString()); + } + + await base.OnDisconnectedAsync(exception); + } + public async Task JoinWhiteboard(Guid whiteboardId) { if (!_whiteboardManager.WhiteboardExists(whiteboardId)) @@ -56,11 +74,28 @@ public class WhiteboardHub : Hub if (status == WhiteboardMembershipStatus.Accepted) { _whiteboardManager.AddUserToWhiteboard(userId, whiteboardId); - + + var joiningUser = whiteboard.Users.FirstOrDefault(u => u.UserId == userId); + if (joiningUser == null) + { + if (ownerId == userId) + { + joiningUser = whiteboard.Owner; + } + else + { + joiningUser = new User(userId, Context.User?.Identity?.Name ?? "Unknown", + ""); + whiteboard.AddUser(joiningUser); + } + } + whiteboard.AddActiveUser(joiningUser); + var state = _whiteboardManager.GetWhiteboard(whiteboardId)!; await Clients.Caller.SendAsync("InitWhiteboard", state); - - await Clients.GroupExcept(whiteboardId.ToString(), Context.ConnectionId).SendAsync("Joined", Context.UserIdentifier!); + + await Clients.GroupExcept(whiteboardId.ToString(), + Context.ConnectionId).SendAsync("Joined", joiningUser); } else { @@ -104,8 +139,13 @@ public class WhiteboardHub : Hub public async Task LeaveWhiteboard(Guid whiteboardId) { + var userId = CurrentUserId; + _whiteboardManager.RemoveUserFromWhiteboard(userId); + _whiteboardManager.GetWhiteboard(whiteboardId)?.RemoveActiveUser(userId); + await Clients.GroupExcept(whiteboardId.ToString(), Context.ConnectionId) .SendAsync("Leaved", Context.UserIdentifier!); + } private Guid CurrentUserId => Guid.Parse(Context.UserIdentifier!); diff --git a/dotnet/AipsRT/Model/Whiteboard/GetWhiteboardService.cs b/dotnet/AipsRT/Model/Whiteboard/GetWhiteboardService.cs index 3ed67ad..68f72ed 100644 --- a/dotnet/AipsRT/Model/Whiteboard/GetWhiteboardService.cs +++ b/dotnet/AipsRT/Model/Whiteboard/GetWhiteboardService.cs @@ -28,6 +28,7 @@ public class GetWhiteboardService { WhiteboardId = entity.Id, OwnerId = entity.OwnerId, + Owner = new User(entity.Owner.Id, entity.Owner.UserName!, entity.Owner.Email!) }; foreach (var membership in entity.Memberships) diff --git a/dotnet/AipsRT/Model/Whiteboard/Whiteboard.cs b/dotnet/AipsRT/Model/Whiteboard/Whiteboard.cs index 8d48b1f..87a728e 100644 --- a/dotnet/AipsRT/Model/Whiteboard/Whiteboard.cs +++ b/dotnet/AipsRT/Model/Whiteboard/Whiteboard.cs @@ -8,9 +8,15 @@ public class Whiteboard public Guid WhiteboardId { get; set; } public Guid OwnerId { get; set; } + public User Owner { get; set; } = null!; public List Users { get; } = []; + public List ActiveUsers { get; } = []; + public void AddActiveUser(User user) => ActiveUsers.Add(user); + public void RemoveActiveUser(Guid userId) + => ActiveUsers.RemoveAll(u => u.UserId == userId); + public List Shapes { get; } = []; public List Rectangles { get; } = []; diff --git a/front/src/assets/scss/_app.scss b/front/src/assets/scss/_app.scss index 145df45..f4286b6 100644 --- a/front/src/assets/scss/_app.scss +++ b/front/src/assets/scss/_app.scss @@ -4,3 +4,7 @@ max-width: 420px; margin: 4rem auto; } + +.btn-close { + filter: invert(1) grayscale(100%) brightness(200%); +} diff --git a/front/src/assets/scss/_variables.scss b/front/src/assets/scss/_variables.scss index 00f0095..99c8619 100644 --- a/front/src/assets/scss/_variables.scss +++ b/front/src/assets/scss/_variables.scss @@ -22,5 +22,3 @@ $border-color: #2a2a2a; $link-color: $primary; -$btn-close-color: #e5e7eb; -$btn-close-filter: invert(1); diff --git a/front/src/components/AppTopBar.vue b/front/src/components/AppTopBar.vue index 6728df0..534f4cc 100644 --- a/front/src/components/AppTopBar.vue +++ b/front/src/components/AppTopBar.vue @@ -1,8 +1,10 @@ diff --git a/front/src/components/RecentWhiteboardsItem.vue b/front/src/components/RecentWhiteboardsItem.vue index 07b53ef..e149837 100644 --- a/front/src/components/RecentWhiteboardsItem.vue +++ b/front/src/components/RecentWhiteboardsItem.vue @@ -19,7 +19,7 @@ const handleClick = () => emit('click', props.whiteboard) @click="handleClick" >
-
{{ whiteboard.title }}
+
{{ whiteboard.title }}
{{ formatDate(whiteboard.createdAt) }}
diff --git a/front/src/components/RecentWhiteboardsPanel.vue b/front/src/components/RecentWhiteboardsPanel.vue index 5b686c8..35d49cf 100644 --- a/front/src/components/RecentWhiteboardsPanel.vue +++ b/front/src/components/RecentWhiteboardsPanel.vue @@ -18,7 +18,7 @@ import RecentWhiteboardsList from './RecentWhiteboardsList.vue' @@ -140,6 +143,28 @@ const copyCodeToClipboard = async () => { +
+
Participants ({{ sessionStore.connectedUsers.length }})
+
+
+ + {{ (user.username || '?').charAt(0).toUpperCase() }} + + + {{ user.username || 'Unknown' }} + (You) + +
+
+
+