EPG-Erinnerungen: Rechtsklick auf Sendung, Glocke-Indikator, MessageBox-Benachrichtigung
This commit is contained in:
parent
faa852016d
commit
5bf1f06bfe
4 changed files with 175 additions and 0 deletions
|
|
@ -19,6 +19,7 @@ public partial class MainWindow : Window
|
|||
private Media? _currentMedia;
|
||||
private AppSettings _settings = AppSettings.Load();
|
||||
private readonly EpgService _epgService = new();
|
||||
private readonly ReminderService _reminderService = new();
|
||||
private readonly LogoService _logoService = new();
|
||||
|
||||
private readonly ObservableCollection<Channel> _allChannels = new();
|
||||
|
|
@ -1050,6 +1051,64 @@ public partial class MainWindow : Window
|
|||
PlayChannel(target);
|
||||
};
|
||||
|
||||
// Rechtsklick: Kontextmenu mit Erinnern-Option
|
||||
box.MouseRightButtonDown += (_, args) =>
|
||||
{
|
||||
args.Handled = true;
|
||||
var hasReminder = _reminderService.HasReminder(ch.Name, ev.StartTime);
|
||||
var menu = new ContextMenu();
|
||||
|
||||
var remind = new MenuItem
|
||||
{
|
||||
Header = hasReminder ? "\u23f0 Erinnerung entfernen" : "\u23f0 5 min vorher erinnern",
|
||||
FontSize = 13
|
||||
};
|
||||
remind.Click += (_, _) =>
|
||||
{
|
||||
if (hasReminder)
|
||||
{
|
||||
var existing = _reminderService.Reminders
|
||||
.FirstOrDefault(r => r.ChannelName == ch.Name && r.StartTime == ev.StartTime);
|
||||
if (existing != null) _reminderService.Remove(existing.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
_reminderService.Add(new Reminder
|
||||
{
|
||||
ChannelName = ch.Name,
|
||||
Title = ev.Title,
|
||||
Description = ev.Description ?? "",
|
||||
StartTime = ev.StartTime,
|
||||
EndTime = ev.EndTime,
|
||||
MinutesBefore = 5
|
||||
});
|
||||
}
|
||||
// Grid neu bauen damit Indikator aktualisiert wird
|
||||
_ = BuildEpgGridAsync();
|
||||
};
|
||||
menu.Items.Add(remind);
|
||||
box.ContextMenu = menu;
|
||||
menu.IsOpen = true;
|
||||
};
|
||||
|
||||
// Erinnerungs-Indikator anzeigen wenn Erinnerung gesetzt
|
||||
if (_reminderService.HasReminder(ch.Name, ev.StartTime))
|
||||
{
|
||||
var bell = new TextBlock
|
||||
{
|
||||
Text = "\u23f0",
|
||||
FontSize = 11,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
Margin = new Thickness(0, 3, 4, 0),
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
var overlay = new Grid();
|
||||
overlay.Children.Add(content);
|
||||
overlay.Children.Add(bell);
|
||||
box.Child = overlay;
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
|
|
|
|||
16
Models/Reminder.cs
Normal file
16
Models/Reminder.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
namespace FritzTV.Models;
|
||||
|
||||
public class Reminder
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
public required string ChannelName { get; set; }
|
||||
public required string Title { get; set; }
|
||||
public string Description { get; set; } = "";
|
||||
public DateTime StartTime { get; set; }
|
||||
public DateTime EndTime { get; set; }
|
||||
public int MinutesBefore { get; set; } = 5;
|
||||
public bool Fired { get; set; } = false;
|
||||
|
||||
/// <summary>Zeitpunkt zu dem die Benachrichtigung ausgelöst wird</summary>
|
||||
public DateTime NotifyAt => StartTime.AddMinutes(-MinutesBefore);
|
||||
}
|
||||
|
|
@ -36,4 +36,5 @@ public static class AppPaths
|
|||
public static string Epg => Path.Combine(Root, "epg");
|
||||
public static string CrashLog => Path.Combine(Root, "crash.log");
|
||||
public static string WebView2Profile => Path.Combine(Root, "webview2");
|
||||
public static string Reminders => Path.Combine(Root, "reminders.json");
|
||||
}
|
||||
|
|
|
|||
99
Services/ReminderService.cs
Normal file
99
Services/ReminderService.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Windows.Threading;
|
||||
using FritzTV.Models;
|
||||
|
||||
namespace FritzTV.Services;
|
||||
|
||||
public class ReminderService
|
||||
{
|
||||
private static readonly string RemindersPath = AppPaths.Reminders;
|
||||
private readonly DispatcherTimer _checkTimer;
|
||||
private List<Reminder> _reminders = new();
|
||||
|
||||
/// <summary>Feuert wenn eine Erinnerung faellig ist. Callback laeuft auf UI-Thread.</summary>
|
||||
public event Action<Reminder>? ReminderDue;
|
||||
|
||||
public IReadOnlyList<Reminder> Reminders => _reminders.AsReadOnly();
|
||||
|
||||
public ReminderService()
|
||||
{
|
||||
Load();
|
||||
_checkTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(30) };
|
||||
_checkTimer.Tick += (_, _) => CheckReminders();
|
||||
_checkTimer.Start();
|
||||
}
|
||||
|
||||
public void Add(Reminder reminder)
|
||||
{
|
||||
_reminders.Add(reminder);
|
||||
Save();
|
||||
}
|
||||
|
||||
public void Remove(Guid id)
|
||||
{
|
||||
_reminders.RemoveAll(r => r.Id == id);
|
||||
Save();
|
||||
}
|
||||
|
||||
public bool HasReminder(string channelName, DateTime startTime)
|
||||
=> _reminders.Any(r => r.ChannelName == channelName && r.StartTime == startTime);
|
||||
|
||||
private void CheckReminders()
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
var due = _reminders
|
||||
.Where(r => !r.Fired && r.NotifyAt <= now && r.StartTime > now.AddMinutes(-30))
|
||||
.ToList();
|
||||
|
||||
foreach (var r in due)
|
||||
{
|
||||
r.Fired = true;
|
||||
FireNotification(r);
|
||||
ReminderDue?.Invoke(r);
|
||||
}
|
||||
|
||||
_reminders.RemoveAll(r => r.Fired && r.StartTime < now.AddHours(-1));
|
||||
if (due.Any()) Save();
|
||||
}
|
||||
|
||||
private static void FireNotification(Reminder r)
|
||||
{
|
||||
try
|
||||
{
|
||||
var minLeft = (int)(r.StartTime - DateTime.Now).TotalMinutes;
|
||||
var when = minLeft <= 0 ? "Jetzt" : $"In {minLeft} Minute{(minLeft == 1 ? "" : "n")}";
|
||||
var msg = $"{when}: {r.Title}\n{r.ChannelName} {r.StartTime:HH:mm}\u2013{r.EndTime:HH:mm}";
|
||||
|
||||
System.Windows.MessageBox.Show(msg, "\u23f0 HomeStream-Erinnerung",
|
||||
System.Windows.MessageBoxButton.OK,
|
||||
System.Windows.MessageBoxImage.Information);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void Load()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(RemindersPath))
|
||||
{
|
||||
var json = File.ReadAllText(RemindersPath);
|
||||
_reminders = JsonSerializer.Deserialize<List<Reminder>>(json) ?? new();
|
||||
_reminders.RemoveAll(r => r.StartTime < DateTime.Now.AddHours(-1));
|
||||
}
|
||||
}
|
||||
catch { _reminders = new(); }
|
||||
}
|
||||
|
||||
private void Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(RemindersPath)!);
|
||||
var json = JsonSerializer.Serialize(_reminders, new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText(RemindersPath, json);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue