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
This commit is contained in:
2026-09-06 18:44:55 +08:00
parent 4b7f3a383c
commit c2f44767a6
19 changed files with 1401 additions and 2 deletions
+125
View File
@@ -0,0 +1,125 @@
<Window x:Class="WindowsGotify.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Windows Gotify"
Width="780"
Height="620"
MinWidth="640"
MinHeight="480"
WindowStartupLocation="CenterScreen">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 标题 -->
<StackPanel Grid.Row="0">
<TextBlock Text="Windows Gotify"
FontSize="26"
FontWeight="Bold" />
<TextBlock Text="Gotify → Windows 原生通知 · 应用内查看历史"
Margin="0,2,0,14"
Foreground="Gray" />
</StackPanel>
<!-- 设置区 -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Gotify URL" />
<TextBox x:Name="UrlTextBox"
Grid.Row="1"
Grid.Column="0"
Margin="0,4,12,12"
Height="30" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="Client Token" />
<PasswordBox x:Name="TokenBox"
Grid.Row="1"
Grid.Column="1"
Margin="0,4,0,12"
Height="30" />
<TextBlock Grid.Row="2" Grid.ColumnSpan="2"
x:Name="StatusText"
FontSize="14"
Margin="0,0,0,4" />
<TextBlock Grid.Row="3" Grid.ColumnSpan="2"
Text="配置保存在 %LOCALAPPDATA%\WindowsGotify\config.json"
Foreground="Gray"
FontSize="11" />
</Grid>
<!-- 历史区 -->
<Border Grid.Row="3"
BorderBrush="#DDD"
BorderThickness="1"
CornerRadius="4"
Padding="0"
Margin="0,12,0,0">
<DockPanel>
<Grid DockPanel.Dock="Top" Margin="10,8,10,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="历史消息(点击行可在浏览器打开链接,留空则只选中)"
FontWeight="Bold"
VerticalAlignment="Center" />
<TextBlock x:Name="HistoryCountText"
Grid.Column="1"
Foreground="Gray"
VerticalAlignment="Center" />
</Grid>
<ListView x:Name="HistoryList"
BorderThickness="0"
MouseDoubleClick="HistoryList_MouseDoubleClick">
<ListView.View>
<GridView>
<GridViewColumn Header="时间" Width="150" DisplayMemberBinding="{Binding DateDisplay}"/>
<GridViewColumn Header="优先级" Width="60" DisplayMemberBinding="{Binding PriorityDisplay}"/>
<GridViewColumn Header="标题" Width="120" DisplayMemberBinding="{Binding TitleDisplay}"/>
<GridViewColumn Header="内容" Width="380" DisplayMemberBinding="{Binding Message}"/>
</GridView>
</ListView.View>
</ListView>
</DockPanel>
</Border>
<!-- 按钮区 -->
<StackPanel Grid.Row="4"
Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="0,12,0,0">
<Button Content="刷新历史"
Width="100"
Height="34"
Margin="0,0,8,0"
Click="RefreshButton_Click" />
<Button Content="测试通知"
Width="100"
Height="34"
Margin="0,0,8,0"
Click="TestButton_Click" />
<Button Content="保存并重连"
Width="120"
Height="34"
Click="SaveButton_Click" />
</StackPanel>
</Grid>
</Window>