Files
Windows-Gotify-Client/Models/GotifyMessage.cs
T
KennethCheng c2f44767a6 feat: 落地 V1 全部源码 — WebSocket 通知 + 应用内历史查看
17 个源文件 + .gitignore + 默认 config.json 模板,严格按方案文档第 6 节实现。

用户核心场景:

- Windows 接收 Gotify 通知(WS /stream → AppNotificationBuilder)

- 应用内查看历史消息(打开 MainWindow 触发 GetRecentMessagesAsync,实时通过 MessageReceived 事件追加)

- 列表条目双击打开 extras.client::notification.click.url

关键变更点:

- GotifyMessage.Extras 类型由 Dictionary<string,object> 改为 Dictionary<string,JsonElement>,避免 System.Text.Json 反序列化时丢失嵌套结构

- 新增 HistoryConfig.ViewerLimit(默认 50,UI 硬上限 200)

- GotifyApiService.GetRecentMessagesAsync:since=0 拉最近 N 条,OrderByDescending(Id) 保证顺序

- GotifyWebSocketService 新增 MessageReceived 事件,MainWindow 用 Dispatcher.Invoke 切回 UI 线程追加

- NotificationService.AddArgument('url=...') 透传 click URL 给 OnNotificationInvoked

- MainWindow.xaml 增加 ListView + 刷新按钮,使用 ObservableCollection<GotifyMessage>

- 默认 config.json 用 https://gotify.example.com 占位 URL,ClientToken 留空,首启动自动写入 %LOCALAPPDATA%

依赖:Microsoft.WindowsAppSDK 2.4.0(方案文档固定版本)。

构建:本机 .NET 8 SDK 未安装,build 待用户在装好 SDK 后执行: dotnet restore && dotnet build -c Release
2026-09-06 18:44:55 +08:00

87 lines
2.3 KiB
C#

using System.Text.Json;
using System.Text.Json.Serialization;
namespace WindowsGotify.Models;
public sealed class GotifyMessage
{
[JsonPropertyName("id")]
public long Id { get; set; }
[JsonPropertyName("appid")]
public long AppId { get; set; }
[JsonPropertyName("message")]
public string Message { get; set; } = "";
[JsonPropertyName("title")]
public string? Title { get; set; }
[JsonPropertyName("priority")]
public int Priority { get; set; }
[JsonPropertyName("date")]
public DateTimeOffset Date { get; set; }
[JsonPropertyName("extras")]
public Dictionary<string, JsonElement>? Extras { get; set; }
[JsonIgnore]
public string TitleDisplay =>
string.IsNullOrWhiteSpace(Title) ? $"(App {AppId})" : Title!;
[JsonIgnore]
public string DateDisplay =>
Date.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss");
[JsonIgnore]
public string PriorityDisplay => $"P{Priority}";
/// <summary>
/// 提取 Gotify extras 中的 client::notification.click.url(用于点击跳转)。
/// </summary>
[JsonIgnore]
public string? ClickUrl
{
get
{
if (Extras is null) return null;
try
{
if (!Extras.TryGetValue("client::notification", out var notif)) return null;
if (notif.ValueKind != JsonValueKind.Object) return null;
if (!notif.TryGetProperty("click", out var click)) return null;
if (click.ValueKind != JsonValueKind.Object) return null;
if (!click.TryGetProperty("url", out var url)) return null;
if (url.ValueKind != JsonValueKind.String) return null;
return url.GetString();
}
catch
{
return null;
}
}
}
}
public sealed class GotifyMessagePage
{
[JsonPropertyName("messages")]
public List<GotifyMessage> Messages { get; set; } = new();
[JsonPropertyName("paging")]
public PagingInfo? Paging { get; set; }
}
public sealed class PagingInfo
{
[JsonPropertyName("size")]
public int Size { get; set; }
[JsonPropertyName("limit")]
public int Limit { get; set; }
[JsonPropertyName("next")]
public string? Next { get; set; }
}