Skip to content

Commit 9ca3bb0

Browse files
committed
Add export button to AttachmentsDetailsView
1 parent 34ad701 commit 9ca3bb0

File tree

8 files changed

+130
-30
lines changed

8 files changed

+130
-30
lines changed

Signal-Windows.Lib/SignalLibHandle.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public interface ISignalLibHandle
7676

7777
// Attachment API
7878
void StartAttachmentDownload(SignalAttachment sa);
79+
Task ExportAttachment(SignalAttachment sa);
7980
//void AbortAttachmentDownload(SignalAttachment sa); TODO
8081
}
8182

@@ -481,6 +482,39 @@ public void StartAttachmentDownload(SignalAttachment sa)
481482
}
482483
});
483484
}
485+
486+
public async Task ExportAttachment(SignalAttachment sa)
487+
{
488+
try
489+
{
490+
Logger.LogTrace("ExportAttachment() locking");
491+
await SemaphoreSlim.WaitAsync(CancelSource.Token);
492+
Logger.LogTrace("ExportAttachment() locked");
493+
var savePicker = new Windows.Storage.Pickers.FileSavePicker
494+
{
495+
SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Downloads,
496+
SuggestedFileName = sa.SentFileName ?? "signal"
497+
};
498+
savePicker.FileTypeChoices.Add("Any", new List<string>() { "." });
499+
var target_file = await savePicker.PickSaveFileAsync();
500+
if (target_file != null)
501+
{
502+
CachedFileManager.DeferUpdates(target_file);
503+
IStorageFile localCopy = await ApplicationData.Current.LocalCacheFolder.GetFileAsync($@"Attachments\{sa.Id}.plain");
504+
await localCopy.CopyAndReplaceAsync(target_file);
505+
Windows.Storage.Provider.FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(target_file);
506+
}
507+
}
508+
catch (Exception e)
509+
{
510+
Logger.LogError("ExportAttachment failed: {0}\n{1}", e.Message, e.StackTrace);
511+
}
512+
finally
513+
{
514+
SemaphoreSlim.Release();
515+
Logger.LogTrace("ExportAttachment() released");
516+
}
517+
}
484518
#endregion
485519

486520
#region internal api

Signal-Windows/Controls/ConversationListElement.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ private void ThreadListItem_DataContextChanged(FrameworkElement sender, DataCont
172172
UpdateBlockedContactElement();
173173
Model.UpdateUI = UpdateBlockedContactElement;
174174
}
175-
else if (frame.CurrentSourcePageType == typeof(MainPage))
175+
else
176176
{
177177
UpdateConversationDisplay();
178178
Model.UpdateUI = UpdateConversationDisplay;

Signal-Windows/ViewModels/GlobalSettingsPageViewModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Signal_Windows.Views;
66
using System;
77
using System.Collections.Generic;
8+
using System.Diagnostics;
89
using System.Linq;
910
using System.Text;
1011
using System.Threading.Tasks;

Signal-Windows/ViewModels/MainPageViewModel.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,62 @@ public SignalConversation SelectedConversation
6969
}
7070
}
7171

72+
private bool _IsPaneOpen = false;
73+
public bool IsPaneOpen
74+
{
75+
get => _IsPaneOpen;
76+
set
77+
{
78+
if (_IsPaneOpen != value)
79+
{
80+
_IsPaneOpen = value;
81+
RaisePropertyChanged(nameof(IsPaneOpen));
82+
}
83+
}
84+
}
85+
86+
private double _CompactPaneLength = 0;
87+
public double CompactPaneLength
88+
{
89+
get => _CompactPaneLength;
90+
set
91+
{
92+
if (_CompactPaneLength != value)
93+
{
94+
_CompactPaneLength = value;
95+
RaisePropertyChanged(nameof(CompactPaneLength));
96+
}
97+
}
98+
}
99+
100+
private double _OpenPaneLength = 320;
101+
public double OpenPaneLength
102+
{
103+
get => _OpenPaneLength;
104+
set
105+
{
106+
if (_OpenPaneLength != value)
107+
{
108+
_OpenPaneLength = value;
109+
RaisePropertyChanged(nameof(OpenPaneLength));
110+
}
111+
}
112+
}
113+
114+
private SplitViewDisplayMode _DisplayMode = SplitViewDisplayMode.CompactInline;
115+
public SplitViewDisplayMode DisplayMode
116+
{
117+
get => _DisplayMode;
118+
set
119+
{
120+
if (_DisplayMode != value)
121+
{
122+
_DisplayMode = value;
123+
RaisePropertyChanged(nameof(DisplayMode));
124+
}
125+
}
126+
}
127+
72128
internal void BackButton_Click(object sender, BackRequestedEventArgs e)
73129
{
74130
SelectedThread = null;

Signal-Windows/Views/AttachmentDetailsPage.xaml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@
66
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
77
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
88
mc:Ignorable="d"
9-
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
9+
Background="Black">
1010

1111
<!-- https://www.goedware.com/index.php/blog/3-pinch-zoom-image-in-uwp-app -->
12-
<FlipView Name="ImageFlipView" ItemsSource="{x:Bind Attachments}" Width="Auto" Height="Auto">
13-
<FlipView.ItemTemplate>
14-
<DataTemplate>
15-
<Image Source="{Binding}" />
16-
</DataTemplate>
17-
</FlipView.ItemTemplate>
18-
</FlipView>
19-
12+
<StackPanel>
13+
<Button Grid.Column="1" x:Name="ExportButton" Background="{x:Null}" Click="ExportButton_Click">
14+
<SymbolIcon Symbol="Save" Foreground="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
15+
</Button>
16+
<FlipView Name="ImageFlipView" ItemsSource="{x:Bind Attachments}" Width="Auto" Height="Auto">
17+
<FlipView.ItemTemplate>
18+
<DataTemplate>
19+
<Image Source="{Binding}" />
20+
</DataTemplate>
21+
</FlipView.ItemTemplate>
22+
</FlipView>
23+
</StackPanel>
2024
</Page>

Signal-Windows/Views/AttachmentDetailsPage.xaml.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Collections.Generic;
44
using System.Collections.ObjectModel;
5+
using System.Diagnostics;
56
using System.IO;
67
using System.Linq;
78
using System.Runtime.InteropServices.WindowsRuntime;
@@ -27,6 +28,7 @@ namespace Signal_Windows.Views
2728
public sealed partial class AttachmentDetailsPage : Page
2829
{
2930
public ObservableCollection<string> Attachments { get; set; } = new ObservableCollection<string>();
31+
private SignalAttachment Attachment;
3032

3133
public AttachmentDetailsPage()
3234
{
@@ -40,7 +42,8 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
4042
base.OnNavigatedTo(e);
4143
Utils.EnableBackButton(BackButton_Click);
4244
Attachments.Clear();
43-
Attachments.Add($"{ApplicationData.Current.LocalCacheFolder.Path}/Attachments/{(e.Parameter as SignalAttachment).Id}.plain");
45+
Attachment = e.Parameter as SignalAttachment;
46+
Attachments.Add($"{ApplicationData.Current.LocalCacheFolder.Path}/Attachments/{Attachment.Id}.plain");
4447
}
4548

4649
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
@@ -54,5 +57,10 @@ private void BackButton_Click(object sender, BackRequestedEventArgs e)
5457
Frame.GoBack();
5558
e.Handled = true;
5659
}
60+
61+
private async void ExportButton_Click(object sender, RoutedEventArgs e)
62+
{
63+
await App.Handle.ExportAttachment(Attachment);
64+
}
5765
}
5866
}

Signal-Windows/Views/MainPage.xaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
xmlns:viewmodels="using:Signal_Windows.ViewModels"
99
xmlns:controls="using:Signal_Windows.Controls"
1010
mc:Ignorable="d"
11+
NavigationCacheMode="Required"
1112
DataContext="{Binding MainPageInstance, Source={StaticResource Locator}}">
1213

1314
<Page.Resources>
@@ -24,7 +25,7 @@
2425
</ResourceDictionary.ThemeDictionaries>
2526
</ResourceDictionary>
2627
</Page.Resources>
27-
<SplitView Name="MainPanel" CompactPaneLength="0" OpenPaneLength="320" DisplayMode="CompactInline">
28+
<SplitView Name="MainPanel" IsPaneOpen="{x:Bind Vm.IsPaneOpen, Mode=OneWay}" CompactPaneLength="{x:Bind Vm.CompactPaneLength, Mode=OneWay}" OpenPaneLength="{x:Bind Vm.OpenPaneLength, Mode=OneWay}" DisplayMode="{x:Bind Vm.DisplayMode, Mode=OneWay}">
2829
<SplitView.Pane>
2930
<Grid x:Name="ContactsGrid">
3031
<Grid.RowDefinitions>
@@ -47,10 +48,10 @@
4748
</Button>
4849
</Grid>
4950
<AutoSuggestBox Grid.Row="1" Margin="16"/>
50-
<ListView Grid.Row="2" Name="ContactsList" ItemsSource="{x:Bind Vm.Conversations, Mode=TwoWay}" SelectionMode="Single" SelectionChanged="Vm.ConversationsList_SelectionChanged" SelectedItem="{x:Bind Vm.SelectedConversation, Mode=TwoWay}">
51+
<ListView Grid.Row="2" Name="ContactsList" ItemsSource="{x:Bind Vm.Conversations, Mode=TwoWay}" SelectionMode="Single" SelectionChanged="Vm.ConversationsList_SelectionChanged" SelectedItem="{x:Bind Vm.SelectedConversation, Mode=TwoWay}" VirtualizingStackPanel.VirtualizationMode="Recycling">
5152
<ListView.ItemsPanel>
5253
<ItemsPanelTemplate>
53-
<StackPanel></StackPanel>
54+
<VirtualizingStackPanel></VirtualizingStackPanel>
5455
</ItemsPanelTemplate>
5556
</ListView.ItemsPanel>
5657
<ListView.ItemContainerStyle>

Signal-Windows/Views/MainPage.xaml.cs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Signal_Windows.ViewModels;
77
using Signal_Windows.Views;
88
using System;
9+
using System.Diagnostics;
910
using System.Threading.Tasks;
1011
using Windows.Foundation;
1112
using Windows.UI.Popups;
@@ -38,20 +39,20 @@ public void SwitchToStyle(PageStyle newStyle)
3839
if (Vm.SelectedThread != null)
3940
{
4041
Utils.EnableBackButton(Vm.BackButton_Click);
41-
MainPanel.IsPaneOpen = false;
42-
MainPanel.CompactPaneLength = 0;
42+
Vm.IsPaneOpen = false;
43+
Vm.CompactPaneLength = 0;
4344
}
4445
else
4546
{
4647
Unselect();
47-
MainPanel.IsPaneOpen = true;
48+
Vm.IsPaneOpen = true;
4849
}
4950
}
5051
else if (newStyle == PageStyle.Wide)
5152
{
5253
Utils.DisableBackButton(Vm.BackButton_Click);
53-
MainPanel.IsPaneOpen = false;
54-
MainPanel.CompactPaneLength = ContactsGrid.Width = 320;
54+
Vm.IsPaneOpen = false;
55+
Vm.CompactPaneLength = ContactsGrid.Width = 320;
5556
}
5657
UpdateStyle(newStyle);
5758
}
@@ -62,39 +63,34 @@ private void UpdateStyle(PageStyle currentStyle)
6263
{
6364
// TODO: When phone is in landscape mode this is incorrect and some stuff gets cut off, we need to
6465
// get the actual useable width (actualwidth - top icon bar - bottom control bar)
65-
ContactsGrid.Width = ActualWidth;
66+
ContactsGrid.Width = Frame.ActualWidth;
6667
if (Vm.SelectedThread == null)
6768
{
68-
MainPanel.OpenPaneLength = ActualWidth;
69+
Vm.OpenPaneLength = Frame.ActualWidth;
6970
}
7071
}
7172
else if (currentStyle == PageStyle.Wide)
7273
{
73-
MainPanel.CompactPaneLength = MainPanel.OpenPaneLength = ContactsGrid.Width = 320;
74+
Vm.CompactPaneLength = Vm.OpenPaneLength = ContactsGrid.Width = 320;
7475
}
7576
}
7677

7778
public PageStyle GetCurrentViewStyle()
7879
{
79-
return Utils.GetViewStyle(new Size(ActualWidth, ActualHeight));
80+
return Utils.GetViewStyle(new Size(Frame.ActualWidth, ActualHeight));
8081
}
8182

8283
protected override void OnNavigatedTo(NavigationEventArgs e)
8384
{
84-
if (e.Parameter != null)
85-
{
86-
Vm.RequestedConversationId = e.Parameter as string;
87-
}
88-
UpdateLayout();
85+
Vm.RequestedConversationId = e.Parameter as string;
8986
SwitchToStyle(GetCurrentViewStyle());
90-
MainPanel.DisplayMode = SplitViewDisplayMode.CompactInline;
87+
Vm.DisplayMode = SplitViewDisplayMode.CompactInline;
9188
Frame.SizeChanged += Frame_SizeChanged;
9289
Vm.TrySelectConversation(Vm.RequestedConversationId);
9390
}
9491

9592
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
9693
{
97-
Vm.Deselect();
9894
Frame.SizeChanged -= Frame_SizeChanged;
9995
if (GetCurrentViewStyle() == PageStyle.Narrow)
10096
{

0 commit comments

Comments
 (0)