diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj
index 030c56350..b8bf69266 100644
--- a/src/Android/Android.csproj
+++ b/src/Android/Android.csproj
@@ -875,6 +875,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Android/Resources/Resource.Designer.cs b/src/Android/Resources/Resource.Designer.cs
index 553e91046..7c2708678 100644
--- a/src/Android/Resources/Resource.Designer.cs
+++ b/src/Android/Resources/Resource.Designer.cs
@@ -2436,361 +2436,364 @@ namespace Bit.Android
public const int design_snackbar_background = 2130837629;
// aapt resource value: 0x7f02007e
- public const int envelope = 2130837630;
+ public const int download = 2130837630;
// aapt resource value: 0x7f02007f
- public const int eye = 2130837631;
+ public const int envelope = 2130837631;
// aapt resource value: 0x7f020080
- public const int eye_slash = 2130837632;
+ public const int eye = 2130837632;
// aapt resource value: 0x7f020081
- public const int fa_lock = 2130837633;
+ public const int eye_slash = 2130837633;
// aapt resource value: 0x7f020082
- public const int fa_lock_selected = 2130837634;
+ public const int fa_lock = 2130837634;
// aapt resource value: 0x7f020083
- public const int fingerprint = 2130837635;
+ public const int fa_lock_selected = 2130837635;
// aapt resource value: 0x7f020084
- public const int fingerprint_white = 2130837636;
+ public const int fingerprint = 2130837636;
// aapt resource value: 0x7f020085
- public const int folder = 2130837637;
+ public const int fingerprint_white = 2130837637;
// aapt resource value: 0x7f020086
- public const int globe = 2130837638;
+ public const int folder = 2130837638;
// aapt resource value: 0x7f020087
- public const int hockeyapp_btn_background = 2130837639;
+ public const int globe = 2130837639;
// aapt resource value: 0x7f020088
- public const int ic_audiotrack = 2130837640;
+ public const int hockeyapp_btn_background = 2130837640;
// aapt resource value: 0x7f020089
- public const int ic_audiotrack_light = 2130837641;
+ public const int ic_audiotrack = 2130837641;
// aapt resource value: 0x7f02008a
- public const int ic_bluetooth_grey = 2130837642;
+ public const int ic_audiotrack_light = 2130837642;
// aapt resource value: 0x7f02008b
- public const int ic_bluetooth_white = 2130837643;
+ public const int ic_bluetooth_grey = 2130837643;
// aapt resource value: 0x7f02008c
- public const int ic_cast_dark = 2130837644;
+ public const int ic_bluetooth_white = 2130837644;
// aapt resource value: 0x7f02008d
- public const int ic_cast_disabled_light = 2130837645;
+ public const int ic_cast_dark = 2130837645;
// aapt resource value: 0x7f02008e
- public const int ic_cast_grey = 2130837646;
+ public const int ic_cast_disabled_light = 2130837646;
// aapt resource value: 0x7f02008f
- public const int ic_cast_light = 2130837647;
+ public const int ic_cast_grey = 2130837647;
// aapt resource value: 0x7f020090
- public const int ic_cast_off_light = 2130837648;
+ public const int ic_cast_light = 2130837648;
// aapt resource value: 0x7f020091
- public const int ic_cast_on_0_light = 2130837649;
+ public const int ic_cast_off_light = 2130837649;
// aapt resource value: 0x7f020092
- public const int ic_cast_on_1_light = 2130837650;
+ public const int ic_cast_on_0_light = 2130837650;
// aapt resource value: 0x7f020093
- public const int ic_cast_on_2_light = 2130837651;
+ public const int ic_cast_on_1_light = 2130837651;
// aapt resource value: 0x7f020094
- public const int ic_cast_on_light = 2130837652;
+ public const int ic_cast_on_2_light = 2130837652;
// aapt resource value: 0x7f020095
- public const int ic_cast_white = 2130837653;
+ public const int ic_cast_on_light = 2130837653;
// aapt resource value: 0x7f020096
- public const int ic_close_dark = 2130837654;
+ public const int ic_cast_white = 2130837654;
// aapt resource value: 0x7f020097
- public const int ic_close_light = 2130837655;
+ public const int ic_close_dark = 2130837655;
// aapt resource value: 0x7f020098
- public const int ic_collapse = 2130837656;
+ public const int ic_close_light = 2130837656;
// aapt resource value: 0x7f020099
- public const int ic_collapse_00000 = 2130837657;
+ public const int ic_collapse = 2130837657;
// aapt resource value: 0x7f02009a
- public const int ic_collapse_00001 = 2130837658;
+ public const int ic_collapse_00000 = 2130837658;
// aapt resource value: 0x7f02009b
- public const int ic_collapse_00002 = 2130837659;
+ public const int ic_collapse_00001 = 2130837659;
// aapt resource value: 0x7f02009c
- public const int ic_collapse_00003 = 2130837660;
+ public const int ic_collapse_00002 = 2130837660;
// aapt resource value: 0x7f02009d
- public const int ic_collapse_00004 = 2130837661;
+ public const int ic_collapse_00003 = 2130837661;
// aapt resource value: 0x7f02009e
- public const int ic_collapse_00005 = 2130837662;
+ public const int ic_collapse_00004 = 2130837662;
// aapt resource value: 0x7f02009f
- public const int ic_collapse_00006 = 2130837663;
+ public const int ic_collapse_00005 = 2130837663;
// aapt resource value: 0x7f0200a0
- public const int ic_collapse_00007 = 2130837664;
+ public const int ic_collapse_00006 = 2130837664;
// aapt resource value: 0x7f0200a1
- public const int ic_collapse_00008 = 2130837665;
+ public const int ic_collapse_00007 = 2130837665;
// aapt resource value: 0x7f0200a2
- public const int ic_collapse_00009 = 2130837666;
+ public const int ic_collapse_00008 = 2130837666;
// aapt resource value: 0x7f0200a3
- public const int ic_collapse_00010 = 2130837667;
+ public const int ic_collapse_00009 = 2130837667;
// aapt resource value: 0x7f0200a4
- public const int ic_collapse_00011 = 2130837668;
+ public const int ic_collapse_00010 = 2130837668;
// aapt resource value: 0x7f0200a5
- public const int ic_collapse_00012 = 2130837669;
+ public const int ic_collapse_00011 = 2130837669;
// aapt resource value: 0x7f0200a6
- public const int ic_collapse_00013 = 2130837670;
+ public const int ic_collapse_00012 = 2130837670;
// aapt resource value: 0x7f0200a7
- public const int ic_collapse_00014 = 2130837671;
+ public const int ic_collapse_00013 = 2130837671;
// aapt resource value: 0x7f0200a8
- public const int ic_collapse_00015 = 2130837672;
+ public const int ic_collapse_00014 = 2130837672;
// aapt resource value: 0x7f0200a9
- public const int ic_errorstatus = 2130837673;
+ public const int ic_collapse_00015 = 2130837673;
// aapt resource value: 0x7f0200aa
- public const int ic_expand = 2130837674;
+ public const int ic_errorstatus = 2130837674;
// aapt resource value: 0x7f0200ab
- public const int ic_expand_00000 = 2130837675;
+ public const int ic_expand = 2130837675;
// aapt resource value: 0x7f0200ac
- public const int ic_expand_00001 = 2130837676;
+ public const int ic_expand_00000 = 2130837676;
// aapt resource value: 0x7f0200ad
- public const int ic_expand_00002 = 2130837677;
+ public const int ic_expand_00001 = 2130837677;
// aapt resource value: 0x7f0200ae
- public const int ic_expand_00003 = 2130837678;
+ public const int ic_expand_00002 = 2130837678;
// aapt resource value: 0x7f0200af
- public const int ic_expand_00004 = 2130837679;
+ public const int ic_expand_00003 = 2130837679;
// aapt resource value: 0x7f0200b0
- public const int ic_expand_00005 = 2130837680;
+ public const int ic_expand_00004 = 2130837680;
// aapt resource value: 0x7f0200b1
- public const int ic_expand_00006 = 2130837681;
+ public const int ic_expand_00005 = 2130837681;
// aapt resource value: 0x7f0200b2
- public const int ic_expand_00007 = 2130837682;
+ public const int ic_expand_00006 = 2130837682;
// aapt resource value: 0x7f0200b3
- public const int ic_expand_00008 = 2130837683;
+ public const int ic_expand_00007 = 2130837683;
// aapt resource value: 0x7f0200b4
- public const int ic_expand_00009 = 2130837684;
+ public const int ic_expand_00008 = 2130837684;
// aapt resource value: 0x7f0200b5
- public const int ic_expand_00010 = 2130837685;
+ public const int ic_expand_00009 = 2130837685;
// aapt resource value: 0x7f0200b6
- public const int ic_expand_00011 = 2130837686;
+ public const int ic_expand_00010 = 2130837686;
// aapt resource value: 0x7f0200b7
- public const int ic_expand_00012 = 2130837687;
+ public const int ic_expand_00011 = 2130837687;
// aapt resource value: 0x7f0200b8
- public const int ic_expand_00013 = 2130837688;
+ public const int ic_expand_00012 = 2130837688;
// aapt resource value: 0x7f0200b9
- public const int ic_expand_00014 = 2130837689;
+ public const int ic_expand_00013 = 2130837689;
// aapt resource value: 0x7f0200ba
- public const int ic_expand_00015 = 2130837690;
+ public const int ic_expand_00014 = 2130837690;
// aapt resource value: 0x7f0200bb
- public const int ic_media_pause = 2130837691;
+ public const int ic_expand_00015 = 2130837691;
// aapt resource value: 0x7f0200bc
- public const int ic_media_play = 2130837692;
+ public const int ic_media_pause = 2130837692;
// aapt resource value: 0x7f0200bd
- public const int ic_media_route_disabled_mono_dark = 2130837693;
+ public const int ic_media_play = 2130837693;
// aapt resource value: 0x7f0200be
- public const int ic_media_route_off_mono_dark = 2130837694;
+ public const int ic_media_route_disabled_mono_dark = 2130837694;
// aapt resource value: 0x7f0200bf
- public const int ic_media_route_on_0_mono_dark = 2130837695;
+ public const int ic_media_route_off_mono_dark = 2130837695;
// aapt resource value: 0x7f0200c0
- public const int ic_media_route_on_1_mono_dark = 2130837696;
+ public const int ic_media_route_on_0_mono_dark = 2130837696;
// aapt resource value: 0x7f0200c1
- public const int ic_media_route_on_2_mono_dark = 2130837697;
+ public const int ic_media_route_on_1_mono_dark = 2130837697;
// aapt resource value: 0x7f0200c2
- public const int ic_media_route_on_mono_dark = 2130837698;
+ public const int ic_media_route_on_2_mono_dark = 2130837698;
// aapt resource value: 0x7f0200c3
- public const int ic_pause_dark = 2130837699;
+ public const int ic_media_route_on_mono_dark = 2130837699;
// aapt resource value: 0x7f0200c4
- public const int ic_pause_light = 2130837700;
+ public const int ic_pause_dark = 2130837700;
// aapt resource value: 0x7f0200c5
- public const int ic_play_dark = 2130837701;
+ public const int ic_pause_light = 2130837701;
// aapt resource value: 0x7f0200c6
- public const int ic_play_light = 2130837702;
+ public const int ic_play_dark = 2130837702;
// aapt resource value: 0x7f0200c7
- public const int ic_speaker_dark = 2130837703;
+ public const int ic_play_light = 2130837703;
// aapt resource value: 0x7f0200c8
- public const int ic_speaker_group_dark = 2130837704;
+ public const int ic_speaker_dark = 2130837704;
// aapt resource value: 0x7f0200c9
- public const int ic_speaker_group_light = 2130837705;
+ public const int ic_speaker_group_dark = 2130837705;
// aapt resource value: 0x7f0200ca
- public const int ic_speaker_light = 2130837706;
+ public const int ic_speaker_group_light = 2130837706;
// aapt resource value: 0x7f0200cb
- public const int ic_successstatus = 2130837707;
+ public const int ic_speaker_light = 2130837707;
// aapt resource value: 0x7f0200cc
- public const int ic_tv_dark = 2130837708;
+ public const int ic_successstatus = 2130837708;
// aapt resource value: 0x7f0200cd
- public const int ic_tv_light = 2130837709;
+ public const int ic_tv_dark = 2130837709;
// aapt resource value: 0x7f0200ce
- public const int icon = 2130837710;
+ public const int ic_tv_light = 2130837710;
// aapt resource value: 0x7f0200cf
- public const int ion_chevron_right = 2130837711;
+ public const int icon = 2130837711;
// aapt resource value: 0x7f0200d0
- public const int lightbulb = 2130837712;
+ public const int ion_chevron_right = 2130837712;
// aapt resource value: 0x7f0200d1
- public const int list_selector = 2130837713;
+ public const int lightbulb = 2130837713;
// aapt resource value: 0x7f0200d2
- public const int @lock = 2130837714;
+ public const int list_selector = 2130837714;
// aapt resource value: 0x7f0200d3
- public const int logo = 2130837715;
+ public const int @lock = 2130837715;
// aapt resource value: 0x7f0200d4
- public const int more = 2130837716;
+ public const int logo = 2130837716;
// aapt resource value: 0x7f0200d5
- public const int mr_dialog_material_background_dark = 2130837717;
+ public const int more = 2130837717;
// aapt resource value: 0x7f0200d6
- public const int mr_dialog_material_background_light = 2130837718;
+ public const int mr_dialog_material_background_dark = 2130837718;
// aapt resource value: 0x7f0200d7
- public const int mr_ic_audiotrack_light = 2130837719;
+ public const int mr_dialog_material_background_light = 2130837719;
// aapt resource value: 0x7f0200d8
- public const int mr_ic_cast_dark = 2130837720;
+ public const int mr_ic_audiotrack_light = 2130837720;
// aapt resource value: 0x7f0200d9
- public const int mr_ic_cast_light = 2130837721;
+ public const int mr_ic_cast_dark = 2130837721;
// aapt resource value: 0x7f0200da
- public const int mr_ic_close_dark = 2130837722;
+ public const int mr_ic_cast_light = 2130837722;
// aapt resource value: 0x7f0200db
- public const int mr_ic_close_light = 2130837723;
+ public const int mr_ic_close_dark = 2130837723;
// aapt resource value: 0x7f0200dc
- public const int mr_ic_media_route_connecting_mono_dark = 2130837724;
+ public const int mr_ic_close_light = 2130837724;
// aapt resource value: 0x7f0200dd
- public const int mr_ic_media_route_connecting_mono_light = 2130837725;
+ public const int mr_ic_media_route_connecting_mono_dark = 2130837725;
// aapt resource value: 0x7f0200de
- public const int mr_ic_media_route_mono_dark = 2130837726;
+ public const int mr_ic_media_route_connecting_mono_light = 2130837726;
// aapt resource value: 0x7f0200df
- public const int mr_ic_media_route_mono_light = 2130837727;
+ public const int mr_ic_media_route_mono_dark = 2130837727;
// aapt resource value: 0x7f0200e0
- public const int mr_ic_pause_dark = 2130837728;
+ public const int mr_ic_media_route_mono_light = 2130837728;
// aapt resource value: 0x7f0200e1
- public const int mr_ic_pause_light = 2130837729;
+ public const int mr_ic_pause_dark = 2130837729;
// aapt resource value: 0x7f0200e2
- public const int mr_ic_play_dark = 2130837730;
+ public const int mr_ic_pause_light = 2130837730;
// aapt resource value: 0x7f0200e3
- public const int mr_ic_play_light = 2130837731;
+ public const int mr_ic_play_dark = 2130837731;
// aapt resource value: 0x7f0200e4
- public const int notification_sm = 2130837732;
-
- // aapt resource value: 0x7f0200f4
- public const int notification_template_icon_bg = 2130837748;
+ public const int mr_ic_play_light = 2130837732;
// aapt resource value: 0x7f0200e5
- public const int plus = 2130837733;
+ public const int notification_sm = 2130837733;
+
+ // aapt resource value: 0x7f0200f5
+ public const int notification_template_icon_bg = 2130837749;
// aapt resource value: 0x7f0200e6
- public const int refresh = 2130837734;
+ public const int plus = 2130837734;
// aapt resource value: 0x7f0200e7
- public const int roundedbg = 2130837735;
+ public const int refresh = 2130837735;
// aapt resource value: 0x7f0200e8
- public const int roundedbgdark = 2130837736;
+ public const int roundedbg = 2130837736;
// aapt resource value: 0x7f0200e9
- public const int search = 2130837737;
+ public const int roundedbgdark = 2130837737;
// aapt resource value: 0x7f0200ea
- public const int share = 2130837738;
+ public const int search = 2130837738;
// aapt resource value: 0x7f0200eb
- public const int share_tools = 2130837739;
+ public const int share = 2130837739;
// aapt resource value: 0x7f0200ec
- public const int splash_screen = 2130837740;
+ public const int share_tools = 2130837740;
// aapt resource value: 0x7f0200ed
- public const int star = 2130837741;
+ public const int splash_screen = 2130837741;
// aapt resource value: 0x7f0200ee
- public const int star_selected = 2130837742;
+ public const int star = 2130837742;
// aapt resource value: 0x7f0200ef
- public const int tools = 2130837743;
+ public const int star_selected = 2130837743;
// aapt resource value: 0x7f0200f0
- public const int tools_selected = 2130837744;
+ public const int tools = 2130837744;
// aapt resource value: 0x7f0200f1
- public const int upload = 2130837745;
+ public const int tools_selected = 2130837745;
// aapt resource value: 0x7f0200f2
- public const int user = 2130837746;
+ public const int upload = 2130837746;
// aapt resource value: 0x7f0200f3
- public const int yubikey = 2130837747;
+ public const int user = 2130837747;
+
+ // aapt resource value: 0x7f0200f4
+ public const int yubikey = 2130837748;
static Drawable()
{
diff --git a/src/Android/Resources/drawable-hdpi/download.png b/src/Android/Resources/drawable-hdpi/download.png
new file mode 100644
index 000000000..a0b964e28
Binary files /dev/null and b/src/Android/Resources/drawable-hdpi/download.png differ
diff --git a/src/Android/Resources/drawable-xhdpi/download.png b/src/Android/Resources/drawable-xhdpi/download.png
new file mode 100644
index 000000000..843eb7384
Binary files /dev/null and b/src/Android/Resources/drawable-xhdpi/download.png differ
diff --git a/src/Android/Resources/drawable-xxhdpi/download.png b/src/Android/Resources/drawable-xxhdpi/download.png
new file mode 100644
index 000000000..82951e574
Binary files /dev/null and b/src/Android/Resources/drawable-xxhdpi/download.png differ
diff --git a/src/Android/Resources/drawable-xxxhdpi/download.png b/src/Android/Resources/drawable-xxxhdpi/download.png
new file mode 100644
index 000000000..631ff3cc0
Binary files /dev/null and b/src/Android/Resources/drawable-xxxhdpi/download.png differ
diff --git a/src/Android/Resources/drawable/download.png b/src/Android/Resources/drawable/download.png
new file mode 100644
index 000000000..477a72d3f
Binary files /dev/null and b/src/Android/Resources/drawable/download.png differ
diff --git a/src/Android/Services/DeviceActionService.cs b/src/Android/Services/DeviceActionService.cs
index 32351fa39..87ba79afc 100644
--- a/src/Android/Services/DeviceActionService.cs
+++ b/src/Android/Services/DeviceActionService.cs
@@ -2,11 +2,9 @@
using Android.Content;
using Bit.App.Abstractions;
using Xamarin.Forms;
-using Java.IO;
using Android.Webkit;
using Plugin.CurrentActivity;
using System.IO;
-using System.Diagnostics;
using Android.Support.V4.Content;
namespace Bit.Android.Services
@@ -21,6 +19,11 @@ namespace Bit.Android.Services
public bool OpenFile(byte[] fileData, string id, string fileName)
{
+ if(!CanOpenFile(fileName))
+ {
+ return false;
+ }
+
var extension = MimeTypeMap.GetFileExtensionFromUrl(fileName);
if(extension == null)
{
@@ -35,29 +38,47 @@ namespace Bit.Android.Services
var cachePath = CrossCurrentActivity.Current.Activity.CacheDir;
var filePath = Path.Combine(cachePath.Path, fileName);
- System.IO.File.WriteAllBytes(filePath, fileData);
+ File.WriteAllBytes(filePath, fileData);
var file = new Java.IO.File(cachePath, fileName);
+ if(!file.IsFile)
+ {
+ return false;
+ }
+
try
{
- var packageManager = CrossCurrentActivity.Current.Activity.PackageManager;
- var testIntent = new Intent(Intent.ActionView);
- testIntent.SetType(mimeType);
- var list = packageManager.QueryIntentActivities(testIntent,
- global::Android.Content.PM.PackageInfoFlags.MatchDefaultOnly);
- if(list.Count > 0 && file.IsFile)
- {
- var intent = new Intent(Intent.ActionView);
- var uri = FileProvider.GetUriForFile(CrossCurrentActivity.Current.Activity.ApplicationContext,
- "com.x8bit.bitwarden.fileprovider", file);
- intent.SetDataAndType(uri, mimeType);
- intent.SetFlags(ActivityFlags.GrantReadUriPermission);
- CrossCurrentActivity.Current.Activity.StartActivity(intent);
- return true;
- }
+ var intent = new Intent(Intent.ActionView);
+ var uri = FileProvider.GetUriForFile(CrossCurrentActivity.Current.Activity.ApplicationContext,
+ "com.x8bit.bitwarden.fileprovider", file);
+ intent.SetDataAndType(uri, mimeType);
+ intent.SetFlags(ActivityFlags.GrantReadUriPermission);
+ CrossCurrentActivity.Current.Activity.StartActivity(intent);
+ return true;
}
catch { }
return false;
}
+
+ public bool CanOpenFile(string fileName)
+ {
+ var extension = MimeTypeMap.GetFileExtensionFromUrl(fileName);
+ if(extension == null)
+ {
+ return false;
+ }
+
+ var mimeType = MimeTypeMap.Singleton.GetMimeTypeFromExtension(extension.ToLower());
+ if(mimeType == null)
+ {
+ return false;
+ }
+
+ var pm = CrossCurrentActivity.Current.Activity.PackageManager;
+ var intent = new Intent(Intent.ActionView);
+ intent.SetType(mimeType);
+ var activities = pm.QueryIntentActivities(intent, global::Android.Content.PM.PackageInfoFlags.MatchDefaultOnly);
+ return (activities?.Count ?? 0) > 0;
+ }
}
}
diff --git a/src/App/Abstractions/Services/IDeviceActionService.cs b/src/App/Abstractions/Services/IDeviceActionService.cs
index 6e4ce8f6a..7d7e06ec5 100644
--- a/src/App/Abstractions/Services/IDeviceActionService.cs
+++ b/src/App/Abstractions/Services/IDeviceActionService.cs
@@ -4,5 +4,6 @@
{
void CopyToClipboard(string text);
bool OpenFile(byte[] fileData, string id, string fileName);
+ bool CanOpenFile(string fileName);
}
}
diff --git a/src/App/Models/Attachment.cs b/src/App/Models/Attachment.cs
index dc41a6218..7f328db90 100644
--- a/src/App/Models/Attachment.cs
+++ b/src/App/Models/Attachment.cs
@@ -13,7 +13,7 @@ namespace Bit.App.Models
Id = data.Id;
Url = data.Url;
FileName = data.FileName != null ? new CipherString(data.FileName) : null;
- Size = data.Size;
+ SetSize(data.Size);
SizeName = data.SizeName;
}
@@ -22,19 +22,30 @@ namespace Bit.App.Models
Id = response.Id;
Url = response.Url;
FileName = response.FileName != null ? new CipherString(response.FileName) : null;
- Size = response.Size;
+ SetSize(response.Size);
SizeName = response.SizeName;
}
public string Id { get; set; }
public string Url { get; set; }
public CipherString FileName { get; set; }
- public string Size { get; set; }
+ public long Size { get; set; }
public string SizeName { get; set; }
public AttachmentData ToAttachmentData(string loginId)
{
return new AttachmentData(this, loginId);
}
+
+ private void SetSize(string sizeString)
+ {
+ long size;
+ if(!long.TryParse(sizeString, out size))
+ {
+ size = 0;
+ }
+
+ Size = size;
+ }
}
}
diff --git a/src/App/Models/Data/AttachmentData.cs b/src/App/Models/Data/AttachmentData.cs
index a64c8f1a2..d59156743 100644
--- a/src/App/Models/Data/AttachmentData.cs
+++ b/src/App/Models/Data/AttachmentData.cs
@@ -16,7 +16,7 @@ namespace Bit.App.Models.Data
LoginId = loginId;
Url = attachment.Url;
FileName = attachment.FileName?.EncryptedString;
- Size = attachment.Size;
+ Size = attachment.Size.ToString();
SizeName = attachment.SizeName;
}
diff --git a/src/App/Models/Page/VaultViewLoginPageModel.cs b/src/App/Models/Page/VaultViewLoginPageModel.cs
index 6b35b07ab..de1b4cba8 100644
--- a/src/App/Models/Page/VaultViewLoginPageModel.cs
+++ b/src/App/Models/Page/VaultViewLoginPageModel.cs
@@ -223,7 +223,8 @@ namespace Bit.App.Models.Page
{
Id = attachment.Id,
Name = attachment.FileName?.Decrypt(login.OrganizationId),
- Size = attachment.SizeName,
+ SizeName = attachment.SizeName,
+ Size = attachment.Size,
Url = attachment.Url
});
}
@@ -239,7 +240,8 @@ namespace Bit.App.Models.Page
{
public string Id { get; set; }
public string Name { get; set; }
- public string Size { get; set; }
+ public string SizeName { get; set; }
+ public long Size { get; set; }
public string Url { get; set; }
}
}
diff --git a/src/App/Pages/Vault/VaultViewLoginPage.cs b/src/App/Pages/Vault/VaultViewLoginPage.cs
index ef0d68f0e..33b6fe5c3 100644
--- a/src/App/Pages/Vault/VaultViewLoginPage.cs
+++ b/src/App/Pages/Vault/VaultViewLoginPage.cs
@@ -196,7 +196,7 @@ namespace Bit.App.Pages
{
AttachmentsSection.Add(new AttachmentViewCell(attachment, async () =>
{
- await SaveAttachmentAsync(attachment);
+ await OpenAttachmentAsync(attachment);
}));
}
Table.Root.Add(AttachmentsSection);
@@ -211,8 +211,22 @@ namespace Bit.App.Pages
EditItem.Dispose();
}
- private async Task SaveAttachmentAsync(VaultViewLoginPageModel.Attachment attachment)
+ private async Task OpenAttachmentAsync(VaultViewLoginPageModel.Attachment attachment)
{
+ // 20 MB warning
+ if(attachment.Size >= 20971520 && !(await _userDialogs.ConfirmAsync(
+ string.Format(AppResources.AttachmentLargeWarning, attachment.SizeName), null,
+ AppResources.Yes, AppResources.No)))
+ {
+ return;
+ }
+
+ if(!_deviceActionService.CanOpenFile(attachment.Name))
+ {
+ await _userDialogs.AlertAsync(AppResources.UnableToOpenFile, null, AppResources.Ok);
+ return;
+ }
+
_userDialogs.ShowLoading(AppResources.Downloading, MaskType.Black);
var data = await _loginService.DownloadAndDecryptAttachmentAsync(null, attachment.Url);
_userDialogs.HideLoading();
@@ -222,8 +236,7 @@ namespace Bit.App.Pages
return;
}
- var opened = _deviceActionService.OpenFile(data, attachment.Id, attachment.Name);
- if(!opened)
+ if(!_deviceActionService.OpenFile(data, attachment.Id, attachment.Name))
{
await _userDialogs.AlertAsync(AppResources.UnableToOpenFile, null, AppResources.Ok);
return;
@@ -269,8 +282,8 @@ namespace Bit.App.Pages
{
_tapped = tappedAction;
Label.Text = attachment.Name;
- Detail.Text = attachment.Size;
- Icon.Source = "user"; // TODO: download icon
+ Detail.Text = attachment.SizeName;
+ Icon.Source = "download";
BackgroundColor = Color.White;
Tapped += AttachmentViewCell_Tapped;
}
diff --git a/src/App/Resources/AppResources.Designer.cs b/src/App/Resources/AppResources.Designer.cs
index 8b42a6858..b058a0d8f 100644
--- a/src/App/Resources/AppResources.Designer.cs
+++ b/src/App/Resources/AppResources.Designer.cs
@@ -151,6 +151,15 @@ namespace Bit.App.Resources {
}
}
+ ///
+ /// Looks up a localized string similar to This attachment is {0} in size. Are you sure you want to download it onto your device?.
+ ///
+ public static string AttachmentLargeWarning {
+ get {
+ return ResourceManager.GetString("AttachmentLargeWarning", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Attachments.
///
@@ -2006,7 +2015,7 @@ namespace Bit.App.Resources {
}
///
- /// Looks up a localized string similar to Unable to open this type of file on your device..
+ /// Looks up a localized string similar to Your device cannot open this type of tile..
///
public static string UnableToOpenFile {
get {
diff --git a/src/App/Resources/AppResources.resx b/src/App/Resources/AppResources.resx
index abcb882cd..8d9fb6b19 100644
--- a/src/App/Resources/AppResources.resx
+++ b/src/App/Resources/AppResources.resx
@@ -912,10 +912,14 @@
Unable to download file.
- Unable to open this type of file on your device.
+ Your device cannot open this type of tile.
Downloading...
Message shown when downloading a file
+
+ This attachment is {0} in size. Are you sure you want to download it onto your device?
+ The placeholder will show the file size of the attachment. Ex "25 MB"
+
\ No newline at end of file
diff --git a/src/App/Utilities/ApiHttpClient.cs b/src/App/Utilities/ApiHttpClient.cs
index 163643995..cc958a07e 100644
--- a/src/App/Utilities/ApiHttpClient.cs
+++ b/src/App/Utilities/ApiHttpClient.cs
@@ -20,9 +20,9 @@ namespace Bit.App
private void Init()
{
//BaseAddress = new Uri("http://169.254.80.80:4000"); // Desktop from VS Android Emulator
- //BaseAddress = new Uri("http://192.168.1.6:4000"); // Desktop
+ BaseAddress = new Uri("http://192.168.1.4:4000"); // Desktop
//BaseAddress = new Uri("https://preview-api.bitwarden.com"); // Preview
- BaseAddress = new Uri("https://api.bitwarden.com"); // Production
+ // BaseAddress = new Uri("https://api.bitwarden.com"); // Production
DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
}
diff --git a/src/App/Utilities/IdentityHttpClient.cs b/src/App/Utilities/IdentityHttpClient.cs
index 58d509c48..259c6d16c 100644
--- a/src/App/Utilities/IdentityHttpClient.cs
+++ b/src/App/Utilities/IdentityHttpClient.cs
@@ -20,9 +20,9 @@ namespace Bit.App
private void Init()
{
//BaseAddress = new Uri("http://169.254.80.80:33656"); // Desktop from VS Android Emulator
- //BaseAddress = new Uri("http://192.168.1.6:33656"); // Desktop
+ BaseAddress = new Uri("http://192.168.1.4:33656"); // Desktop
//BaseAddress = new Uri("https://identity-api.bitwarden.com"); // Preview
- BaseAddress = new Uri("https://identity.bitwarden.com"); // Production
+ //BaseAddress = new Uri("https://identity.bitwarden.com"); // Production
DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
}
diff --git a/src/iOS/Resources/download.png b/src/iOS/Resources/download.png
new file mode 100644
index 000000000..477a72d3f
Binary files /dev/null and b/src/iOS/Resources/download.png differ
diff --git a/src/iOS/Resources/download@2x.png b/src/iOS/Resources/download@2x.png
new file mode 100644
index 000000000..843eb7384
Binary files /dev/null and b/src/iOS/Resources/download@2x.png differ
diff --git a/src/iOS/Resources/download@3x.png b/src/iOS/Resources/download@3x.png
new file mode 100644
index 000000000..82951e574
Binary files /dev/null and b/src/iOS/Resources/download@3x.png differ
diff --git a/src/iOS/Services/DeviceActionService.cs b/src/iOS/Services/DeviceActionService.cs
index 618edc608..f9cb9086e 100644
--- a/src/iOS/Services/DeviceActionService.cs
+++ b/src/iOS/Services/DeviceActionService.cs
@@ -14,7 +14,12 @@ namespace Bit.iOS.Services
public bool OpenFile(byte[] fileData, string id, string fileName)
{
- throw new NotImplementedException();
+ return true;
+ }
+
+ public bool CanOpenFile(string fileName)
+ {
+ return true;
}
}
}
diff --git a/src/iOS/iOS.csproj b/src/iOS/iOS.csproj
index dd0e6dae7..7c353b9be 100644
--- a/src/iOS/iOS.csproj
+++ b/src/iOS/iOS.csproj
@@ -725,6 +725,15 @@
+
+
+
+
+
+
+
+
+