Skip to content

Commit 75cdfd0

Browse files
authored
1 parent a58864e commit 75cdfd0

File tree

4 files changed

+56
-10
lines changed

4 files changed

+56
-10
lines changed

App/Services/MutagenController.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public interface ISyncSessionController : IAsyncDisposable
8585
/// </summary>
8686
Task<SyncSessionControllerStateModel> RefreshState(CancellationToken ct = default);
8787

88-
Task<SyncSessionModel> CreateSyncSession(CreateSyncSessionRequest req, CancellationToken ct = default);
88+
Task<SyncSessionModel> CreateSyncSession(CreateSyncSessionRequest req, Action<string> progressCallback, CancellationToken ct = default);
8989
Task<SyncSessionModel> PauseSyncSession(string identifier, CancellationToken ct = default);
9090
Task<SyncSessionModel> ResumeSyncSession(string identifier, CancellationToken ct = default);
9191
Task TerminateSyncSession(string identifier, CancellationToken ct = default);
@@ -200,12 +200,15 @@ public async Task<SyncSessionControllerStateModel> RefreshState(CancellationToke
200200
return state;
201201
}
202202

203-
public async Task<SyncSessionModel> CreateSyncSession(CreateSyncSessionRequest req, CancellationToken ct = default)
203+
public async Task<SyncSessionModel> CreateSyncSession(CreateSyncSessionRequest req, Action<string>? progressCallback = null, CancellationToken ct = default)
204204
{
205205
using var _ = await _lock.LockAsync(ct);
206206
var client = await EnsureDaemon(ct);
207207

208208
await using var prompter = await Prompter.Create(client, true, ct);
209+
if (progressCallback != null)
210+
prompter.OnProgress += (_, progress) => progressCallback(progress);
211+
209212
var createRes = await client.Synchronization.CreateAsync(new CreateRequest
210213
{
211214
Prompter = prompter.Identifier,
@@ -603,6 +606,8 @@ private async Task StopDaemon(CancellationToken ct)
603606

604607
private class Prompter : IAsyncDisposable
605608
{
609+
public event EventHandler<string>? OnProgress;
610+
606611
private readonly AsyncDuplexStreamingCall<HostRequest, HostResponse> _dup;
607612
private readonly CancellationTokenSource _cts;
608613
private readonly Task _handleRequestsTask;
@@ -684,6 +689,9 @@ private async Task HandleRequests(CancellationToken ct)
684689
if (response.Message == null)
685690
throw new InvalidOperationException("Prompting.Host response stream returned a null message");
686691

692+
if (!response.IsPrompt)
693+
OnProgress?.Invoke(this, response.Message);
694+
687695
// Currently we only reply to SSH fingerprint messages with
688696
// "yes" and send an empty reply for everything else.
689697
var reply = "";

App/ViewModels/FileSyncListViewModel.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public partial class FileSyncListViewModel : ObservableObject
6767
public partial string NewSessionRemotePath { get; set; } = "";
6868
// TODO: NewSessionRemotePathDialogOpen for remote path
6969

70+
[ObservableProperty]
71+
public partial string NewSessionStatus { get; set; } = "";
72+
7073
public bool NewSessionCreateEnabled
7174
{
7275
get
@@ -187,6 +190,7 @@ private void ClearNewForm()
187190
NewSessionLocalPath = "";
188191
NewSessionRemoteHost = "";
189192
NewSessionRemotePath = "";
193+
NewSessionStatus = "";
190194
}
191195

192196
[RelayCommand]
@@ -263,13 +267,26 @@ private void CancelNewSession()
263267
ClearNewForm();
264268
}
265269

270+
private void OnCreateSessionProgress(string message)
271+
{
272+
// Ensure we're on the UI thread.
273+
if (_dispatcherQueue == null) return;
274+
if (!_dispatcherQueue.HasThreadAccess)
275+
{
276+
_dispatcherQueue.TryEnqueue(() => OnCreateSessionProgress(message));
277+
return;
278+
}
279+
280+
NewSessionStatus = message;
281+
}
282+
266283
[RelayCommand]
267284
private async Task ConfirmNewSession()
268285
{
269286
if (OperationInProgress || !NewSessionCreateEnabled) return;
270287
OperationInProgress = true;
271288

272-
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(15));
289+
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(120));
273290
try
274291
{
275292
// The controller will send us a state changed event.
@@ -286,7 +303,7 @@ await _syncSessionController.CreateSyncSession(new CreateSyncSessionRequest
286303
Host = NewSessionRemoteHost,
287304
Path = NewSessionRemotePath,
288305
},
289-
}, cts.Token);
306+
}, OnCreateSessionProgress, cts.Token);
290307

291308
ClearNewForm();
292309
}
@@ -304,6 +321,7 @@ await _syncSessionController.CreateSyncSession(new CreateSyncSessionRequest
304321
finally
305322
{
306323
OperationInProgress = false;
324+
NewSessionStatus = "";
307325
}
308326
}
309327

App/Views/Pages/FileSyncListMainPage.xaml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,11 @@
274274
<ColumnDefinition Width="2*" MinWidth="200" />
275275
<ColumnDefinition Width="1*" MinWidth="120" />
276276
<ColumnDefinition Width="2*" MinWidth="200" />
277-
<ColumnDefinition Width="1*" MinWidth="100" MaxWidth="200" />
278-
<ColumnDefinition Width="1*" MinWidth="100" MaxWidth="200" />
277+
<!--
278+
To fit the status better, the last two columns
279+
are merged for the new sync row.
280+
-->
281+
<ColumnDefinition Width="2*" MinWidth="200" MaxWidth="400" />
279282
</Grid.ColumnDefinitions>
280283

281284
<Border Grid.Column="0" Padding="0">
@@ -340,6 +343,13 @@
340343
HorizontalAlignment="Stretch"
341344
Text="{x:Bind ViewModel.NewSessionRemotePath, Mode=TwoWay}" />
342345
</Border>
346+
<Border Grid.Column="4">
347+
<TextBlock
348+
Text="{x:Bind ViewModel.NewSessionStatus, Mode=OneWay}"
349+
VerticalAlignment="Center"
350+
TextTrimming="CharacterEllipsis"
351+
IsTextTrimmedChanged="TooltipText_IsTextTrimmedChanged" />
352+
</Border>
343353
</Grid>
344354
</StackPanel>
345355
</ScrollView>

Tests.App/Services/MutagenControllerTest.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ public async Task Ok(CancellationToken ct)
112112
// Ensure the daemon is stopped because all sessions are terminated.
113113
await AssertDaemonStopped(dataDirectory, ct);
114114

115+
var progressMessages = new List<string>();
116+
void OnProgress(string message)
117+
{
118+
TestContext.Out.WriteLine("Create session progress: " + message);
119+
progressMessages.Add(message);
120+
}
121+
115122
var session1 = await controller.CreateSyncSession(new CreateSyncSessionRequest
116123
{
117124
Alpha = new CreateSyncSessionRequest.Endpoint
@@ -124,7 +131,10 @@ public async Task Ok(CancellationToken ct)
124131
Protocol = CreateSyncSessionRequest.Endpoint.ProtocolKind.Local,
125132
Path = betaDirectory.FullName,
126133
},
127-
}, ct);
134+
}, OnProgress, ct);
135+
136+
// There should've been at least one progress message.
137+
Assert.That(progressMessages, Is.Not.Empty);
128138

129139
state = controller.GetState();
130140
Assert.That(state.SyncSessions, Has.Count.EqualTo(1));
@@ -142,7 +152,7 @@ public async Task Ok(CancellationToken ct)
142152
Protocol = CreateSyncSessionRequest.Endpoint.ProtocolKind.Local,
143153
Path = betaDirectory.FullName,
144154
},
145-
}, ct);
155+
}, null, ct);
146156

147157
state = controller.GetState();
148158
Assert.That(state.SyncSessions, Has.Count.EqualTo(2));
@@ -225,7 +235,7 @@ await controller.CreateSyncSession(new CreateSyncSessionRequest
225235
Protocol = CreateSyncSessionRequest.Endpoint.ProtocolKind.Local,
226236
Path = betaDirectory.FullName,
227237
},
228-
}, ct);
238+
}, null, ct);
229239
}
230240

231241
await AssertDaemonStopped(dataDirectory, ct);
@@ -265,7 +275,7 @@ await controller1.CreateSyncSession(new CreateSyncSessionRequest
265275
Protocol = CreateSyncSessionRequest.Endpoint.ProtocolKind.Local,
266276
Path = betaDirectory.FullName,
267277
},
268-
}, ct);
278+
}, null, ct);
269279

270280
controller2 = new MutagenController(_mutagenBinaryPath, dataDirectory);
271281
await controller2.RefreshState(ct);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy