mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-21 09:02:26 +08:00
通知功能完善
This commit is contained in:
@@ -162,7 +162,8 @@
|
||||
FallbackSource="avares://System.Application.SteamTools.Client.Avalonia/Application/UI/Assets/AppResources/avatar.jpg">
|
||||
</gif:Image2>
|
||||
</Border>
|
||||
<ui:InfoBadge Classes="message"
|
||||
<ui:InfoBadge Classes="Critical message"
|
||||
IsVisible="{ReflectionBinding Source={x:Static service:NotificationService.Current},Path=UnreadNotificationsCount,Converter={StaticResource IsNullConverter},ConverterParameter=invert,Mode=OneWay}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"/>
|
||||
</Panel>
|
||||
|
||||
@@ -126,7 +126,9 @@
|
||||
CommandParameter="Notice">
|
||||
<ui:Button.Content>
|
||||
<DockPanel>
|
||||
<ui:InfoBadge Value="3"
|
||||
<ui:InfoBadge Value="{ReflectionBinding Source={x:Static service:NotificationService.Current},Path=UnreadNotificationsCount,Mode=OneWay}"
|
||||
IsVisible="{ReflectionBinding Source={x:Static service:NotificationService.Current},Path=UnreadNotificationsCount,Converter={StaticResource IsNullConverter},ConverterParameter=invert,Mode=OneWay}"
|
||||
Classes="Critical"
|
||||
DockPanel.Dock="Right"
|
||||
HorizontalAlignment="Right" />
|
||||
<TextBlock Text="{ReflectionBinding Path=Res.NotificationChannelType_Name_Announcement,Mode=OneWay,Source={x:Static resx:R.Current}}"
|
||||
|
||||
+22
-7
@@ -31,7 +31,7 @@
|
||||
|
||||
<ui:CommandBarElementContainer Margin="5 0">
|
||||
<WrapPanel VerticalAlignment="Center">
|
||||
<TextBlock Text="消息类型:"
|
||||
<TextBlock Text="{ReflectionBinding Path=Res.Notice_Type,StringFormat={}{0}:,Mode=OneWay,Source={x:Static resx:R.Current}}"
|
||||
VerticalAlignment="Center"/>
|
||||
<ComboBox VerticalAlignment="Center"
|
||||
Items="{ReflectionBinding Source={x:Static service:NotificationService.Current},Path=NoticeTypes,Mode=OneWay}"
|
||||
@@ -58,7 +58,8 @@
|
||||
</ui:CommandBarButton.Icon>
|
||||
</ui:CommandBarButton>-->
|
||||
|
||||
<ui:CommandBarButton Label="全部标记为已读"
|
||||
<ui:CommandBarButton Label="{ReflectionBinding Path=Res.Notice_AllMarkHasRead,Mode=OneWay,Source={x:Static resx:R.Current}}"
|
||||
IsEnabled="{ReflectionBinding Source={x:Static service:NotificationService.Current},Path=UnreadNotificationsCount,Converter={StaticResource IsNullConverter},ConverterParameter=invert,Mode=OneWay}"
|
||||
Command="{Binding MarkAllRead,Mode=OneTime}">
|
||||
<ui:CommandBarButton.Icon>
|
||||
<ui:SymbolIcon Symbol="Checkmark"/>
|
||||
@@ -94,20 +95,34 @@
|
||||
Margin="10"
|
||||
IsVisible="{Binding Path=!IsEmpty,Mode=OneWay}">
|
||||
<Panel>
|
||||
<Grid ColumnDefinitions="3*,Auto,7*">
|
||||
<Grid ColumnDefinitions="4*,Auto,7*">
|
||||
<Border>
|
||||
<ListBox Items="{Binding Notices}"
|
||||
SelectedItem="{Binding NoticeItem,Mode=TwoWay}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:NoticeDTO">
|
||||
<StackPanel Margin="10" Spacing="8">
|
||||
<TextBlock Text="{Binding Title,Mode=OneWay}"
|
||||
Classes="h6"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
<DockPanel>
|
||||
<ui:InfoBadge IsVisible="{Binding !HasRead}"
|
||||
Classes="Critical"
|
||||
Height="6"
|
||||
Width="6"
|
||||
DockPanel.Dock="Right"
|
||||
HorizontalAlignment="Right" />
|
||||
<TextBlock Text="{Binding Title,Mode=OneWay}"
|
||||
Classes="h6"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
</DockPanel>
|
||||
<TextBlock
|
||||
Text="{Binding Introduction}"
|
||||
Foreground="{DynamicResource InactiveForegroundBrushKey}"
|
||||
Classes="h8"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
<TextBlock
|
||||
Text="{Binding CreationTime,StringFormat={}{0:yyyy-MM-dd}}"
|
||||
Foreground="{DynamicResource InactiveForegroundBrushKey}"
|
||||
HorizontalAlignment="Right"
|
||||
Classes="h8"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
@@ -140,7 +155,7 @@
|
||||
DecodeWidth="{ReflectionBinding $parent.Width}"
|
||||
Margin="10 0"
|
||||
Source="{Binding NoticeItem.PictureStream^}"
|
||||
IsVisible="{Binding NoticeItem.PictureStream^,Converter={StaticResource IsNullConverter},ConverterParameter=invert}}"
|
||||
IsVisible="{Binding NoticeItem.PictureStream,Converter={StaticResource IsNullConverter},ConverterParameter=invert}}"
|
||||
Stretch="Uniform" />
|
||||
|
||||
<TextBlock TextWrapping="Wrap"
|
||||
|
||||
+3
-5
@@ -87,7 +87,7 @@ namespace Avalonia.Controls
|
||||
{
|
||||
TitleBar.ExtendViewIntoTitleBar = true;
|
||||
|
||||
//titleBar.LayoutMetricsChanged += OnApplicationTitleBarLayoutMetricsChanged;
|
||||
//TitleBar.LayoutMetricsChanged += OnApplicationTitleBarLayoutMetricsChanged;
|
||||
|
||||
if (this.FindControl<Control>("TitleBarHost") is IControl t)
|
||||
{
|
||||
@@ -109,8 +109,7 @@ namespace Avalonia.Controls
|
||||
//ExtendClientAreaToDecorationsHint = true;
|
||||
//ExtendClientAreaTitleBarHeightHint = -1;
|
||||
|
||||
ExtendClientAreaChromeHints =
|
||||
ExtendClientAreaChromeHints.Default;
|
||||
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.Default;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -131,8 +130,7 @@ namespace Avalonia.Controls
|
||||
}
|
||||
else
|
||||
{
|
||||
ExtendClientAreaChromeHints =
|
||||
ExtendClientAreaChromeHints.SystemChrome;
|
||||
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.Default;
|
||||
}
|
||||
#pragma warning restore CA1416 // 验证平台兼容性
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using SQLite;
|
||||
using System.Application.Columns;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NotNull = System.Diagnostics.CodeAnalysis.NotNullAttribute;
|
||||
using SQLiteNotNull = SQLite.NotNullAttribute;
|
||||
using SQLiteTable = SQLite.TableAttribute;
|
||||
|
||||
namespace System.Application.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// 通知记录
|
||||
/// </summary>
|
||||
[SQLiteTable("A765AD32")]
|
||||
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
|
||||
public class Notification : IEntity<Guid>
|
||||
{
|
||||
string DebuggerDisplay => Id.ToString();
|
||||
|
||||
[Column("2ABD43F2")]
|
||||
[PrimaryKey]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Column("4557AC21")]
|
||||
public DateTimeOffset ExpirationTime { get; set; } = DateTimeOffset.Now;
|
||||
|
||||
[Column("8E7393C5")]
|
||||
public bool HasRead { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,5 @@ namespace System.Application
|
||||
/// 当前登录用户
|
||||
/// </summary>
|
||||
public const string KEY_CURRENT_LOGIN_USER = "KEY_CURRENT_LOGIN_USER";
|
||||
|
||||
/// <summary>
|
||||
/// 上次启动时收到的通知纪录 ID
|
||||
/// </summary>
|
||||
public const string ON_LAST_STARTUP_NOTIFICATION_RECORD_ID = "ON_LAST_STARTUP_NOTIFICATION_RECORD_ID";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Application.Entities;
|
||||
using System.Application.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Application.Repositories
|
||||
{
|
||||
public interface INotificationRepository : IRepository<Notification, Guid>
|
||||
{
|
||||
|
||||
Task<IList<Notification>> GetAllAsync(Expression<Func<Notification, bool>>? expression = null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using AutoMapper;
|
||||
using System.Application.Entities;
|
||||
using System.Application.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Application.Repositories.Implementation
|
||||
{
|
||||
internal sealed class NotificationRepository : Repository<Notification, Guid>, INotificationRepository
|
||||
{
|
||||
public async Task<IList<Notification>> GetAllAsync(Expression<Func<Notification, bool>>? expression = null)
|
||||
{
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
return await AttemptAndRetry(async () =>
|
||||
{
|
||||
var r = dbConnection.Table<Notification>();
|
||||
if (expression != null)
|
||||
r = r.Where(expression);
|
||||
return await r.ToArrayAsync();
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddSingleton<IUserRepository, UserRepository>();
|
||||
services.AddSingleton<IGameAccountPlatformAuthenticatorRepository, GameAccountPlatformAuthenticatorRepository>();
|
||||
services.AddSingleton<IScriptRepository, ScriptRepository>();
|
||||
services.AddSingleton<INotificationRepository, NotificationRepository>();
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,14 +101,6 @@ namespace System.Application.Services
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最后一次收到的通知启用时间 只提示大于此时间的通知
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
static Task<DateTimeOffset?> GetLastNotificationTime() => ISecureStorage.Instance.GetAsync<DateTimeOffset?>(ON_LAST_STARTUP_NOTIFICATION_RECORD_ID);
|
||||
|
||||
static Task SetLastNotificationTime(DateTimeOffset time) => ISecureStorage.Instance.SetAsync<DateTimeOffset?>(ON_LAST_STARTUP_NOTIFICATION_RECORD_ID, time);
|
||||
|
||||
/// <summary>
|
||||
/// NotifyIcon / TrayIcon 右下角托盘菜单助手类
|
||||
/// </summary>
|
||||
|
||||
@@ -4,6 +4,7 @@ using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Application.Models;
|
||||
using System.Application.Properties;
|
||||
using System.Application.Repositories;
|
||||
using System.Application.Settings;
|
||||
using System.Application.UI.Resx;
|
||||
using System.Collections.Generic;
|
||||
@@ -30,6 +31,7 @@ namespace System.Application.Services
|
||||
public static NotificationService Current => mCurrent ?? new();
|
||||
|
||||
readonly IHttpService httpService = DI.Get<IHttpService>();
|
||||
readonly INotificationRepository notificationRepository = DI.Get<INotificationRepository>();
|
||||
|
||||
public SourceCache<NoticeDTO, Guid> NoticesSource { get; }
|
||||
|
||||
@@ -39,6 +41,8 @@ namespace System.Application.Services
|
||||
[Reactive]
|
||||
public ObservableCollection<NoticeTypeDTO> NoticeTypes { get; set; }
|
||||
|
||||
public NoticeTypeDTO DefaultType { get; } = new NoticeTypeDTO() { Name = AppResources.AllTyoe };
|
||||
|
||||
public NotificationService()
|
||||
{
|
||||
mCurrent = this;
|
||||
@@ -48,38 +52,39 @@ namespace System.Application.Services
|
||||
|
||||
public async Task GetNews(int trycount = 0)
|
||||
{
|
||||
var lastTime = await INotificationService.GetLastNotificationTime();
|
||||
var data = await notificationRepository.GetAllAsync(w => w.ExpirationTime > DateTimeOffset.Now);
|
||||
UnreadNotificationsCount = data.Count(x => !x.HasRead);
|
||||
var client = ICloudServiceClient.Instance.Notice;
|
||||
var result = await client.NewMsg(null, null);
|
||||
if (result.IsSuccess && result.Content != null)
|
||||
{
|
||||
var noticeList = result.Content.Where(x => lastTime.HasValue ? x.EnableTime > lastTime : true);
|
||||
if (noticeList.Count() > 1)
|
||||
var noticeList = result.Content.Where(x => !data.Any(d => d.Id == x.Id));
|
||||
if (noticeList.Any_Nullable())
|
||||
{
|
||||
await INotificationService.SetLastNotificationTime(noticeList.Max(x => x.EnableTime));
|
||||
INotificationService.Instance.Notify(new NotificationBuilder()
|
||||
if (noticeList.Count() > 1)
|
||||
{
|
||||
Title = AppResources.NotificationChannelType_Description_Announcement,
|
||||
Content = AppResources.Notice_Tray.Format(result.Content.Length),
|
||||
AutoCancel = NotificationBuilder.DefaultAutoCancel,
|
||||
Type = NotificationType.Announcement,
|
||||
Click = new NotificationBuilder.ClickAction(() =>
|
||||
INotificationService.Instance.Notify(new NotificationBuilder()
|
||||
{
|
||||
IWindowManager.Instance.Show(CustomWindow.Notice);
|
||||
})
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var notice = noticeList.FirstOrDefault();
|
||||
if (notice != null && notice.EnableTime > lastTime)
|
||||
Title = AppResources.Notice_Tray_Title,
|
||||
Content = AppResources.Notice_Tray_Content.Format(result.Content.Length),
|
||||
AutoCancel = NotificationBuilder.DefaultAutoCancel,
|
||||
Type = NotificationType.Announcement,
|
||||
Click = new NotificationBuilder.ClickAction(() =>
|
||||
{
|
||||
IWindowManager.Instance.Show(CustomWindow.Notice);
|
||||
})
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
await INotificationService.SetLastNotificationTime(notice.EnableTime);
|
||||
var notice = noticeList.First();
|
||||
INotificationService.Instance.Notify(notice);
|
||||
}
|
||||
|
||||
await InsertNotificationRecord(noticeList);
|
||||
}
|
||||
|
||||
DeleteExpiredRecordAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +95,7 @@ namespace System.Application.Services
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
NoticeTypes.Clear();
|
||||
NoticeTypes.Add(DefaultType);
|
||||
NoticeTypes.AddRange(result.Content!.OrderBy(x => x.Order));
|
||||
}
|
||||
}
|
||||
@@ -97,7 +103,9 @@ namespace System.Application.Services
|
||||
public async Task LoadNotification(NoticeTypeDTO? selectGroup)
|
||||
{
|
||||
var client = ICloudServiceClient.Instance.Notice;
|
||||
var result = await client.Table(selectGroup?.Id, 1, 30);
|
||||
var typeid = selectGroup == DefaultType ? null : selectGroup?.Id;
|
||||
var isAll = typeid is null;
|
||||
var result = await client.Table(typeid, 1, 30);
|
||||
if (result.IsSuccess && result.Content != null)
|
||||
{
|
||||
//foreach (var item in result.Content!.DataSource)
|
||||
@@ -107,7 +115,59 @@ namespace System.Application.Services
|
||||
//}
|
||||
NoticesSource.Clear();
|
||||
NoticesSource.AddOrUpdate(result.Content.DataSource);
|
||||
if (isAll)
|
||||
{
|
||||
await LoadHasReadRecord();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task LoadHasReadRecord()
|
||||
{
|
||||
var data = await notificationRepository.GetAllAsync(w => w.ExpirationTime > DateTimeOffset.Now);
|
||||
if (data.Any_Nullable())
|
||||
{
|
||||
//var oldData = data.Where(w => w.ExpirationTime > DateTimeOffset.Now);
|
||||
//if (oldData.Any())
|
||||
// await notificationRepository.DeleteRangeAsync(oldData);
|
||||
UnreadNotificationsCount = data.Count(x => !x.HasRead);
|
||||
|
||||
foreach (var d in data)
|
||||
{
|
||||
var notice = NoticesSource.Lookup(d.Id);
|
||||
if (notice.HasValue)
|
||||
notice.Value.HasRead = d.HasRead;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InsertNotificationRecord(IEnumerable<NoticeDTO> notices)
|
||||
{
|
||||
var data = await notificationRepository.GetAllAsync(w => w.ExpirationTime > DateTimeOffset.Now);
|
||||
var newData = notices
|
||||
.Where(w => !data.Any(d => d.Id == w.Id))
|
||||
.Select(s => new Entities.Notification()
|
||||
{
|
||||
Id = s.Id,
|
||||
HasRead = false,
|
||||
ExpirationTime = s.OverdueTime,
|
||||
});
|
||||
var num = await notificationRepository.InsertRangeAsync(newData);
|
||||
if (num > 0)
|
||||
{
|
||||
UnreadNotificationsCount += num;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task MarkNotificationHasRead(params Entities.Notification[] notice)
|
||||
{
|
||||
await notificationRepository.UpdateRangeAsync(notice);
|
||||
}
|
||||
|
||||
public async void DeleteExpiredRecordAsync()
|
||||
{
|
||||
var data = await notificationRepository.GetAllAsync(w => w.ExpirationTime < DateTimeOffset.Now);
|
||||
await notificationRepository.DeleteRangeAsync(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-3
@@ -515,6 +515,15 @@ namespace System.Application.UI.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 全部类型 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string AllTyoe {
|
||||
get {
|
||||
return ResourceManager.GetString("AllTyoe", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 和 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -4069,11 +4078,38 @@ namespace System.Application.UI.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 当前有 {0} 条{1}通知,详情请在程序内通知公告处查看。 的本地化字符串。
|
||||
/// 查找类似 全部标记为已读 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Notice_Tray {
|
||||
public static string Notice_AllMarkHasRead {
|
||||
get {
|
||||
return ResourceManager.GetString("Notice_Tray", resourceCulture);
|
||||
return ResourceManager.GetString("Notice_AllMarkHasRead", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 收到{0}条新消息,详情请在程序内我的消息处查看。 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Notice_Tray_Content {
|
||||
get {
|
||||
return ResourceManager.GetString("Notice_Tray_Content", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 消息提示 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Notice_Tray_Title {
|
||||
get {
|
||||
return ResourceManager.GetString("Notice_Tray_Title", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 消息类型 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Notice_Type {
|
||||
get {
|
||||
return ResourceManager.GetString("Notice_Type", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2272,8 +2272,11 @@ AAAAA-BBBBB-CCCC3</value>
|
||||
<data name="SaveEditedAppInfo_SelectImageFailed" xml:space="preserve">
|
||||
<value>请正确选择一张要应用的图片</value>
|
||||
</data>
|
||||
<data name="Notice_Tray" xml:space="preserve">
|
||||
<value>当前有 {0} 条{1}通知,详情请在程序内通知公告处查看。</value>
|
||||
<data name="Notice_Tray_Title" xml:space="preserve">
|
||||
<value>消息提示</value>
|
||||
</data>
|
||||
<data name="Notice_Tray_Content" xml:space="preserve">
|
||||
<value>收到{0}条新消息,详情请在程序内我的消息处查看。</value>
|
||||
</data>
|
||||
<data name="CommunityFix_CertificateStatus" xml:space="preserve">
|
||||
<value>证书状态</value>
|
||||
@@ -2365,4 +2368,13 @@ AAAAA-BBBBB-CCCC3</value>
|
||||
<data name="SeeDetails" xml:space="preserve">
|
||||
<value>查看详情</value>
|
||||
</data>
|
||||
<data name="AllTyoe" xml:space="preserve">
|
||||
<value>全部类型</value>
|
||||
</data>
|
||||
<data name="Notice_AllMarkHasRead" xml:space="preserve">
|
||||
<value>全部标记为已读</value>
|
||||
</data>
|
||||
<data name="Notice_Type" xml:space="preserve">
|
||||
<value>消息类型</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -39,9 +39,20 @@ namespace System.Application.UI.ViewModels
|
||||
{
|
||||
Title = GetTitleByDisplayName(DisplayName);
|
||||
//OpenNotice = ReactiveCommand.CreateFromTask<string>(x => Browser2.OpenAsync(x));
|
||||
MarkAllRead = ReactiveCommand.Create(() =>
|
||||
MarkAllRead = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var data = NotificationService.Current.NoticesSource.Items.Select(s => new Entities.Notification
|
||||
{
|
||||
Id = s.Id,
|
||||
ExpirationTime = s.OverdueTime,
|
||||
HasRead = true
|
||||
}).ToArray();
|
||||
await NotificationService.Current.MarkNotificationHasRead(data);
|
||||
|
||||
foreach (var item in NotificationService.Current.NoticesSource.Items)
|
||||
{
|
||||
item.HasRead = true;
|
||||
}
|
||||
});
|
||||
|
||||
NotificationService.Current.NoticesSource
|
||||
@@ -62,6 +73,21 @@ namespace System.Application.UI.ViewModels
|
||||
await NotificationService.Current.LoadNotification(x);
|
||||
IsLoading = false;
|
||||
});
|
||||
|
||||
this.WhenValueChanged(x => x.NoticeItem)
|
||||
.Subscribe(x =>
|
||||
{
|
||||
if (x != null && !x.HasRead)
|
||||
{
|
||||
_ = NotificationService.Current.MarkNotificationHasRead(new Entities.Notification
|
||||
{
|
||||
Id = x.Id,
|
||||
ExpirationTime = x.OverdueTime,
|
||||
HasRead = true
|
||||
});
|
||||
x.HasRead = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override async void Activation()
|
||||
@@ -69,6 +95,7 @@ namespace System.Application.UI.ViewModels
|
||||
//if (IsFirstActivation)
|
||||
IsLoading = true;
|
||||
await NotificationService.Current.LoadNoticeTypes();
|
||||
SelectType = NotificationService.Current.NoticeTypes.FirstOrDefault();
|
||||
await NotificationService.Current.LoadNotification(SelectType);
|
||||
IsLoading = false;
|
||||
base.Activation();
|
||||
|
||||
@@ -102,16 +102,6 @@ namespace System.Application.Models
|
||||
[S_JsonProperty("9")]
|
||||
public DateTimeOffset OverdueTime { get; set; }
|
||||
|
||||
#if MVVM_VM
|
||||
/// <summary>
|
||||
/// 是否过期
|
||||
/// </summary>
|
||||
[MPIgnore]
|
||||
[N_JsonIgnore]
|
||||
[S_JsonIgnore]
|
||||
public bool Overdue => DateTimeOffset.Now > OverdueTime;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 通知渠道
|
||||
/// </summary>
|
||||
@@ -129,5 +119,24 @@ namespace System.Application.Models
|
||||
[N_JsonProperty("12")]
|
||||
[S_JsonProperty("12")]
|
||||
public string? Context { get; set; } = string.Empty;
|
||||
|
||||
#if MVVM_VM
|
||||
/// <summary>
|
||||
/// 是否过期
|
||||
/// </summary>
|
||||
[MPIgnore]
|
||||
[N_JsonIgnore]
|
||||
[S_JsonIgnore]
|
||||
public bool Overdue => DateTimeOffset.Now > OverdueTime;
|
||||
|
||||
/// <summary>
|
||||
/// 是否已读
|
||||
/// </summary>
|
||||
[MPIgnore]
|
||||
[N_JsonIgnore]
|
||||
[S_JsonIgnore]
|
||||
[Reactive]
|
||||
public bool HasRead { get; set; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user