mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2025-04-17 14:34:05 -05:00

* Migrate friends service to new IPC * Add a note that the pointer buffer size and domain counts are wrong * Wrong length * Format whitespace * PR feedback * Fill in structs from PR feedback * Missed that one * Somehow forgot to save that one * Fill in enums from PR review * Language enum, NotificationTime * Format whitespace * Fix the warning
173 lines
5.7 KiB
C#
173 lines
5.7 KiB
C#
using Ryujinx.Horizon.Common;
|
|
using Ryujinx.Horizon.Sdk.Account;
|
|
using Ryujinx.Horizon.Sdk.OsTypes;
|
|
using Ryujinx.Horizon.Sdk.Sf;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Ryujinx.Horizon.Sdk.Friends.Detail.Ipc
|
|
{
|
|
partial class NotificationService : INotificationService, IDisposable
|
|
{
|
|
private readonly NotificationEventHandler _notificationEventHandler;
|
|
private readonly Uid _userId;
|
|
private readonly FriendsServicePermissionLevel _permissionLevel;
|
|
|
|
private readonly object _lock = new();
|
|
|
|
private SystemEventType _notificationEvent;
|
|
|
|
private readonly LinkedList<SizedNotificationInfo> _notifications;
|
|
|
|
private bool _hasNewFriendRequest;
|
|
private bool _hasFriendListUpdate;
|
|
|
|
public NotificationService(NotificationEventHandler notificationEventHandler, Uid userId, FriendsServicePermissionLevel permissionLevel)
|
|
{
|
|
_notificationEventHandler = notificationEventHandler;
|
|
_userId = userId;
|
|
_permissionLevel = permissionLevel;
|
|
_notifications = new LinkedList<SizedNotificationInfo>();
|
|
Os.CreateSystemEvent(out _notificationEvent, EventClearMode.AutoClear, interProcess: true).AbortOnFailure();
|
|
|
|
_hasNewFriendRequest = false;
|
|
_hasFriendListUpdate = false;
|
|
|
|
notificationEventHandler.RegisterNotificationService(this);
|
|
}
|
|
|
|
[CmifCommand(0)]
|
|
public Result GetEvent([CopyHandle] out int eventHandle)
|
|
{
|
|
eventHandle = Os.GetReadableHandleOfSystemEvent(ref _notificationEvent);
|
|
|
|
return Result.Success;
|
|
}
|
|
|
|
[CmifCommand(1)]
|
|
public Result Clear()
|
|
{
|
|
lock (_lock)
|
|
{
|
|
_hasNewFriendRequest = false;
|
|
_hasFriendListUpdate = false;
|
|
|
|
_notifications.Clear();
|
|
}
|
|
|
|
return Result.Success;
|
|
}
|
|
|
|
[CmifCommand(2)]
|
|
public Result Pop(out SizedNotificationInfo sizedNotificationInfo)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
if (_notifications.Count >= 1)
|
|
{
|
|
sizedNotificationInfo = _notifications.First.Value;
|
|
_notifications.RemoveFirst();
|
|
|
|
if (sizedNotificationInfo.Type == NotificationEventType.FriendListUpdate)
|
|
{
|
|
_hasFriendListUpdate = false;
|
|
}
|
|
else if (sizedNotificationInfo.Type == NotificationEventType.NewFriendRequest)
|
|
{
|
|
_hasNewFriendRequest = false;
|
|
}
|
|
|
|
return Result.Success;
|
|
}
|
|
}
|
|
|
|
sizedNotificationInfo = default;
|
|
|
|
return FriendResult.NotificationQueueEmpty;
|
|
}
|
|
|
|
public void SignalFriendListUpdate(Uid targetId)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
if (_userId == targetId)
|
|
{
|
|
if (!_hasFriendListUpdate)
|
|
{
|
|
SizedNotificationInfo friendListNotification = new();
|
|
|
|
if (_notifications.Count != 0)
|
|
{
|
|
friendListNotification = _notifications.First.Value;
|
|
_notifications.RemoveFirst();
|
|
}
|
|
|
|
friendListNotification.Type = NotificationEventType.FriendListUpdate;
|
|
_hasFriendListUpdate = true;
|
|
|
|
if (_hasNewFriendRequest)
|
|
{
|
|
SizedNotificationInfo newFriendRequestNotification = new();
|
|
|
|
if (_notifications.Count != 0)
|
|
{
|
|
newFriendRequestNotification = _notifications.First.Value;
|
|
_notifications.RemoveFirst();
|
|
}
|
|
|
|
newFriendRequestNotification.Type = NotificationEventType.NewFriendRequest;
|
|
_notifications.AddFirst(newFriendRequestNotification);
|
|
}
|
|
|
|
// We defer this to make sure we are on top of the queue.
|
|
_notifications.AddFirst(friendListNotification);
|
|
}
|
|
|
|
Os.SignalSystemEvent(ref _notificationEvent);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SignalNewFriendRequest(Uid targetId)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
if (_permissionLevel.HasFlag(FriendsServicePermissionLevel.ViewerMask) && _userId == targetId)
|
|
{
|
|
if (!_hasNewFriendRequest)
|
|
{
|
|
if (_notifications.Count == 100)
|
|
{
|
|
SignalFriendListUpdate(targetId);
|
|
}
|
|
|
|
SizedNotificationInfo newFriendRequestNotification = new()
|
|
{
|
|
Type = NotificationEventType.NewFriendRequest,
|
|
};
|
|
|
|
_notifications.AddLast(newFriendRequestNotification);
|
|
_hasNewFriendRequest = true;
|
|
}
|
|
|
|
Os.SignalSystemEvent(ref _notificationEvent);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
_notificationEventHandler.UnregisterNotificationService(this);
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(disposing: true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
}
|
|
}
|