-
Notifications
You must be signed in to change notification settings - Fork 757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/filesavepicker #3380
Feat/filesavepicker #3380
Changes from all commits
60d6b71
28c588e
badbfd6
c4740ab
243ea44
1e03ea3
2ff0bae
0c18226
351610b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<Page | ||
x:Class="UITests.Shared.Windows_Storage.FilePickers.FileSavePickerTest" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
mc:Ignorable="d" | ||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> | ||
|
||
<StackPanel> | ||
<Button Content="Save pdf" Click="SavePdfButton_Click" Margin="0,10,10,0"/> | ||
<Button Content="Save image" Click="SaveImgButton_Click" Margin="0,10,10,0"/> | ||
<Button Content="Save txt" Click="SaveTxtButton_Click" Margin="0,10,10,0"/> | ||
|
||
<TextBlock Text="File name:"/> | ||
<TextBlock x:Name="FileName"/> | ||
|
||
<TextBlock Text="File path:" /> | ||
<TextBlock x:Name="FilePath"/> | ||
|
||
<TextBlock Text="File Status:" /> | ||
<TextBlock x:Name="FileUpdateStatus"/> | ||
|
||
<TextBlock Text="Action output:"/> | ||
<TextBlock x:Name="OutputTextBlock"/> | ||
|
||
</StackPanel> | ||
|
||
</Page> |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
namespace Windows.Storage.Pickers { | ||
|
||
export class FileSavePicker { | ||
public static SaveAs(fileName: string, dataPtr: any, size: number): void { | ||
|
||
var buffer = new Uint8Array(size); | ||
|
||
for (var i = 0; i < size; i++) { | ||
buffer[i] = Module.getValue(dataPtr + i, "i8"); | ||
} | ||
|
||
var a = window.document.createElement('a'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Codacy found an issue: Identifier 'a' is never reassigned; use 'const' instead of 'var'. |
||
var blob = new Blob([buffer]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Codacy found an issue: Identifier 'blob' is never reassigned; use 'const' instead of 'var'. |
||
|
||
a.href = window.URL.createObjectURL(blob); | ||
a.download = fileName; | ||
|
||
document.body.appendChild(a); | ||
a.click(); | ||
document.body.removeChild(a); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#if __ANDROID__ | ||
using Android.App; | ||
using Android.Content; | ||
|
||
namespace Uno | ||
{ | ||
/// <summary> | ||
/// OnActivityResultArgs : an object containing the parameters of the Activity.OnActivityResult | ||
/// </summary> | ||
/// <param name="ct">CancellationToken</param> | ||
/// <param name="intent">The Intent you want to send</param> | ||
/// <param name="requestCode">A specific Response code, this is useful if you send more than one type of request in parallel</param> | ||
public class ActivityResultArgs | ||
{ | ||
public ActivityResultArgs(int requestCode, Result resultCode, Intent intent) | ||
{ | ||
RequestCode = requestCode; | ||
ResultCode = resultCode; | ||
Intent = intent; | ||
} | ||
public Intent Intent { get; } | ||
|
||
public int RequestCode { get; } | ||
|
||
public Result ResultCode { get; } | ||
} | ||
} | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
#if __ANDROID__ | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
using Android.App; | ||
using Android.Content; | ||
using Android.Content.PM; | ||
using Uno.UI; | ||
|
||
namespace Uno | ||
{ | ||
|
||
[Activity(ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)] | ||
public class AsyncActivity : Activity | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to be internal |
||
{ | ||
// Some devices (Galaxy S4) use a second activity to get the result. | ||
// This dictionary is used to keep track of the original activities that requests the values. | ||
private static readonly Dictionary<int, AsyncActivity> _originalActivities = new Dictionary<int, AsyncActivity>(); | ||
private readonly TaskCompletionSource<OnActivityResultArgs> _completionSource = new TaskCompletionSource<OnActivityResultArgs>(); | ||
private static event Action<AsyncActivity> Handler; | ||
|
||
public int RequestCode { get; private set; } | ||
|
||
public AsyncActivity() { } | ||
|
||
protected override void OnResume() | ||
{ | ||
base.OnResume(); | ||
|
||
Handler?.Invoke(this); | ||
} | ||
|
||
public static async Task<T> InitialiseActivity<T>(Intent intent, int requestCode = 0) where T : AsyncActivity | ||
{ | ||
var finished = new TaskCompletionSource<AsyncActivity>(); | ||
|
||
var taskCompletionSource = new TaskCompletionSource<AsyncActivity>(); | ||
void handler(AsyncActivity instance) => taskCompletionSource.TrySetResult(instance); | ||
|
||
try | ||
{ | ||
Handler += handler; | ||
ContextHelper.Current.StartActivity(typeof(T)); | ||
|
||
var result = await taskCompletionSource.Task as T; | ||
result.RequestCode = requestCode; | ||
result.Intent = intent; | ||
return result; | ||
} | ||
finally | ||
{ | ||
Handler -= handler; | ||
} | ||
} | ||
|
||
public async Task<OnActivityResultArgs> Start() | ||
{ | ||
try | ||
{ | ||
_originalActivities[RequestCode] = this; | ||
|
||
StartActivityForResult(Intent, RequestCode); | ||
|
||
//the Task that returns when OnActivityResult is called | ||
var result = await _completionSource.Task; | ||
return result; | ||
} | ||
finally | ||
{ | ||
Finish();//Close the activity | ||
_originalActivities.Remove(RequestCode); | ||
} | ||
} | ||
|
||
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent) | ||
{ | ||
base.OnActivityResult(requestCode, resultCode, intent); | ||
|
||
// Some devices (Galaxy S4) use a second activity to get the result. | ||
// In this case the current instance is not the same as the one that requested the value. | ||
// In this case we must get the original activity and use it's TaskCompletionSource instead of ours. | ||
var currentActivityIsANewOne = false; | ||
if (_originalActivities.TryGetValue(requestCode, out var originalActivity)) | ||
{ | ||
currentActivityIsANewOne = originalActivity != this; | ||
} | ||
else | ||
{ | ||
originalActivity = this; | ||
} | ||
|
||
if (currentActivityIsANewOne) | ||
{ | ||
// Finish this activity (because we are not the original) | ||
Finish(); | ||
} | ||
|
||
// Push a new OnActivityResultArgs in the calling activity | ||
if (originalActivity.RequestCode == requestCode) | ||
{ | ||
originalActivity._completionSource.TrySetResult(new OnActivityResultArgs(requestCode, resultCode, intent)); | ||
} | ||
} | ||
protected override void OnDestroy() | ||
{ | ||
base.OnDestroy(); | ||
|
||
//AsyncActivity could be destroyed by the system before receiving the result, | ||
//In such a case, we need to complete the _completionSource. In the normal flow, OnDestroy will | ||
//only be called after the _completionSource's Task has already RanToCompletion | ||
_completionSource?.TrySetResult(new OnActivityResultArgs(RequestCode, Result.Canceled, null)); | ||
} | ||
} | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Codacy found an issue: Identifier 'buffer' is never reassigned; use 'const' instead of 'var'.