NotificationInbox
TsgcHTMLComponent_NotificationInbox:一个带有未读徽章的铃铛和一个显示某个用户通知的下拉列表,适用于 Delphi、C++ Builder 和 .NET。记录由您的应用保存,组件负责渲染它们。
TsgcHTMLComponent_NotificationInbox:一个带有未读徽章的铃铛和一个显示某个用户通知的下拉列表,适用于 Delphi、C++ Builder 和 .NET。记录由您的应用保存,组件负责渲染它们。
库本身不存储任何内容。您的应用用它保存的记录来响应 OnLoadNotifications,并通过 OnMarkRead 和 OnMarkAllRead 得知用户做了什么,以便持久化。组件只渲染界面,不执行任何授权。它适用于所有版本,可通过 WebSocket 或服务器发送事件工作。
TsgcHTMLComponent_NotificationInbox(单元 sgcHTML_Component_NotificationInbox)
Bootstrap 下拉框标记:一个铃铛、一个未读徽章和一个列表
Delphi, C++ Builder, .NET
给收件箱设置 InboxID,在 OnLoadNotifications 中用您自己的存储填充它,在 OnMarkRead 和 OnMarkAllRead 中持久化用户所做的操作,并把回传的操作路由到 ProcessAction,用户取自会话。
uses
sgcHTML_Session, sgcHTML_Component_NotificationInbox;
var
oInbox: TsgcHTMLComponent_NotificationInbox;
begin
oInbox := TsgcHTMLComponent_NotificationInbox.Create(nil);
try
oInbox.InboxID := 'inbox';
oInbox.Title := 'Notifications';
oInbox.MaxItems := 10;
oInbox.OnLoadNotifications := InboxLoad;
oInbox.OnMarkRead := InboxMarkRead;
oInbox.OnMarkAllRead := InboxMarkAllRead;
// the user comes from the session, never from the form
oInbox.LoadNotifications(sgcHTMLRequestSession.UserID);
Response := oInbox.HTML; // bell, unread badge and dropdown
finally
oInbox.Free;
end;
end;
// the application owns the rows: fill the list, newest first
procedure TMain.InboxLoad(Sender: TObject; const aUserID: string;
aList: TsgcHTMLInboxItems);
begin
with aList.Add do
begin
Id := '1042';
Title := 'New order';
Text := 'Order #1042 was placed.';
Timestamp := '2 min ago';
Read := False;
end;
end;
procedure TMain.InboxMarkRead(Sender: TObject; const aUserID,
aNotificationID: string);
begin
// persist it, after checking that aUserID owns aNotificationID
end;
// in the message handler that receives the actions the inbox posts
if oInbox.ProcessAction(vUser, vAction, vNotificationID) then
oHTMX.PushFragment(vGuid, oInbox.GetListFragmentHTML +
oInbox.GetBadgeFragmentHTML);
// includes: sgcHTML_Session.hpp, sgcHTML_Component_NotificationInbox.hpp
TsgcHTMLComponent_NotificationInbox *oInbox = new TsgcHTMLComponent_NotificationInbox(NULL);
try
{
oInbox->InboxID = "inbox";
oInbox->Title = "Notifications";
oInbox->MaxItems = 10;
oInbox->OnLoadNotifications = InboxLoad;
oInbox->OnMarkRead = InboxMarkRead;
oInbox->OnMarkAllRead = InboxMarkAllRead;
// the user comes from the session, never from the form
oInbox->LoadNotifications(sgcHTMLRequestSession()->UserID);
String html = oInbox->HTML; // bell, unread badge and dropdown
}
__finally
{
delete oInbox;
}
// the application owns the rows: fill the list, newest first
void __fastcall TMain::InboxLoad(TObject *Sender, const String aUserID,
TsgcHTMLInboxItems *aList)
{
TsgcHTMLInboxItem *item = aList->Add();
item->Id = "1042";
item->Title = "New order";
item->Text = "Order #1042 was placed.";
item->Timestamp = "2 min ago";
item->Read = false;
}
void __fastcall TMain::InboxMarkRead(TObject *Sender, const String aUserID,
const String aNotificationID)
{
// persist it, after checking that aUserID owns aNotificationID
}
// in the message handler that receives the actions the inbox posts
if (oInbox->ProcessAction(vUser, vAction, vNotificationID))
oHTMX->PushFragment(vGuid, oInbox->GetListFragmentHTML() +
oInbox->GetBadgeFragmentHTML());
using esegece.sgcWebSockets;
var inbox = new TsgcHTMLComponent_NotificationInbox();
inbox.InboxID = "inbox";
inbox.Title = "Notifications";
inbox.MaxItems = 10;
inbox.OnLoadNotifications += InboxLoad;
inbox.OnMarkRead += InboxMarkRead;
inbox.OnMarkAllRead += InboxMarkAllRead;
// the user comes from the session, never from the form
string user = sgcHTMLSessionHelpers.sgcHTMLRequestSession()?.UserID ?? "";
inbox.LoadNotifications(user);
string html = inbox.HTML; // bell, unread badge and dropdown
// the application owns the rows: fill the list, newest first
void InboxLoad(object sender, string userID, TsgcHTMLInboxItems list)
{
var item = list.Add();
item.Id = "1042";
item.Title = "New order";
item.Text = "Order #1042 was placed.";
item.Timestamp = "2 min ago";
item.Read = false;
}
void InboxMarkRead(object sender, string userID, string notificationID)
{
// persist it, after checking that userID owns notificationID
}
// in the message handler that receives the actions the inbox posts
if (inbox.ProcessAction(user, action, notificationId))
htmx.PushFragment(guid, inbox.GetListFragmentHTML() + inbox.GetBadgeFragmentHTML());
您最常使用的成员。
Items 是一个 TsgcHTMLInboxItems 集合;每个 TsgcHTMLInboxItem 都有 Id、Title、Text、Timestamp、Url、Icon 和 Read。记录中的所有内容都是数据,渲染时会被转义,包括 Icon:请传入字面字符,不要传入 HTML 实体或标记。Url 会经过净化,javascript: 和 data: 链接会被拒绝。
组件只保存它正在渲染的内容。OnLoadNotifications(aUserID, aList) 触发时 aList 已被清空:请用该用户的通知填充它,最新的在前。OnMarkRead(aUserID, aNotificationID) 在条目被标记为已读之后触发,OnMarkAllRead(aUserID) 在所有条目都被标记之后触发。
LoadNotifications(aUserID)、MarkRead(aUserID, aNotificationID) 和 MarkAllRead(aUserID) 负责实际工作。ProcessAction(aUserID, aAction, aNotificationID) 把一条回传的操作路由给合适的那个,当该操作不是收件箱操作时返回 False,因此您可以继续查找它的所有者。
下拉框回传 inboxMarkRead(字段 action、inbox、id)、inboxMarkAllRead 和 inboxRefresh(字段 action、inbox),形式为 data-sgc-ws-send 表单。inbox 字段携带渲染该表单的收件箱的元素 id,设置了 InboxID 时就是它,包含多个收件箱的页面正是靠它把操作路由到正确的组件。
组件只渲染界面,不执行任何授权。每个操作都作为客户端发送的数据传输,因此恶意客户端可以伪造任何操作和任何通知 id。标记中不会写入任何用户 id:请从请求会话(sgcHTMLRequestSession)中获取执行操作的用户,绝不要从表单中获取,并且在持久化任何内容之前,先检查该用户是否拥有所收到的通知 id。
Title 是下拉框的标题,EmptyText 是没有内容可显示时的占位文本,BellIcon 是触发器字符,默认是带有 HTML 实体的受信任标记。MaxItems 限制可见行数(默认 10,0 表示全部显示),ShowMarkAllRead 和 ShowBadge 默认开启,AddNotification(aId, aTitle, aText, aTimestamp, aUrl, aIcon) 添加一行,或更新具有相同 id 的那一行。
每条通知、徽章和列表都带有稳定的元素 id。发生一次变更后,只需用 GetItemFragmentHTML(aId)、GetBadgeFragmentHTML 或 GetListFragmentHTML 渲染受影响的标记,并通过 TsgcHTMX_Engine_Server.PushFragment 或 BroadcastFragment 推送,而不必重新渲染整个页面。UnreadCount 统计 Read 为 False 的条目数。
该单元在定义了 SGC_HTML 时编译,sgcVer.inc 不会为 Android 和 iOS 定义它。它适用于所有版本,可通过 WebSocket 或服务器发送事件工作。sgcHTML 是独立的包,与 sgcWebSockets 分开销售。
收件箱本身不在页面和推送之间做选择:这由 TsgcHTMLComponent_Notification 完成,参见 Notification 和 WebPush。每个用户希望使用哪些通道,在 NotificationPreferences 中设置。