-
-
Notifications
You must be signed in to change notification settings - Fork 492
/
Copy pathDebouncedProperty.cs
129 lines (107 loc) · 3.37 KB
/
DebouncedProperty.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//
// Copyright Fela Ameghino 2015-2025
//
// Distributed under the GNU General Public License v3.0. (See accompanying
// file LICENSE or copy at https://www.gnu.org/licenses/gpl-3.0.txt)
//
using System;
using System.Threading;
using Windows.UI.Xaml;
namespace Telegram.Common
{
public partial class DebouncedProperty<T>
{
private readonly DispatcherTimer _timer;
private readonly Timer _backgroundTimer;
private readonly TimeSpan _interval;
private readonly Action<T> _update;
private readonly Func<T, bool> _canUpdate;
private CancellationToken _cancellationToken;
private T _lastValue;
private T _value;
public DebouncedProperty(double milliseconds, Action<T> update, Func<T, bool> canUpdate = null, bool useBackgroundThread = false)
: this(TimeSpan.FromMilliseconds(milliseconds), update, canUpdate, useBackgroundThread)
{
}
public DebouncedProperty(TimeSpan throttle, Action<T> update, Func<T, bool> canUpdate = null, bool useBackgroundThread = false)
{
if (useBackgroundThread)
{
_backgroundTimer = new Timer(OnTick);
}
else
{
_timer = new DispatcherTimer();
_timer.Interval = throttle;
_timer.Tick += OnTick;
}
_interval = throttle;
_update = update;
_canUpdate = canUpdate ?? DefaultCanUpdate;
}
private static bool DefaultCanUpdate(T value)
{
return true;
}
public static implicit operator T(DebouncedProperty<T> debouncer)
{
return debouncer._value;
}
public void Cancel()
{
_timer?.Stop();
_backgroundTimer?.Change(Timeout.Infinite, Timeout.Infinite);
}
private void OnTick(object sender)
{
_backgroundTimer.Change(Timeout.Infinite, Timeout.Infinite);
if (_cancellationToken.IsCancellationRequested)
{
_lastValue = default;
}
else
{
_value = _lastValue;
_update(_lastValue);
_lastValue = default;
}
}
private void OnTick(object sender, object e)
{
_timer.Stop();
if (_cancellationToken.IsCancellationRequested)
{
_lastValue = default;
}
else
{
_value = _lastValue;
_update(_lastValue);
_lastValue = default;
}
}
public T Value
{
get => _value;
set => _value = value;
}
public void Set(T value, CancellationToken cancellationToken = default)
{
_timer?.Stop();
_backgroundTimer?.Change(Timeout.Infinite, Timeout.Infinite);
if (_canUpdate(value))
{
_cancellationToken = cancellationToken;
_lastValue = value;
_timer?.Start();
_backgroundTimer?.Change(_interval, TimeSpan.Zero);
}
else
{
_cancellationToken = default;
_value = value;
_lastValue = default;
}
}
}
}