mirror of
https://github.com/achiez/NebulaAuth-Steam-Desktop-Authenticator-by-Achies.git
synced 2026-07-25 06:14:31 +00:00
feat(confirmations): reveal items in grouped market sell confirmations (#18)
Grouped market sell confirmations previously appeared as a single row showing only the item count (e.g. "Sell 4 pcs"). This made it difficult to verify which items were being confirmed or their prices. Add an expandable grouped confirmation that reveals individual items with their icon, name and price. Also allow confirming or canceling items individually while keeping confirm-all and cancel-all actions. Includes a scrollable list for large batches and minor UI/code cleanup. Co-authored-by: bohdanbtw [bohdanbtw@DESKTOP-ANGF2KJ](mailto:bohdanbtw@DESKTOP-ANGF2KJ)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using NebulaAuth.Model;
|
||||
@@ -130,7 +130,7 @@ public static class DialogsController
|
||||
var content = msg == null ? new ConfirmCancelDialog() : new ConfirmCancelDialog(msg);
|
||||
|
||||
var result = await DialogHost.Show(content);
|
||||
return result != null && (bool) result;
|
||||
return result != null && (bool)result;
|
||||
}
|
||||
|
||||
public static async Task<string?> ShowTextFieldDialog(string? title = null, string? msg = null)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -51,7 +51,7 @@ public static class Storage
|
||||
await Task.Run(() =>
|
||||
{
|
||||
return Parallel.ForEachAsync(files,
|
||||
new ParallelOptions {CancellationToken = token, MaxDegreeOfParallelism = threadCount},
|
||||
new ParallelOptions { CancellationToken = token, MaxDegreeOfParallelism = threadCount },
|
||||
async (file, ct) =>
|
||||
{
|
||||
try
|
||||
@@ -218,7 +218,7 @@ public static class Storage
|
||||
|
||||
if (counter % 5 == 0)
|
||||
{
|
||||
progress?.Report(counter / (double) files.Count);
|
||||
progress?.Report(counter / (double)files.Count);
|
||||
await Task.Delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:confirmations="clr-namespace:SteamLib.SteamMobile.Confirmations;assembly=SteamLibForked"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
@@ -6,7 +6,6 @@
|
||||
xmlns:entities="clr-namespace:NebulaAuth.Model.Entities"
|
||||
xmlns:vm="clr-namespace:NebulaAuth.ViewModel">
|
||||
|
||||
|
||||
<DataTemplate DataType="{x:Type confirmations:Confirmation}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -175,36 +174,96 @@
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type entities:MarketMultiConfirmation}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<materialDesign:PackIcon VerticalAlignment="Center" Width="20" Height="20" Kind="CartArrowUp"
|
||||
Margin="0,0,10,0" />
|
||||
<TextBlock VerticalAlignment="Center" Grid.Column="1">
|
||||
<Run Text="{Tr MainWindow.ConfirmationTemplates.Market, IsDynamic=False}" />
|
||||
<Run Text="{Binding Confirmations.Count, Mode=OneWay}" />
|
||||
<Run Text="{Tr Common.Abbreviations.Count.Items, IsDynamic=False}" />
|
||||
</TextBlock>
|
||||
<Expander Padding="0" Background="Transparent" materialDesign:ExpanderAssist.ExpanderButtonPosition="Start" materialDesign:ExpanderAssist.HorizontalHeaderPadding="0" HorizontalAlignment="Stretch">
|
||||
<Expander.Header>
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<materialDesign:PackIcon VerticalAlignment="Center" Width="20" Height="20" Kind="CartArrowUp"
|
||||
Margin="0,0,10,0" />
|
||||
<TextBlock VerticalAlignment="Center" Grid.Column="1">
|
||||
<Run Text="{Tr MainWindow.ConfirmationTemplates.Market, IsDynamic=False}" />
|
||||
<Run Text="{Binding Confirmations.Count, Mode=OneWay}" />
|
||||
<Run Text="{Tr Common.Abbreviations.Count.Items, IsDynamic=False}" />
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock VerticalAlignment="Center" Grid.Column="2" HorizontalAlignment="Left" Margin="5,0,0,0"
|
||||
Text="{Binding Time, StringFormat=t}" />
|
||||
<Button Margin="5,0,0,0" VerticalAlignment="Center" Grid.Column="3"
|
||||
Style="{StaticResource MaterialDesignIconButton}"
|
||||
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.(vm:MainVM.ConfirmCommand)}"
|
||||
CommandParameter="{Binding }">
|
||||
<materialDesign:PackIcon Kind="Check" />
|
||||
</Button>
|
||||
<Button Grid.Column="4" Style="{StaticResource MaterialDesignIconButton}"
|
||||
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.(vm:MainVM.CancelCommand)}"
|
||||
CommandParameter="{Binding }">
|
||||
<materialDesign:PackIcon Kind="Close" />
|
||||
</Button>
|
||||
</Grid>
|
||||
<TextBlock VerticalAlignment="Center" Grid.Column="2" HorizontalAlignment="Center" Margin="5,0,0,0"
|
||||
Text="{Binding Time, StringFormat=t}" />
|
||||
|
||||
<!-- Confirm all -->
|
||||
<Button Margin="5,0,0,0" VerticalAlignment="Center" Grid.Column="4"
|
||||
Style="{StaticResource MaterialDesignIconButton}"
|
||||
ToolTip="{Tr MainWindow.ConfirmationTemplates.ConfirmAll}"
|
||||
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.(vm:MainVM.ConfirmCommand)}"
|
||||
CommandParameter="{Binding }">
|
||||
<materialDesign:PackIcon Kind="CheckAll" />
|
||||
</Button>
|
||||
<!-- Cancel all -->
|
||||
<Button Grid.Column="5" Style="{StaticResource MaterialDesignIconButton}"
|
||||
ToolTip="{Tr MainWindow.ConfirmationTemplates.CancelAll}"
|
||||
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.(vm:MainVM.CancelCommand)}"
|
||||
CommandParameter="{Binding }">
|
||||
<materialDesign:PackIcon Kind="Close" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Expander.Header>
|
||||
|
||||
<Border Margin="30,6,0,0" Background="{DynamicResource MaterialDesignPaper}" CornerRadius="4">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
MaxHeight="320">
|
||||
<ItemsControl ItemsSource="{Binding Confirmations}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type confirmations:MarketConfirmation}">
|
||||
<Grid Margin="0,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Image HorizontalAlignment="Center" VerticalAlignment="Center" MaxWidth="32"
|
||||
MaxHeight="32" Margin="0,0,10,0"
|
||||
Source="{Binding ItemImageUri}" />
|
||||
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center">
|
||||
<TextBlock TextWrapping="WrapWithOverflow" Text="{Binding ItemName}" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock VerticalAlignment="Center" Grid.Column="2" HorizontalAlignment="Left"
|
||||
Margin="8,0,0,0"
|
||||
Text="{Binding Time, StringFormat=t}" />
|
||||
|
||||
<Button Margin="5,0,0,0" VerticalAlignment="Center" Grid.Column="3"
|
||||
Style="{StaticResource MaterialDesignIconButton}"
|
||||
ToolTip="{Tr MainWindow.ConfirmationTemplates.ConfirmOne}"
|
||||
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.(vm:MainVM.ConfirmCommand)}"
|
||||
CommandParameter="{Binding}">
|
||||
|
||||
<materialDesign:PackIcon Kind="Check" />
|
||||
</Button>
|
||||
<Button Grid.Column="4" Style="{StaticResource MaterialDesignIconButton}"
|
||||
ToolTip="{Tr MainWindow.ConfirmationTemplates.CancelOne}"
|
||||
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.(vm:MainVM.CancelCommand)}"
|
||||
CommandParameter="{Binding}">
|
||||
<materialDesign:PackIcon Kind="Close" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Expander>
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type confirmations:PurchaseConfirmation}">
|
||||
<Grid>
|
||||
@@ -227,7 +286,7 @@
|
||||
<materialDesign:PackIcon Kind="Check" />
|
||||
</Button>
|
||||
<Button Grid.Column="4" Style="{StaticResource MaterialDesignIconButton}"
|
||||
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.(vm:MainVM.CancelCommand)}"
|
||||
Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.(vm:MainVM.ConfirmCommand)}"
|
||||
CommandParameter="{Binding }">
|
||||
<materialDesign:PackIcon Kind="Close" />
|
||||
</Button>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
@@ -76,18 +76,27 @@ public partial class MainVM //Confirmations
|
||||
return SendConfirmation(SelectedMafile, confirmation, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task SendConfirmation(Mafile mafile, Confirmation confirmation, bool confirm)
|
||||
{
|
||||
bool result;
|
||||
|
||||
try
|
||||
{
|
||||
if (confirmation is MarketMultiConfirmation multi)
|
||||
switch (confirmation)
|
||||
{
|
||||
result = await MaClient.SendMultipleConfirmation(mafile, multi.Confirmations, confirm);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await MaClient.SendConfirmation(mafile, confirmation, confirm);
|
||||
case MarketMultiConfirmation multi:
|
||||
result = await MaClient.SendMultipleConfirmation(mafile, multi.Confirmations, confirm);
|
||||
break;
|
||||
|
||||
case MarketConfirmation market:
|
||||
result = await MaClient.SendConfirmation(mafile, market, confirm);
|
||||
break;
|
||||
|
||||
default:
|
||||
result = await MaClient.SendConfirmation(mafile, confirmation, confirm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -96,13 +105,49 @@ public partial class MainVM //Confirmations
|
||||
return;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
Confirmations.Remove(confirmation);
|
||||
}
|
||||
else
|
||||
if (!result)
|
||||
{
|
||||
SnackbarController.SendSnackbar(GetLocalization("ConfirmationError"));
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateConfirmationState(confirmation);
|
||||
}
|
||||
|
||||
private void UpdateConfirmationState(Confirmation confirmation)
|
||||
{
|
||||
if (confirmation is MarketConfirmation item)
|
||||
{
|
||||
var parent = Confirmations
|
||||
.OfType<MarketMultiConfirmation>()
|
||||
.FirstOrDefault(p => p.Confirmations.Contains(item));
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
Confirmations.Remove(item);
|
||||
return;
|
||||
}
|
||||
|
||||
parent.Confirmations.Remove(item);
|
||||
|
||||
if (parent.Confirmations.Count == 0)
|
||||
{
|
||||
Confirmations.Remove(parent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent.Confirmations.Count == 1)
|
||||
{
|
||||
var remaining = parent.Confirmations[0];
|
||||
var idx = Confirmations.IndexOf(parent);
|
||||
Confirmations[idx] = remaining;
|
||||
return;
|
||||
}
|
||||
|
||||
parent.Time = parent.Confirmations.FirstOrDefault()?.Time ?? parent.Time;
|
||||
return;
|
||||
}
|
||||
|
||||
Confirmations.Remove(confirmation);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
@@ -410,6 +410,34 @@
|
||||
"zh": "购买",
|
||||
"ua": "Покупка",
|
||||
"fr": "Acheter"
|
||||
},
|
||||
"ConfirmAll": {
|
||||
"en": "Confirm all",
|
||||
"ru": "Подтвердить все",
|
||||
"zh": "全部确认",
|
||||
"ua": "Підтвердити все",
|
||||
"fr": "Tout confirmer"
|
||||
},
|
||||
"CancelAll": {
|
||||
"en": "Cancel all",
|
||||
"ru": "Отклонить все",
|
||||
"zh": "全部取消",
|
||||
"ua": "Відхилити все",
|
||||
"fr": "Tout annuler"
|
||||
},
|
||||
"ConfirmOne": {
|
||||
"en": "Confirm this item",
|
||||
"ru": "Подтвердить этот предмет",
|
||||
"zh": "确认此物品",
|
||||
"ua": "Підтвердити цей предмет",
|
||||
"fr": "Confirmer cet objet"
|
||||
},
|
||||
"CancelOne": {
|
||||
"en": "Cancel this item",
|
||||
"ru": "Отклонить этот предмет",
|
||||
"zh": "取消此物品",
|
||||
"ua": "Відхилити цей предмет",
|
||||
"fr": "Annuler cet objet"
|
||||
}
|
||||
},
|
||||
"CodeCopied": {
|
||||
|
||||
Reference in New Issue
Block a user