Merge pull request #345 from bkaankose/hotfix/Expander
New expander control for conversation threads
This commit is contained in:
@@ -192,10 +192,12 @@ namespace Wino.Core.MenuItems
|
||||
item.IsExpanded = false;
|
||||
item.IsSelected = false;
|
||||
|
||||
Remove(item);
|
||||
try
|
||||
{
|
||||
Remove(item);
|
||||
}
|
||||
catch (Exception) { }
|
||||
});
|
||||
|
||||
// RemoveRange(itemsToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
<ResourceDictionary Source="/Styles/CommandBarItems.xaml" />
|
||||
<ResourceDictionary Source="/Styles/ItemContainerStyles.xaml" />
|
||||
<ResourceDictionary Source="/Styles/WinoInfoBar.xaml" />
|
||||
|
||||
<styles:CustomMessageDialogStyles />
|
||||
<styles:WinoExpanderStyle />
|
||||
|
||||
<ResourceDictionary>
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using MoreLinq;
|
||||
using Serilog;
|
||||
using Windows.UI.Xaml;
|
||||
@@ -48,8 +48,15 @@ namespace Wino.Controls.Advanced
|
||||
set { SetValue(LoadMoreCommandProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsThreadScrollingEnabled
|
||||
{
|
||||
get { return (bool)GetValue(IsThreadScrollingEnabledProperty); }
|
||||
set { SetValue(IsThreadScrollingEnabledProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsThreadScrollingEnabledProperty = DependencyProperty.Register(nameof(IsThreadScrollingEnabled), typeof(bool), typeof(WinoListView), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty LoadMoreCommandProperty = DependencyProperty.Register(nameof(LoadMoreCommand), typeof(ICommand), typeof(WinoListView), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty IsThreadListViewProperty = DependencyProperty.Register(nameof(IsThreadListView), typeof(bool), typeof(WinoListView), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty IsThreadListViewProperty = DependencyProperty.Register(nameof(IsThreadListView), typeof(bool), typeof(WinoListView), new PropertyMetadata(false, new PropertyChangedCallback(OnIsThreadViewChanged)));
|
||||
public static readonly DependencyProperty ItemDeletedCommandProperty = DependencyProperty.Register(nameof(ItemDeletedCommand), typeof(ICommand), typeof(WinoListView), new PropertyMetadata(null));
|
||||
|
||||
public WinoListView()
|
||||
@@ -65,7 +72,6 @@ namespace Wino.Controls.Advanced
|
||||
DragItemsCompleted += ItemDragCompleted;
|
||||
DragItemsStarting += ItemDragStarting;
|
||||
SelectionChanged += SelectedItemsChanged;
|
||||
ItemClick += MailItemClicked;
|
||||
ProcessKeyboardAccelerators += ProcessDelKey;
|
||||
}
|
||||
|
||||
@@ -85,6 +91,22 @@ namespace Wino.Controls.Advanced
|
||||
internalScrollviewer.ViewChanged += InternalScrollVeiwerViewChanged;
|
||||
}
|
||||
|
||||
private static void OnIsThreadViewChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoListView winoListView)
|
||||
{
|
||||
winoListView.AdjustThreadViewContainerVisuals();
|
||||
}
|
||||
}
|
||||
|
||||
private void AdjustThreadViewContainerVisuals()
|
||||
{
|
||||
if (IsThreadListView)
|
||||
{
|
||||
ItemContainerTransitions.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private double lastestRaisedOffset = 0;
|
||||
private int lastItemSize = 0;
|
||||
|
||||
@@ -160,19 +182,6 @@ namespace Wino.Controls.Advanced
|
||||
}
|
||||
}
|
||||
|
||||
private void MailItemClicked(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
if (e.ClickedItem is ThreadMailItemViewModel clickedThread)
|
||||
{
|
||||
clickedThread.IsThreadExpanded = !clickedThread.IsThreadExpanded;
|
||||
|
||||
if (!clickedThread.IsThreadExpanded)
|
||||
{
|
||||
SelectedItems.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeSelectionMode(ListViewSelectionMode selectionMode)
|
||||
{
|
||||
SelectionMode = selectionMode;
|
||||
@@ -294,6 +303,10 @@ namespace Wino.Controls.Advanced
|
||||
removedMailItemViewModel.IsSelected = false;
|
||||
WeakReferenceMessenger.Default.Send(new MailItemSelectionRemovedEvent(removedMailItemViewModel));
|
||||
}
|
||||
else if (removedItem is ThreadMailItemViewModel removedThreadItemViewModel)
|
||||
{
|
||||
removedThreadItemViewModel.IsThreadExpanded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,10 +324,19 @@ namespace Wino.Controls.Advanced
|
||||
}
|
||||
else if (addedItem is ThreadMailItemViewModel threadMailItemViewModel)
|
||||
{
|
||||
threadMailItemViewModel.IsThreadExpanded = true;
|
||||
if (IsThreadScrollingEnabled)
|
||||
{
|
||||
if (internalScrollviewer != null && ContainerFromItem(threadMailItemViewModel) is FrameworkElement threadFrameworkElement)
|
||||
{
|
||||
internalScrollviewer.ScrollToElement(threadFrameworkElement, true, true, bringToTopOrLeft: true);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't select thread containers.
|
||||
SelectedItems.Remove(addedItem);
|
||||
// Try to select first item.
|
||||
if (GetThreadInternalListView(threadMailItemViewModel) is WinoListView internalListView)
|
||||
{
|
||||
internalListView.SelectFirstItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,16 +358,23 @@ namespace Wino.Controls.Advanced
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SelectionMode == ListViewSelectionMode.Extended && SelectedItems.Count == 1)
|
||||
{
|
||||
// Tell main list view to unselect all his items.
|
||||
}
|
||||
|
||||
if (SelectedItems[0] is MailItemViewModel selectedMailItemViewModel)
|
||||
public async void SelectFirstItem()
|
||||
{
|
||||
if (Items.Count > 0)
|
||||
{
|
||||
if (Items[0] is MailItemViewModel firstMailItemViewModel)
|
||||
{
|
||||
// Make sure the invisible container is realized.
|
||||
await Task.Delay(250);
|
||||
|
||||
if (ContainerFromItem(firstMailItemViewModel) is ListViewItem firstItemContainer)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send(new ResetSingleMailItemSelectionEvent(selectedMailItemViewModel));
|
||||
firstItemContainer.IsSelected = true;
|
||||
}
|
||||
|
||||
firstMailItemViewModel.IsSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -356,7 +385,7 @@ namespace Wino.Controls.Advanced
|
||||
|
||||
if (itemContainer is ListViewItem listItem)
|
||||
{
|
||||
var expander = listItem.GetChildByName<Expander>("ThreadExpander");
|
||||
var expander = listItem.GetChildByName<WinoExpander>("ThreadExpander");
|
||||
|
||||
if (expander != null)
|
||||
return expander.Content as WinoListView;
|
||||
@@ -370,7 +399,6 @@ namespace Wino.Controls.Advanced
|
||||
DragItemsCompleted -= ItemDragCompleted;
|
||||
DragItemsStarting -= ItemDragStarting;
|
||||
SelectionChanged -= SelectedItemsChanged;
|
||||
ItemClick -= MailItemClicked;
|
||||
ProcessKeyboardAccelerators -= ProcessDelKey;
|
||||
|
||||
if (internalScrollviewer != null)
|
||||
|
||||
@@ -80,8 +80,6 @@ namespace Wino.Controls
|
||||
control.UpdateInformation();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async void UpdateInformation()
|
||||
{
|
||||
if (KnownHostImage == null || InitialsGrid == null || InitialsTextblock == null || (string.IsNullOrEmpty(FromName) && string.IsNullOrEmpty(FromAddress)))
|
||||
|
||||
@@ -2,15 +2,21 @@
|
||||
x:Class="Wino.Controls.MailItemDisplayInformationControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
|
||||
xmlns:controls="using:Wino.Controls"
|
||||
xmlns:enums="using:Wino.Core.Domain.Enums"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:enums="using:Wino.Core.Domain.Enums"
|
||||
xmlns:helpers="using:Wino.Helpers"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
FocusVisualMargin="8"
|
||||
FocusVisualPrimaryBrush="{StaticResource SystemControlRevealFocusVisualBrush}"
|
||||
FocusVisualPrimaryThickness="2"
|
||||
FocusVisualSecondaryBrush="{StaticResource SystemControlFocusVisualSecondaryBrush}"
|
||||
FocusVisualSecondaryThickness="1"
|
||||
xmlns:helpers="using:Wino.Helpers"
|
||||
PointerEntered="ControlPointerEntered"
|
||||
PointerExited="ControlPointerExited">
|
||||
|
||||
@@ -25,26 +31,24 @@
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Background="Transparent" Tapped="ThreadHeaderTapped">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition x:Name="ContainerHeight" Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid>
|
||||
<Grid
|
||||
x:Name="RootContainer"
|
||||
Padding="0,1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
x:DefaultBindMode="OneWay">
|
||||
|
||||
<!-- Custom Interaction Focus Indicator -->
|
||||
<Ellipse
|
||||
Width="8"
|
||||
Height="8"
|
||||
Canvas.ZIndex="9999"
|
||||
Margin="0,12,8,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Visibility="{x:Bind IsCustomFocused, Mode=OneWay}"
|
||||
Fill="{ThemeResource SystemAccentColor}" />
|
||||
Canvas.ZIndex="9999"
|
||||
Fill="{ThemeResource SystemAccentColor}"
|
||||
Visibility="{x:Bind IsCustomFocused, Mode=OneWay}" />
|
||||
|
||||
<Border
|
||||
x:Name="RootContainerVisualWrapper"
|
||||
@@ -66,9 +70,9 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
SenderContactPicture="{x:Bind MailItem.SenderContact.Base64ContactPicture}"
|
||||
FromAddress="{x:Bind MailItem.FromAddress, Mode=OneWay}"
|
||||
FromName="{x:Bind MailItem.FromName, Mode=OneWay}"
|
||||
SenderContactPicture="{x:Bind MailItem.SenderContact.Base64ContactPicture}"
|
||||
Visibility="{x:Bind IsAvatarVisible, Mode=OneWay}" />
|
||||
|
||||
<Grid
|
||||
@@ -145,20 +149,47 @@
|
||||
</Grid>
|
||||
|
||||
<!-- Subject + IsDraft -->
|
||||
<Grid Grid.Row="1" ColumnSpacing="4">
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<local:AnimatedIcon
|
||||
xmlns:local="using:Microsoft.UI.Xaml.Controls"
|
||||
x:Name="ExpandCollapseChevron"
|
||||
Width="14"
|
||||
Height="14"
|
||||
Margin="-4,0,2,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
local:AnimatedIcon.State="NormalOff"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Foreground="{ThemeResource ApplicationForegroundThemeBrush}"
|
||||
RenderTransformOrigin="0.5, 0.5"
|
||||
Visibility="{x:Bind IsThreadExpanderVisible, Mode=OneWay}">
|
||||
<animatedvisuals:AnimatedChevronRightDownSmallVisualSource />
|
||||
<local:AnimatedIcon.FallbackIconSource>
|
||||
<local:FontIconSource
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
FontSize="12"
|
||||
Glyph=""
|
||||
IsTextScaleFactorEnabled="False" />
|
||||
</local:AnimatedIcon.FallbackIconSource>
|
||||
<local:AnimatedIcon.RenderTransform />
|
||||
</local:AnimatedIcon>
|
||||
|
||||
<TextBlock
|
||||
x:Name="TitleText"
|
||||
Grid.Column="1"
|
||||
MaxLines="1"
|
||||
Text="{x:Bind MailItem.Subject}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Grid.Column="2"
|
||||
Margin="4,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="11"
|
||||
@@ -231,7 +262,7 @@
|
||||
<VisualStateGroup x:Name="SizingStates">
|
||||
<VisualState x:Name="Compact">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContainerHeight.Height" Value="50" />
|
||||
<Setter Target="RootContainer.Height" Value="60" />
|
||||
<Setter Target="ContentGrid.Padding" Value="8,0" />
|
||||
<Setter Target="PreviewTextContainer.Visibility" Value="Collapsed" />
|
||||
</VisualState.Setters>
|
||||
@@ -243,7 +274,7 @@
|
||||
<!-- Medium -->
|
||||
<VisualState x:Name="Medium">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContainerHeight.Height" Value="65" />
|
||||
<Setter Target="RootContainer.Height" Value="80" />
|
||||
<Setter Target="ContentGrid.Padding" Value="6,0" />
|
||||
<Setter Target="PreviewTextContainer.Visibility" Value="Visible" />
|
||||
</VisualState.Setters>
|
||||
@@ -255,7 +286,7 @@
|
||||
<!-- Spacious -->
|
||||
<VisualState x:Name="Spacious">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ContainerHeight.Height" Value="Auto" />
|
||||
<Setter Target="RootContainer.Height" Value="Auto" />
|
||||
<Setter Target="ContentGrid.Padding" Value="12,12,6,12" />
|
||||
<Setter Target="PreviewTextContainer.Visibility" Value="Visible" />
|
||||
</VisualState.Setters>
|
||||
@@ -277,6 +308,19 @@
|
||||
</VisualState.StateTriggers>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
<!-- Thread Expanding States -->
|
||||
<VisualStateGroup x:Name="ExpanderStates">
|
||||
<VisualState x:Name="NotExpanded" />
|
||||
<VisualState x:Name="ExpandedState">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpandCollapseChevron.(controls:AnimatedIcon.State)" Value="NormalOn" />
|
||||
</VisualState.Setters>
|
||||
<VisualState.StateTriggers>
|
||||
<StateTrigger IsActive="{x:Bind IsThreadExpanded, Mode=OneWay}" />
|
||||
</VisualState.StateTriggers>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System.Numerics;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
@@ -16,12 +15,14 @@ namespace Wino.Controls
|
||||
{
|
||||
public ImagePreviewControl GetImagePreviewControl() => ContactImage;
|
||||
|
||||
public bool IsRunningHoverAction { get; set; }
|
||||
|
||||
public static readonly DependencyProperty DisplayModeProperty = DependencyProperty.Register(nameof(DisplayMode), typeof(MailListDisplayMode), typeof(MailItemDisplayInformationControl), new PropertyMetadata(MailListDisplayMode.Spacious));
|
||||
public static readonly DependencyProperty ShowPreviewTextProperty = DependencyProperty.Register(nameof(ShowPreviewText), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty IsCustomFocusedProperty = DependencyProperty.Register(nameof(IsCustomFocused), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty IsAvatarVisibleProperty = DependencyProperty.Register(nameof(IsAvatarVisible), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty IsSubjectVisibleProperty = DependencyProperty.Register(nameof(IsSubjectVisible), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty ConnectedExpanderProperty = DependencyProperty.Register(nameof(ConnectedExpander), typeof(Expander), typeof(MailItemDisplayInformationControl), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty ConnectedExpanderProperty = DependencyProperty.Register(nameof(ConnectedExpander), typeof(WinoExpander), typeof(MailItemDisplayInformationControl), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty LeftHoverActionProperty = DependencyProperty.Register(nameof(LeftHoverAction), typeof(MailOperation), typeof(MailItemDisplayInformationControl), new PropertyMetadata(MailOperation.None));
|
||||
public static readonly DependencyProperty CenterHoverActionProperty = DependencyProperty.Register(nameof(CenterHoverAction), typeof(MailOperation), typeof(MailItemDisplayInformationControl), new PropertyMetadata(MailOperation.None));
|
||||
public static readonly DependencyProperty RightHoverActionProperty = DependencyProperty.Register(nameof(RightHoverAction), typeof(MailOperation), typeof(MailItemDisplayInformationControl), new PropertyMetadata(MailOperation.None));
|
||||
@@ -29,6 +30,20 @@ namespace Wino.Controls
|
||||
public static readonly DependencyProperty MailItemProperty = DependencyProperty.Register(nameof(MailItem), typeof(IMailItem), typeof(MailItemDisplayInformationControl), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty IsHoverActionsEnabledProperty = DependencyProperty.Register(nameof(IsHoverActionsEnabled), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty Prefer24HourTimeFormatProperty = DependencyProperty.Register(nameof(Prefer24HourTimeFormat), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty IsThreadExpanderVisibleProperty = DependencyProperty.Register(nameof(IsThreadExpanderVisible), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty IsThreadExpandedProperty = DependencyProperty.Register(nameof(IsThreadExpanded), typeof(bool), typeof(MailItemDisplayInformationControl), new PropertyMetadata(false));
|
||||
|
||||
public bool IsThreadExpanded
|
||||
{
|
||||
get { return (bool)GetValue(IsThreadExpandedProperty); }
|
||||
set { SetValue(IsThreadExpandedProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsThreadExpanderVisible
|
||||
{
|
||||
get { return (bool)GetValue(IsThreadExpanderVisibleProperty); }
|
||||
set { SetValue(IsThreadExpanderVisibleProperty, value); }
|
||||
}
|
||||
|
||||
public bool Prefer24HourTimeFormat
|
||||
{
|
||||
@@ -72,10 +87,9 @@ namespace Wino.Controls
|
||||
set { SetValue(RightHoverActionProperty, value); }
|
||||
}
|
||||
|
||||
|
||||
public Expander ConnectedExpander
|
||||
public WinoExpander ConnectedExpander
|
||||
{
|
||||
get { return (Expander)GetValue(ConnectedExpanderProperty); }
|
||||
get { return (WinoExpander)GetValue(ConnectedExpanderProperty); }
|
||||
set { SetValue(ConnectedExpanderProperty, value); }
|
||||
}
|
||||
|
||||
@@ -109,8 +123,6 @@ namespace Wino.Controls
|
||||
set { SetValue(DisplayModeProperty, value); }
|
||||
}
|
||||
|
||||
private bool tappedHandlingFlag = false;
|
||||
|
||||
public MailItemDisplayInformationControl()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -147,38 +159,22 @@ namespace Wino.Controls
|
||||
|
||||
private void ExecuteHoverAction(MailOperation operation)
|
||||
{
|
||||
IsRunningHoverAction = true;
|
||||
|
||||
MailOperationPreperationRequest package = null;
|
||||
|
||||
if (MailItem is MailCopy mailCopy)
|
||||
package = new MailOperationPreperationRequest(operation, mailCopy, toggleExecution: true);
|
||||
else if (MailItem is ThreadMailItemViewModel threadMailItemViewModel)
|
||||
package = new MailOperationPreperationRequest(operation, threadMailItemViewModel.GetMailCopies(), toggleExecution: true);
|
||||
else if (MailItem is ThreadMailItem threadMailItem)
|
||||
package = new MailOperationPreperationRequest(operation, threadMailItem.ThreadItems.Cast<MailItemViewModel>().Select(a => a.MailCopy), toggleExecution: true);
|
||||
|
||||
if (package == null) return;
|
||||
|
||||
tappedHandlingFlag = true;
|
||||
|
||||
HoverActionExecutedCommand?.Execute(package);
|
||||
}
|
||||
|
||||
private void ThreadHeaderTapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
// Due to CanDrag=True, outer expander doesn't get the click event and it doesn't expand. We expand here manually.
|
||||
// Also hover action button clicks will be delegated here after the execution runs.
|
||||
// We should not expand the thread if the reason we are here is for hover actions.
|
||||
|
||||
if (tappedHandlingFlag)
|
||||
{
|
||||
tappedHandlingFlag = false;
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConnectedExpander == null) return;
|
||||
|
||||
ConnectedExpander.IsExpanded = !ConnectedExpander.IsExpanded;
|
||||
}
|
||||
|
||||
private void FirstActionClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ExecuteHoverAction(LeftHoverAction);
|
||||
|
||||
@@ -1,17 +1,129 @@
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using CommunityToolkit.Diagnostics;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Hosting;
|
||||
using Windows.UI.Xaml.Markup;
|
||||
|
||||
namespace Wino.Controls
|
||||
{
|
||||
public class WinoExpander : Expander
|
||||
[ContentProperty(Name = nameof(Content))]
|
||||
public class WinoExpander : Control
|
||||
{
|
||||
private const string PART_HeaderGrid = "HeaderGrid";
|
||||
private const string PART_ContentAreaWrapper = "ContentAreaWrapper";
|
||||
private const string PART_ContentArea = "ContentArea";
|
||||
|
||||
private ContentControl HeaderGrid;
|
||||
private ContentControl ContentArea;
|
||||
private Grid ContentAreaWrapper;
|
||||
|
||||
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(nameof(Header), typeof(UIElement), typeof(WinoExpander), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(UIElement), typeof(WinoExpander), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register(nameof(IsExpanded), typeof(bool), typeof(WinoExpander), new PropertyMetadata(false, new PropertyChangedCallback(OnIsExpandedChanged)));
|
||||
public static readonly DependencyProperty TemplateSettingsProperty = DependencyProperty.Register(nameof(TemplateSettings), typeof(WinoExpanderTemplateSettings), typeof(WinoExpander), new PropertyMetadata(new WinoExpanderTemplateSettings()));
|
||||
|
||||
public UIElement Content
|
||||
{
|
||||
get { return (UIElement)GetValue(ContentProperty); }
|
||||
set { SetValue(ContentProperty, value); }
|
||||
}
|
||||
|
||||
public WinoExpanderTemplateSettings TemplateSettings
|
||||
{
|
||||
get { return (WinoExpanderTemplateSettings)GetValue(TemplateSettingsProperty); }
|
||||
set { SetValue(TemplateSettingsProperty, value); }
|
||||
}
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get { return (bool)GetValue(IsExpandedProperty); }
|
||||
set { SetValue(IsExpandedProperty, value); }
|
||||
}
|
||||
|
||||
public UIElement Header
|
||||
{
|
||||
get { return (UIElement)GetValue(HeaderProperty); }
|
||||
set { SetValue(HeaderProperty, value); }
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
if (GetTemplateChild("ExpanderHeader") is ToggleButton toggleButton)
|
||||
|
||||
HeaderGrid = GetTemplateChild(PART_HeaderGrid) as ContentControl;
|
||||
ContentAreaWrapper = GetTemplateChild(PART_ContentAreaWrapper) as Grid;
|
||||
ContentArea = GetTemplateChild(PART_ContentArea) as ContentControl;
|
||||
|
||||
Guard.IsNotNull(HeaderGrid, nameof(HeaderGrid));
|
||||
Guard.IsNotNull(ContentAreaWrapper, nameof(ContentAreaWrapper));
|
||||
Guard.IsNotNull(ContentArea, nameof(ContentArea));
|
||||
|
||||
var clipComposition = ElementCompositionPreview.GetElementVisual(ContentAreaWrapper);
|
||||
clipComposition.Clip = clipComposition.Compositor.CreateInsetClip();
|
||||
|
||||
ContentAreaWrapper.SizeChanged += ContentSizeChanged;
|
||||
HeaderGrid.Tapped += HeaderTapped;
|
||||
}
|
||||
|
||||
private void ContentSizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
TemplateSettings.ContentHeight = e.NewSize.Height;
|
||||
TemplateSettings.NegativeContentHeight = -1 * (double)e.NewSize.Height;
|
||||
}
|
||||
|
||||
private void HeaderTapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
|
||||
{
|
||||
// Tapped is delegated from executing hover action like flag or delete.
|
||||
// No need to toggle the expander.
|
||||
|
||||
if (Header is MailItemDisplayInformationControl itemDisplayInformationControl &&
|
||||
itemDisplayInformationControl.IsRunningHoverAction)
|
||||
{
|
||||
toggleButton.Padding = new Windows.UI.Xaml.Thickness(0, 4, 0, 4);
|
||||
itemDisplayInformationControl.IsRunningHoverAction = false;
|
||||
return;
|
||||
}
|
||||
|
||||
IsExpanded = !IsExpanded;
|
||||
}
|
||||
|
||||
private static void OnIsExpandedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is WinoExpander control)
|
||||
control.UpdateVisualStates();
|
||||
}
|
||||
|
||||
private void UpdateVisualStates()
|
||||
{
|
||||
VisualStateManager.GoToState(this, IsExpanded ? "Expanded" : "Collapsed", true);
|
||||
}
|
||||
}
|
||||
|
||||
#region Settings
|
||||
|
||||
public class WinoExpanderTemplateSettings : DependencyObject
|
||||
{
|
||||
public static readonly DependencyProperty HeaderHeightProperty = DependencyProperty.Register(nameof(HeaderHeight), typeof(double), typeof(WinoExpanderTemplateSettings), new PropertyMetadata(0.0));
|
||||
public static readonly DependencyProperty ContentHeightProperty = DependencyProperty.Register(nameof(ContentHeight), typeof(double), typeof(WinoExpanderTemplateSettings), new PropertyMetadata(0.0));
|
||||
public static readonly DependencyProperty NegativeContentHeightProperty = DependencyProperty.Register(nameof(NegativeContentHeight), typeof(double), typeof(WinoExpanderTemplateSettings), new PropertyMetadata(0.0));
|
||||
|
||||
public double NegativeContentHeight
|
||||
{
|
||||
get { return (double)GetValue(NegativeContentHeightProperty); }
|
||||
set { SetValue(NegativeContentHeightProperty, value); }
|
||||
}
|
||||
|
||||
public double HeaderHeight
|
||||
{
|
||||
get { return (double)GetValue(HeaderHeightProperty); }
|
||||
set { SetValue(HeaderHeightProperty, value); }
|
||||
}
|
||||
|
||||
public double ContentHeight
|
||||
{
|
||||
get { return (double)GetValue(ContentHeightProperty); }
|
||||
set { SetValue(ContentHeightProperty, value); }
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -93,7 +93,8 @@ namespace Wino.Extensions
|
||||
|
||||
if (isVerticalScrolling)
|
||||
{
|
||||
scrollViewer.ChangeView(null, position.Y, zoomFactor, !smoothScrolling);
|
||||
// Accomodate for additional header.
|
||||
scrollViewer.ChangeView(null, Math.Max(0, position.Y - 48), zoomFactor, !smoothScrolling);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
89
Wino.Mail/Styles/WinoExpanderStyle.xaml
Normal file
89
Wino.Mail/Styles/WinoExpanderStyle.xaml
Normal file
@@ -0,0 +1,89 @@
|
||||
<ResourceDictionary
|
||||
x:Class="Wino.Styles.WinoExpanderStyle"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
|
||||
xmlns:controls="using:Wino.Controls"
|
||||
xmlns:local="using:Wino.Styles"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls">
|
||||
|
||||
<ControlTemplate x:Key="DefaultWinoThreadControlTemplate" TargetType="controls:WinoExpander">
|
||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header -->
|
||||
<ContentControl
|
||||
x:Name="HeaderGrid"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Background="{TemplateBinding Background}"
|
||||
Content="{TemplateBinding Header}" />
|
||||
|
||||
<!-- Content -->
|
||||
<Grid x:Name="ContentAreaWrapper" Grid.Row="1">
|
||||
<ContentControl
|
||||
x:Name="ContentArea"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Content="{TemplateBinding Content}"
|
||||
RenderTransformOrigin="0.5,0.5"
|
||||
Visibility="Collapsed">
|
||||
<ContentControl.RenderTransform>
|
||||
<CompositeTransform />
|
||||
</ContentControl.RenderTransform>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="OpenCloseStates">
|
||||
<VisualState x:Name="Collapsed">
|
||||
<VisualState.Storyboard>
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentArea" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0.111" Value="Collapsed" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentArea" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0" Value="0" />
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="1.0, 1.0, 0.0, 1.0"
|
||||
KeyTime="0:0:0.111"
|
||||
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.NegativeContentHeight}" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState.Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Expanded">
|
||||
<VisualState.Storyboard>
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentArea" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentArea" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.NegativeContentHeight}" />
|
||||
<SplineDoubleKeyFrame
|
||||
KeySpline="0.0, 0.0, 0.0, 1.0"
|
||||
KeyTime="0:0:0.333"
|
||||
Value="0" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState.Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<Style TargetType="controls:WinoExpander">
|
||||
<Setter Property="Background" Value="{ThemeResource AppBarItemBackgroundThemeBrush}" />
|
||||
<Setter Property="Template" Value="{StaticResource DefaultWinoThreadControlTemplate}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
12
Wino.Mail/Styles/WinoExpanderStyle.xaml.cs
Normal file
12
Wino.Mail/Styles/WinoExpanderStyle.xaml.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace Wino.Styles
|
||||
{
|
||||
partial class WinoExpanderStyle : ResourceDictionary
|
||||
{
|
||||
public WinoExpanderStyle()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,18 +169,14 @@
|
||||
<DataTemplate x:DataType="viewModelData:ThreadMailItemViewModel">
|
||||
<controls:WinoExpander
|
||||
x:Name="ThreadExpander"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
BackgroundSizing="InnerBorderEdge"
|
||||
BorderThickness="0"
|
||||
IsExpanded="{x:Bind IsThreadExpanded, Mode=TwoWay}">
|
||||
<muxc:Expander.Header>
|
||||
<controls:WinoExpander.Header>
|
||||
<controls:MailItemDisplayInformationControl
|
||||
x:DefaultBindMode="OneWay"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
CanDrag="True"
|
||||
CenterHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.CenterHoverAction, Mode=OneWay}"
|
||||
ConnectedExpander="{Binding ElementName=ThreadExpander}"
|
||||
ContextRequested="MailItemContextRequested"
|
||||
@@ -191,13 +187,15 @@
|
||||
IsAvatarVisible="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowSenderPicturesEnabled, Mode=OneWay}"
|
||||
IsHitTestVisible="True"
|
||||
IsHoverActionsEnabled="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsHoverActionsEnabled, Mode=OneWay}"
|
||||
IsThreadExpanded="{x:Bind IsThreadExpanded, Mode=TwoWay}"
|
||||
IsThreadExpanderVisible="True"
|
||||
LeftHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.LeftHoverAction, Mode=OneWay}"
|
||||
MailItem="{x:Bind MailItem, Mode=OneWay}"
|
||||
Prefer24HourTimeFormat="{Binding ElementName=root, Path=ViewModel.PreferencesService.Prefer24HourTimeFormat, Mode=OneWay}"
|
||||
RightHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.RightHoverAction, Mode=OneWay}"
|
||||
ShowPreviewText="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowPreviewEnabled, Mode=OneWay}" />
|
||||
</muxc:Expander.Header>
|
||||
<muxc:Expander.Content>
|
||||
</controls:WinoExpander.Header>
|
||||
<controls:WinoExpander.Content>
|
||||
<listview:WinoListView
|
||||
x:Name="ThreadItemsList"
|
||||
ui:ListViewExtensions.ItemContainerStretchDirection="Horizontal"
|
||||
@@ -212,7 +210,7 @@
|
||||
</TransitionCollection>
|
||||
</ListView.ItemContainerTransitions>
|
||||
</listview:WinoListView>
|
||||
</muxc:Expander.Content>
|
||||
</controls:WinoExpander.Content>
|
||||
</controls:WinoExpander>
|
||||
</DataTemplate>
|
||||
</selectors:MailItemDisplaySelector.ThreadMailItemTemplate>
|
||||
@@ -261,7 +259,8 @@
|
||||
<Border
|
||||
x:Name="MailListContainer"
|
||||
Grid.Column="0"
|
||||
Padding="5,5,5,0"
|
||||
Padding="5,0,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{ThemeResource WinoContentZoneBackgroud}"
|
||||
BorderBrush="{StaticResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
@@ -463,6 +462,7 @@
|
||||
<SemanticZoom.ZoomedInView>
|
||||
<listview:WinoListView
|
||||
x:Name="MailListView"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
ui:ListViewExtensions.ItemContainerStretchDirection="Horizontal"
|
||||
ui:ScrollViewerExtensions.EnableMiddleClickScrolling="True"
|
||||
|
||||
@@ -311,6 +311,9 @@
|
||||
<Compile Include="Styles\CustomMessageDialogStyles.xaml.cs">
|
||||
<DependentUpon>CustomMessageDialogStyles.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Styles\WinoExpanderStyle.xaml.cs">
|
||||
<DependentUpon>WinoExpanderStyle.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Abstract\AboutPageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\AccountDetailsPageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\AccountManagementPageAbstract.cs" />
|
||||
@@ -527,6 +530,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Styles\WinoExpanderStyle.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Styles\WinoInfoBar.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
Reference in New Issue
Block a user