Skip to content

Commit cc7cbf7

Browse files
committed
feat: improve InventoryLocalIdentificationView
1 parent e35faa6 commit cc7cbf7

5 files changed

Lines changed: 238 additions & 9 deletions

File tree

src/ByteSync.Client/Business/Inventories/InventoryProcessData.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ public InventoryProcessData()
4242
}
4343
else if (v.Identification == InventoryTaskStatus.Running)
4444
{
45-
IdentificationStatus.OnNext(InventoryTaskStatus.Cancelled);
45+
IdentificationStatus.OnNext(v.Main == InventoryTaskStatus.Error
46+
? InventoryTaskStatus.Error
47+
: InventoryTaskStatus.Cancelled);
4648
}
4749
});
4850

@@ -57,7 +59,9 @@ public InventoryProcessData()
5759
}
5860
else if (v.Analysis == InventoryTaskStatus.Running)
5961
{
60-
AnalysisStatus.OnNext(InventoryTaskStatus.Cancelled);
62+
AnalysisStatus.OnNext(v.Main == InventoryTaskStatus.Error
63+
? InventoryTaskStatus.Error
64+
: InventoryTaskStatus.Cancelled);
6165
}
6266
});
6367

src/ByteSync.Client/ViewModels/Sessions/Inventories/InventoryLocalIdentificationViewModel.cs

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1-
using System.Reactive.Disposables;
1+
using System.Reactive.Disposables;
22
using System.Reactive.Linq;
3+
using Avalonia.Media;
4+
using ByteSync.Assets.Resources;
35
using ByteSync.Business.Inventories;
46
using ByteSync.Interfaces.Controls.Inventories;
7+
using ByteSync.Interfaces.Controls.Themes;
58
using ReactiveUI;
69
using ReactiveUI.Fody.Helpers;
710

811
namespace ByteSync.ViewModels.Sessions.Inventories;
912

1013
public class InventoryLocalIdentificationViewModel : ActivatableViewModelBase
1114
{
12-
private readonly IInventoryService _inventoryService;
15+
private readonly IInventoryService _inventoryService = null!;
16+
private readonly IThemeService _themeService = null!;
1317

1418
public InventoryLocalIdentificationViewModel()
1519
{
@@ -22,6 +26,13 @@ public InventoryLocalIdentificationViewModel(IInventoryService inventoryService)
2226
this.WhenActivated(HandleActivation);
2327
}
2428

29+
public InventoryLocalIdentificationViewModel(IInventoryService inventoryService, IThemeService themeService)
30+
: this(inventoryService)
31+
{
32+
_themeService = themeService;
33+
IdentificationIconBrush = _themeService.GetBrush("HomeCloudSynchronizationBackGround");
34+
}
35+
2536
private void HandleActivation(CompositeDisposable disposables)
2637
{
2738
_inventoryService.InventoryProcessData.IdentificationStatus
@@ -42,6 +53,63 @@ private void HandleActivation(CompositeDisposable disposables)
4253
IdentifiedSize = m.IdentifiedSize;
4354
})
4455
.DisposeWith(disposables);
56+
57+
_inventoryService.InventoryProcessData.IdentificationStatus
58+
.ObserveOn(RxApp.MainThreadScheduler)
59+
.Subscribe(status =>
60+
{
61+
switch (status)
62+
{
63+
case InventoryTaskStatus.Error:
64+
case InventoryTaskStatus.Cancelled:
65+
case InventoryTaskStatus.NotLaunched:
66+
IdentificationIcon = "SolidXCircle";
67+
SetIdentificationBrush(status);
68+
69+
break;
70+
case InventoryTaskStatus.Success:
71+
IdentificationIcon = "SolidCheckCircle";
72+
SetIdentificationBrush(status);
73+
74+
break;
75+
case InventoryTaskStatus.Pending:
76+
IdentificationIcon = "RegularPauseCircle";
77+
SetIdentificationBrush(status);
78+
79+
break;
80+
case InventoryTaskStatus.Running:
81+
IdentificationIcon = "None";
82+
SetIdentificationBrush(status);
83+
84+
break;
85+
default:
86+
IdentificationIcon = "None";
87+
SetIdentificationBrush(status);
88+
89+
break;
90+
}
91+
92+
string key = status switch
93+
{
94+
InventoryTaskStatus.Success => "InventoryProcess_IdentificationSuccess",
95+
InventoryTaskStatus.Cancelled => "InventoryProcess_IdentificationCancelled",
96+
InventoryTaskStatus.Error => "InventoryProcess_IdentificationError",
97+
InventoryTaskStatus.Pending => "InventoryProcess_IdentificationRunning",
98+
InventoryTaskStatus.Running => "InventoryProcess_IdentificationRunning",
99+
InventoryTaskStatus.NotLaunched => "InventoryProcess_IdentificationCancelled",
100+
_ => string.Empty
101+
};
102+
IdentificationStatusText = string.IsNullOrEmpty(key)
103+
? string.Empty
104+
: Resources.ResourceManager.GetString(key, Resources.Culture) ?? string.Empty;
105+
})
106+
.DisposeWith(disposables);
107+
108+
_themeService.SelectedTheme
109+
.Skip(1)
110+
.ObserveOn(RxApp.MainThreadScheduler)
111+
.Subscribe(_ => { SetIdentificationBrush(IdentificationStatus); })
112+
.DisposeWith(disposables);
45113
}
46114

47115
public extern InventoryTaskStatus IdentificationStatus { [ObservableAsProperty] get; }
@@ -56,4 +124,39 @@ private void HandleActivation(CompositeDisposable disposables)
56124

57125
[Reactive]
58126
public long IdentifiedSize { get; set; }
127+
128+
[Reactive]
129+
public string IdentificationIcon { get; set; } = "None";
130+
131+
[Reactive]
132+
public string IdentificationStatusText { get; set; } = string.Empty;
133+
134+
[Reactive]
135+
public IBrush? IdentificationIconBrush { get; set; }
136+
137+
private void SetIdentificationBrush(InventoryTaskStatus status)
138+
{
139+
switch (status)
140+
{
141+
case InventoryTaskStatus.Error:
142+
case InventoryTaskStatus.Cancelled:
143+
case InventoryTaskStatus.NotLaunched:
144+
IdentificationIconBrush = _theme_service_get_secondary();
145+
146+
break;
147+
case InventoryTaskStatus.Success:
148+
IdentificationIconBrush = _theme_service_get_background();
149+
150+
break;
151+
case InventoryTaskStatus.Pending:
152+
case InventoryTaskStatus.Running:
153+
default:
154+
IdentificationIconBrush = _theme_service_get_background();
155+
156+
break;
157+
}
158+
}
159+
160+
private IBrush _theme_service_get_background() => _themeService.GetBrush("HomeCloudSynchronizationBackGround");
161+
private IBrush _theme_service_get_secondary() => _themeService.GetBrush("MainSecondaryColor");
59162
}

src/ByteSync.Client/ViewModels/Sessions/Inventories/InventoryLocalStatusViewModel.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class InventoryLocalStatusViewModel : ActivatableViewModelBase
1919
private readonly ITimeTrackingCache _timeTrackingCache = null!;
2020
private readonly IInventoryService _inventoryService = null!;
2121
private readonly IThemeService? _themeService;
22+
private InventoryTaskStatus _currentLocalStatus;
2223

2324
public InventoryLocalStatusViewModel()
2425
{
@@ -81,6 +82,7 @@ public InventoryLocalStatusViewModel(ISessionService sessionService, ITimeTracki
8182
.ObserveOn(RxApp.MainThreadScheduler)
8283
.Subscribe(st =>
8384
{
85+
_currentLocalStatus = st;
8486
switch (st)
8587
{
8688
case InventoryTaskStatus.Pending:
@@ -128,6 +130,33 @@ public InventoryLocalStatusViewModel(ISessionService sessionService, ITimeTracki
128130
}
129131
})
130132
.DisposeWith(disposables);
133+
134+
_themeService?.SelectedTheme
135+
.Skip(1)
136+
.ObserveOn(RxApp.MainThreadScheduler)
137+
.Subscribe(_ =>
138+
{
139+
switch (_currentLocalStatus)
140+
{
141+
case InventoryTaskStatus.Success:
142+
LocalMainIconBrush = _themeService?.GetBrush("HomeCloudSynchronizationBackGround");
143+
144+
break;
145+
case InventoryTaskStatus.Pending:
146+
case InventoryTaskStatus.Running:
147+
LocalMainIconBrush = null;
148+
149+
break;
150+
case InventoryTaskStatus.Error:
151+
case InventoryTaskStatus.Cancelled:
152+
case InventoryTaskStatus.NotLaunched:
153+
default:
154+
LocalMainIconBrush = _themeService?.GetBrush("MainSecondaryColor");
155+
156+
break;
157+
}
158+
})
159+
.DisposeWith(disposables);
131160
});
132161
}
133162

src/ByteSync.Client/Views/Sessions/Inventories/InventoryLocalIdentificationView.axaml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,15 @@
2020
IsVisible="{Binding IsIdentificationRunning}" />
2121

2222
<misc:Icon FontSize="60"
23-
Value="{Binding IdentificationStatus,
24-
Converter={StaticResource InventoryProcessStatusToIconConverter}}"
25-
Foreground="{DynamicResource HomeCloudSynchronizationBackGround}"
23+
Value="{Binding IdentificationIcon}"
24+
Foreground="{Binding IdentificationIconBrush}"
2625
IsVisible="{Binding !IsIdentificationRunning}"
2726
Margin="0" VerticalAlignment="Center" HorizontalAlignment="Center" />
2827

2928
</StackPanel>
3029

3130
<Label Height="30" VerticalContentAlignment="Center"
32-
Content="{Binding IdentificationStatus, Converter={StaticResource InventoryProcessStatusToTextConverter},
33-
ConverterParameter='InventoryProcess_Identification'}"
31+
Content="{Binding IdentificationStatusText}"
3432
HorizontalContentAlignment="Center" FontWeight="Bold" Margin="6" />
3533

3634
<Grid HorizontalAlignment="Center" Margin="3 12 3 0" Height="100">
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System.Reactive.Linq;
2+
using Avalonia.Media;
3+
using ByteSync.Business.Inventories;
4+
using ByteSync.Business.Themes;
5+
using ByteSync.Interfaces.Controls.Inventories;
6+
using ByteSync.Interfaces.Controls.Themes;
7+
using ByteSync.Tests.Helpers;
8+
using ByteSync.ViewModels.Sessions.Inventories;
9+
using FluentAssertions;
10+
using Moq;
11+
using NUnit.Framework;
12+
13+
namespace ByteSync.Tests.ViewModels.Sessions.Inventories;
14+
15+
[TestFixture]
16+
public class InventoryLocalIdentificationViewModelTests
17+
{
18+
private InventoryProcessData _processData = null!;
19+
private Mock<IInventoryService> _inventoryService = null!;
20+
private Mock<IThemeService> _themeService = null!;
21+
private IBrush _backgroundBrush = null!;
22+
private IBrush _secondaryBrush = null!;
23+
24+
[SetUp]
25+
public void Setup()
26+
{
27+
_processData = new InventoryProcessData();
28+
29+
_inventoryService = new Mock<IInventoryService>();
30+
_inventoryService.SetupGet(x => x.InventoryProcessData).Returns(_processData);
31+
32+
_backgroundBrush = Mock.Of<IBrush>();
33+
_secondaryBrush = Mock.Of<IBrush>();
34+
35+
_themeService = new Mock<IThemeService>(MockBehavior.Strict);
36+
_themeService.Setup(x => x.GetBrush("HomeCloudSynchronizationBackGround")).Returns(_backgroundBrush);
37+
_themeService.Setup(x => x.GetBrush("MainSecondaryColor")).Returns(_secondaryBrush);
38+
_themeService.SetupGet(x => x.SelectedTheme)
39+
.Returns(Observable.Never<Theme>());
40+
}
41+
42+
[Test]
43+
public void StatusTransitions_UpdateIconsBrushesAndText()
44+
{
45+
var vm = CreateVm();
46+
47+
vm.IdentificationIcon.Should().Be("RegularPauseCircle");
48+
vm.IdentificationIconBrush.Should().BeSameAs(_backgroundBrush);
49+
_processData.IdentificationStatus.OnNext(InventoryTaskStatus.Pending);
50+
51+
_processData.IdentificationStatus.OnNext(InventoryTaskStatus.Running);
52+
53+
vm.IdentificationStatus.Should().Be(InventoryTaskStatus.Running);
54+
vm.IsIdentificationRunning.Should().BeTrue();
55+
vm.IdentificationIcon.Should().Be("None");
56+
vm.IdentificationIconBrush.Should().BeSameAs(_backgroundBrush);
57+
vm.IdentificationStatusText.Should().NotBeNullOrWhiteSpace();
58+
59+
_processData.IdentificationStatus.OnNext(InventoryTaskStatus.Cancelled);
60+
61+
vm.IdentificationStatus.Should().Be(InventoryTaskStatus.Cancelled);
62+
vm.IsIdentificationRunning.Should().BeFalse();
63+
vm.IdentificationIcon.Should().Be("SolidXCircle");
64+
vm.IdentificationIconBrush.Should().BeSameAs(_secondaryBrush);
65+
var cancelledText = vm.IdentificationStatusText;
66+
cancelledText.Should().NotBeNullOrWhiteSpace();
67+
68+
_processData.IdentificationStatus.OnNext(InventoryTaskStatus.Success);
69+
70+
vm.IdentificationStatus.Should().Be(InventoryTaskStatus.Success);
71+
vm.IdentificationIcon.Should().Be("SolidCheckCircle");
72+
vm.IdentificationIconBrush.Should().BeSameAs(_backgroundBrush);
73+
var successText = vm.IdentificationStatusText;
74+
successText.Should().NotBeNullOrWhiteSpace();
75+
successText.Should().NotBe(cancelledText);
76+
77+
// Simulate a running identification then a main error
78+
_processData.IdentificationStatus.OnNext(InventoryTaskStatus.Running);
79+
_processData.MainStatus.OnNext(InventoryTaskStatus.Error);
80+
81+
vm.ShouldEventuallyBe(x => x.IdentificationStatus, InventoryTaskStatus.Error);
82+
vm.IdentificationIcon.Should().Be("SolidXCircle");
83+
vm.IdentificationIconBrush.Should().BeSameAs(_secondaryBrush);
84+
vm.IdentificationStatusText.Should().NotBeNullOrWhiteSpace();
85+
vm.IdentificationStatusText.Should().NotBe(successText);
86+
}
87+
88+
private InventoryLocalIdentificationViewModel CreateVm()
89+
{
90+
var vm = new InventoryLocalIdentificationViewModel(_inventoryService.Object, _themeService.Object);
91+
vm.Activator.Activate();
92+
93+
return vm;
94+
}
95+
}

0 commit comments

Comments
 (0)