mirror of
https://github.com/bitwarden/mobile.git
synced 2024-11-22 11:35:21 +01:00
New Android attachment handling to support saving or opening attachments (#751)
* New Android attachment handling to support saving or opening (when available) attachments * Simplified options dialog logic & changed error text
This commit is contained in:
parent
70c49922b0
commit
2b1d186611
@ -230,15 +230,8 @@ namespace Bit.Droid.Services
|
||||
string mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(extension);
|
||||
if(mimeType == null)
|
||||
{
|
||||
if(extension == "json")
|
||||
{
|
||||
// Explicit support for json since older versions of Android don't recognize the extension
|
||||
mimeType = "text/json";
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Unable to identify so fall back to generic "any" type
|
||||
mimeType = "*/*";
|
||||
}
|
||||
|
||||
var intent = new Intent(Intent.ActionCreateDocument);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.App.Resources;
|
||||
using System;
|
||||
using Bit.App.Resources;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using System.Collections.Generic;
|
||||
@ -76,6 +77,18 @@ namespace Bit.App.Pages
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(message.Command == "selectSaveFileResult")
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
var data = message.Data as Tuple<string, string>;
|
||||
if(data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_vm.SaveFileSelected(data.Item1, data.Item2);
|
||||
});
|
||||
}
|
||||
});
|
||||
await LoadOnAppearedAsync(_scrollView, true, async () =>
|
||||
{
|
||||
|
@ -34,6 +34,8 @@ namespace Bit.App.Pages
|
||||
private bool _totpLow;
|
||||
private DateTime? _totpInterval = null;
|
||||
private string _previousCipherId;
|
||||
private byte[] _attachmentData;
|
||||
private string _attachmentFilename;
|
||||
|
||||
public ViewPageViewModel()
|
||||
{
|
||||
@ -405,10 +407,19 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var canOpenFile = true;
|
||||
if(!_deviceActionService.CanOpenFile(attachment.FileName))
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToOpenFile);
|
||||
return;
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
// iOS is currently hardcoded to always return CanOpenFile == true, but should it ever return false
|
||||
// for any reason we want to be sure to catch it here.
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToOpenFile);
|
||||
return;
|
||||
}
|
||||
|
||||
canOpenFile = false;
|
||||
}
|
||||
|
||||
await _deviceActionService.ShowLoadingAsync(AppResources.Downloading);
|
||||
@ -421,10 +432,23 @@ namespace Bit.App.Pages
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToDownloadFile);
|
||||
return;
|
||||
}
|
||||
if(!_deviceActionService.OpenFile(data, attachment.Id, attachment.FileName))
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToOpenFile);
|
||||
return;
|
||||
if(canOpenFile)
|
||||
{
|
||||
// We can open this attachment directly, so give the user the option to open or save
|
||||
PromptOpenOrSave(data, attachment);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We can't open this attachment so go directly to save
|
||||
SaveAttachment(data, attachment);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OpenAttachment(data, attachment);
|
||||
}
|
||||
}
|
||||
catch
|
||||
@ -433,6 +457,59 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
|
||||
public async void PromptOpenOrSave(byte[] data, AttachmentView attachment)
|
||||
{
|
||||
var selection = await Page.DisplayActionSheet(attachment.FileName, AppResources.Cancel, null,
|
||||
AppResources.Open, AppResources.Save);
|
||||
if(selection == AppResources.Open)
|
||||
{
|
||||
OpenAttachment(data, attachment);
|
||||
}
|
||||
else if(selection == AppResources.Save)
|
||||
{
|
||||
SaveAttachment(data, attachment);
|
||||
}
|
||||
}
|
||||
|
||||
public async void OpenAttachment(byte[] data, AttachmentView attachment)
|
||||
{
|
||||
if(!_deviceActionService.OpenFile(data, attachment.Id, attachment.FileName))
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToOpenFile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public async void SaveAttachment(byte[] data, AttachmentView attachment)
|
||||
{
|
||||
_attachmentData = data;
|
||||
_attachmentFilename = attachment.FileName;
|
||||
if(!_deviceActionService.SaveFile(_attachmentData, null, _attachmentFilename, null))
|
||||
{
|
||||
ClearAttachmentData();
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToSaveAttachment);
|
||||
}
|
||||
}
|
||||
|
||||
public async void SaveFileSelected(string contentUri, string filename)
|
||||
{
|
||||
if(_deviceActionService.SaveFile(_attachmentData, null, filename ?? _attachmentFilename, contentUri))
|
||||
{
|
||||
ClearAttachmentData();
|
||||
_platformUtilsService.ShowToast("success", null, AppResources.SaveAttachmentSuccess);
|
||||
return;
|
||||
}
|
||||
|
||||
ClearAttachmentData();
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToSaveAttachment);
|
||||
}
|
||||
|
||||
private void ClearAttachmentData()
|
||||
{
|
||||
_attachmentData = null;
|
||||
_attachmentFilename = null;
|
||||
}
|
||||
|
||||
private async void CopyAsync(string id, string text = null)
|
||||
{
|
||||
string name = null;
|
||||
|
18
src/App/Resources/AppResources.Designer.cs
generated
18
src/App/Resources/AppResources.Designer.cs
generated
@ -2841,5 +2841,23 @@ namespace Bit.App.Resources {
|
||||
return ResourceManager.GetString("PasswordGeneratorPolicyInEffect", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
public static string Open {
|
||||
get {
|
||||
return ResourceManager.GetString("Open", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
public static string UnableToSaveAttachment {
|
||||
get {
|
||||
return ResourceManager.GetString("UnableToSaveAttachment", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
public static string SaveAttachmentSuccess {
|
||||
get {
|
||||
return ResourceManager.GetString("SaveAttachmentSuccess", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1615,4 +1615,14 @@
|
||||
<data name="PasswordGeneratorPolicyInEffect" xml:space="preserve">
|
||||
<value>One or more organization policies are affecting your generator settings</value>
|
||||
</data>
|
||||
<data name="Open" xml:space="preserve">
|
||||
<value>Open</value>
|
||||
<comment>Button text for an open operation (verb).</comment>
|
||||
</data>
|
||||
<data name="UnableToSaveAttachment" xml:space="preserve">
|
||||
<value>There was a problem saving this attachment. If the problem persists, you can save it from the web vault.</value>
|
||||
</data>
|
||||
<data name="SaveAttachmentSuccess" xml:space="preserve">
|
||||
<value>Attachment saved successfully</value>
|
||||
</data>
|
||||
</root>
|
Loading…
Reference in New Issue
Block a user