• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

thorstenalpers / CleanMyPosts / 15141113493

20 May 2025 03:04PM UTC coverage: 0.0% (-11.5%) from 11.466%
15141113493

push

github

thorstenalpers
Change test framework

0 of 278 branches covered (0.0%)

Branch coverage included in aggregate %.

0 of 882 relevant lines covered (0.0%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/UI/ViewModels/XViewModel.cs
1
using System.Windows;
2
using CleanMyPosts.UI.Contracts.Services;
3
using CleanMyPosts.UI.Models;
4
using CleanMyPosts.UI.Views;
5
using CommunityToolkit.Mvvm.ComponentModel;
6
using CommunityToolkit.Mvvm.Input;
7
using Microsoft.Extensions.Logging;
8
using Microsoft.Extensions.Options;
9
using Microsoft.Web.WebView2.Wpf;
10

11
namespace CleanMyPosts.UI.ViewModels;
12

13
public partial class XViewModel : ObservableObject
14
{
15
    private readonly IWebViewHostService _webViewHostService;
16
    private readonly ILogger<XViewModel> _logger;
17
    private readonly IXWebViewScriptService _xWebViewScriptService;
18
    private OverlayWindow _overlayWindow;
19

20
    private readonly string _xBaseUrl;
21

22
    [ObservableProperty]
23
    private bool _areButtonsEnabled;
24

25
    private bool _isInitialized = false;
26
    private string _userName;
27

28
    public XViewModel(ILogger<XViewModel> logger,
×
29
                         IWebViewHostService webViewHostService,
×
30
                         IOptions<AppConfig> options,
×
31
                         IXWebViewScriptService xWebViewScriptService)
×
32
    {
33
        _webViewHostService = webViewHostService ?? throw new ArgumentNullException(nameof(webViewHostService));
×
34
        _xWebViewScriptService = xWebViewScriptService ?? throw new ArgumentNullException(nameof(xWebViewScriptService));
×
35
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
×
36
        _webViewHostService.NavigationCompleted += OnNavigationCompleted;
×
37
        _webViewHostService.WebMessageReceived += OnWebMessageReceived;
×
38
        _xBaseUrl = options.Value.XBaseUrl;
×
39
    }
×
40

41
    public async Task InitializeAsync(WebView2 webView)
42
    {
43
        if (_isInitialized)
×
44
        {
45
            return;
×
46
        }
47

48
        await _webViewHostService.InitializeAsync(webView);
×
49

50
        _webViewHostService.Source = new Uri(_xBaseUrl);
×
51

52
        var jsScript = @"
×
53
                window.onerror = function(message, source, lineno, colno, error) {
×
54
                    chrome.webview.postMessage(JSON.stringify({
×
55
                        level: 'error',
×
56
                        message: `JS Error: ${message} at ${source}:${lineno}:${colno}`
×
57
                    }));
×
58
                };
×
59
            ";
×
60

61
        await _webViewHostService.ExecuteScriptAsync(jsScript);
×
62

63
        _isInitialized = true;
×
64
    }
×
65

66
    private async void OnNavigationCompleted(object sender, NavigationCompletedEventArgs e)
67
    {
68
        if (e.IsSuccess)
×
69
        {
70
            if (!string.IsNullOrEmpty(_userName))
×
71
            {
72
                return;
×
73
            }
74

75
            const int maxRetries = 5;
76
            const int delayMs = 500;
77

78
            var attempts = 0;
×
79
            while (attempts < maxRetries)
×
80
            {
81
                _userName = await _xWebViewScriptService.GetUserNameAsync();
×
82
                if (!string.IsNullOrEmpty(_userName))
×
83
                {
84
                    _logger.LogInformation("User logged in.");
×
85
                    AreButtonsEnabled = true;
×
86
                    return;
×
87
                }
88
                attempts++;
×
89
                await Task.Delay(delayMs);
×
90
            }
91
            _logger.LogInformation("User not logged in.");
×
92
        }
93
    }
×
94

95
    private void OnWebMessageReceived(object sender, WebMessageReceivedEventArgs e)
96
    {
97
        try
98
        {
99
            var jsonDoc = System.Text.Json.JsonDocument.Parse(e.Message);
×
100
            var root = jsonDoc.RootElement;
×
101
            var level = root.GetProperty("level").GetString();
×
102
            var message = root.GetProperty("message").GetString();
×
103

104
            if (level == "error")
×
105
            {
106
                _logger.LogError("JS Error: {Message}", message);
×
107
            }
108
            else if (level == "warning")
×
109
            {
110
                _logger.LogWarning("JS Warning: {Message}", message);
×
111
            }
112
            else
113
            {
114
                _logger.LogInformation("JS: {Message}", message);
×
115
            }
116
        }
×
117
        catch (Exception ex)
×
118
        {
119
            _logger.LogWarning(ex, "Malformed JS message: {Raw}", e.Message);
×
120
        }
×
121
    }
×
122

123
    private EventHandler<NavigationCompletedEventArgs> IsUserLoggedInEventHandler()
124
    {
125
        return async (s, e) =>
×
126
        {
×
127
            if (e.IsSuccess)
×
128
            {
×
129
                var maxRetries = 5;
×
130
                var delayInMilliseconds = 500;
×
131
                var attempts = 0;
×
132
                string userName = null;
×
133

×
134
                while (attempts < maxRetries)
×
135
                {
×
136
                    userName = await _xWebViewScriptService.GetUserNameAsync();
×
137
                    if (!string.IsNullOrEmpty(userName))
×
138
                    {
×
139
                        AreButtonsEnabled = true;
×
140
                        _webViewHostService.NavigationCompleted -= IsUserLoggedInEventHandler();
×
141
                        return;
×
142
                    }
×
143
                    else
×
144
                    {
×
145
                        attempts++;
×
146
                        await Task.Delay(delayInMilliseconds);
×
147
                    }
×
148
                }
×
149
            }
×
150
        };
×
151
    }
152

153
    [RelayCommand]
154
    private async Task ShowPosts()
155
    {
156
        EnableUserInteractions(false);
×
157
        await _xWebViewScriptService.ShowPostsAsync();
×
158
        EnableUserInteractions(true);
×
159
    }
×
160

161
    [RelayCommand]
162
    private async Task DeletePosts()
163
    {
164
        EnableUserInteractions(false);
×
165
        await _xWebViewScriptService.DeletePostsAsync();
×
166
        EnableUserInteractions(true);
×
167
    }
×
168

169
    [RelayCommand]
170
    private async Task ShowLikes()
171
    {
172
        EnableUserInteractions(false);
×
173
        await _xWebViewScriptService.ShowLikesAsync();
×
174
        EnableUserInteractions(true);
×
175
    }
×
176

177
    [RelayCommand]
178
    private async Task DeleteLikes()
179
    {
180
        EnableUserInteractions(false);
×
181
        await Task.Delay(10002);
×
182
        EnableUserInteractions(true);
×
183
    }
×
184

185
    [RelayCommand]
186
    private async Task ShowFollowing()
187
    {
188
        EnableUserInteractions(false);
×
189
        await _xWebViewScriptService.ShowFollowingAsync();
×
190
        EnableUserInteractions(true);
×
191
    }
×
192

193
    [RelayCommand]
194
    private async Task DeleteFollowing()
195
    {
196
        EnableUserInteractions(false);
×
197
        await Task.Delay(10001);
×
198
        EnableUserInteractions(true);
×
199
    }
×
200

201
    private void EnableUserInteractions(bool enable)
202
    {
203
        if (enable)
×
204
        {
205
            AreButtonsEnabled = true;
×
206
            if (_overlayWindow != null)
×
207
            {
208
                var mainWindow = Application.Current.MainWindow;
×
209
                if (mainWindow != null)
×
210
                {
211
                    mainWindow.LocationChanged -= MainWindowOnLocationOrSizeChanged;
×
212
                    mainWindow.SizeChanged -= MainWindowOnLocationOrSizeChanged;
×
213
                }
214

215
                _overlayWindow.Close();
×
216
                _overlayWindow = null;
×
217
            }
218
        }
219
        else
220
        {
221
            AreButtonsEnabled = false;
×
222

223
            if (_overlayWindow == null)
×
224
            {
225
                _overlayWindow = new OverlayWindow
×
226
                {
×
227
                    WindowStartupLocation = WindowStartupLocation.Manual,
×
228
                    Owner = Application.Current.MainWindow
×
229
                };
×
230
                UpdateOverlayPosition();
×
231
                var mainWindow = Application.Current.MainWindow;
×
232
                if (mainWindow != null)
×
233
                {
234
                    mainWindow.LocationChanged += MainWindowOnLocationOrSizeChanged;
×
235
                    mainWindow.SizeChanged += MainWindowOnLocationOrSizeChanged;
×
236
                }
237
                _overlayWindow.Show();
×
238
            }
239
        }
240
    }
×
241

242
    private void MainWindowOnLocationOrSizeChanged(object sender, EventArgs e)
243
    {
244
        UpdateOverlayPosition();
×
245
    }
×
246

247
    private void UpdateOverlayPosition()
248
    {
249
        if (_overlayWindow == null)
×
250
        {
251
            return;
×
252
        }
253

254
        var mainWindow = Application.Current.MainWindow;
×
255
        if (mainWindow == null)
×
256
        {
257
            return;
×
258
        }
259

260
        var topLeft = mainWindow.PointToScreen(new Point(0, 0));
×
261

262
        var presentationSource = PresentationSource.FromVisual(mainWindow);
×
263
        if (presentationSource?.CompositionTarget != null)
×
264
        {
265
            var transform = presentationSource.CompositionTarget.TransformFromDevice;
×
266
            var topLeftInWpfUnits = transform.Transform(topLeft);
×
267

268
            _overlayWindow.Left = topLeftInWpfUnits.X;
×
269
            _overlayWindow.Top = topLeftInWpfUnits.Y;
×
270
            _overlayWindow.Width = mainWindow.ActualWidth;
×
271
            _overlayWindow.Height = mainWindow.ActualHeight;
×
272
        }
273
        else
274
        {
275
            _overlayWindow.Left = topLeft.X;
×
276
            _overlayWindow.Top = topLeft.Y;
×
277
            _overlayWindow.Width = mainWindow.ActualWidth;
×
278
            _overlayWindow.Height = mainWindow.ActualHeight;
×
279
        }
280
    }
×
281
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc