major elements of new app design implemented
caution: not fully functional, several features missing/crashing
BIN
src/MaterialTest2/Resources/drawable-xhdpi/ic_dashboard.png
Normal file
After Width: | Height: | Size: 132 B |
BIN
src/MaterialTest2/Resources/drawable-xhdpi/ic_discuss.png
Normal file
After Width: | Height: | Size: 247 B |
BIN
src/MaterialTest2/Resources/drawable-xhdpi/ic_done.png
Normal file
After Width: | Height: | Size: 297 B |
BIN
src/MaterialTest2/Resources/drawable-xhdpi/ic_event.png
Normal file
After Width: | Height: | Size: 225 B |
BIN
src/MaterialTest2/Resources/drawable-xhdpi/ic_forum.png
Normal file
After Width: | Height: | Size: 226 B |
BIN
src/MaterialTest2/Resources/drawable-xhdpi/ic_headset.png
Normal file
After Width: | Height: | Size: 488 B |
BIN
src/MaterialTest2/Resources/drawable-xhdpi/ic_menu.png
Normal file
After Width: | Height: | Size: 135 B |
69
src/MaterialTest2/Resources/layout/Mainold.axml
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:local="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/drawerLayout"
|
||||
android:layout_height="match_parent">
|
||||
<!-- activity view -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<include
|
||||
android:id="@+id/toolbar2"
|
||||
layout="@layout/toolbar2" />
|
||||
<ScrollView xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/main_content">
|
||||
<Button
|
||||
android:id="@+id/MyButton"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/Hello" />
|
||||
<CheckBox
|
||||
android:text="CheckBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/checkBox1" />
|
||||
<ImageView
|
||||
android:id="@+id/imglogo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_keepass2android" />
|
||||
<EditText
|
||||
android:inputType="textEmailAddress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/editText1" />
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:choiceMode="singleChoice" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
<!-- navigation drawer -->
|
||||
<RelativeLayout
|
||||
android:layout_gravity="left|start"
|
||||
android:layout_width="match_parent"
|
||||
android:background="#fff"
|
||||
android:layout_height="match_parent">
|
||||
<Button
|
||||
android:id="@+id/MyButton2"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/Hello" />
|
||||
</RelativeLayout>
|
||||
</android.support.v4.widget.DrawerLayout>
|
33
src/MaterialTest2/Resources/layout/nav_header.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2015 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="192dp"
|
||||
android:background="?attr/colorAccent"
|
||||
android:padding="16dp"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark"
|
||||
android:orientation="vertical"
|
||||
android:gravity="bottom">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Username"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
|
||||
|
||||
</LinearLayout>
|
5
src/MaterialTest2/Resources/values/dimens.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="detail_backdrop_height">200dp</dimen>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
@ -10,7 +10,7 @@ namespace keepass2android
|
||||
{
|
||||
[Activity(Label = "@string/app_name",
|
||||
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/Base")]
|
||||
Theme = "@style/MyTheme_ActionBar")]
|
||||
[IntentFilter(new[] { "keepass2android.AboutActivity" }, Categories = new[] { Intent.CategoryDefault })]
|
||||
public class AboutActivity: Activity, IDialogInterfaceOnDismissListener
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ namespace keepass2android
|
||||
{
|
||||
[Activity(Label = "@string/app_name",
|
||||
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/Base")]
|
||||
Theme = "@style/MyTheme_ActionBar")]
|
||||
public class CreateDatabaseActivity : Activity
|
||||
{
|
||||
private IOConnectionInfo _ioc;
|
||||
|
@ -14,7 +14,7 @@ using KeePassLib.Utility;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = AppNames.AppName, Theme = "@style/Base")]
|
||||
[Activity(Label = AppNames.AppName, Theme = "@style/MyTheme_ActionBar")]
|
||||
public class DonateReminder : Activity
|
||||
{
|
||||
class Reminder
|
||||
|
@ -44,7 +44,8 @@ using Uri = Android.Net.Uri;
|
||||
namespace keepass2android
|
||||
{
|
||||
|
||||
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden, Theme="@style/NoTitleBar")]
|
||||
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/MyTheme_ActionBar")]
|
||||
public class EntryActivity : LockCloseActivity
|
||||
{
|
||||
public const String KeyEntry = "entry";
|
||||
@ -125,28 +126,6 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
protected void SetupMoveButtons() {
|
||||
View moveView = FindViewById(Resource.Id.entry_move);
|
||||
/* Disabled for simpler UI. Wait if users demand that button.
|
||||
if (App.Kp2a.GetDb().CanWrite)
|
||||
{
|
||||
moveView.Visibility = ViewStates.Visible;
|
||||
moveView.Click += (sender, e) =>
|
||||
{
|
||||
NavigateToFolderAndLaunchMoveElementTask navMoveTask =
|
||||
new NavigateToFolderAndLaunchMoveElementTask(Entry.ParentGroup,Entry.Uuid, false);
|
||||
navMoveTask.SetActivityResult(this, KeePass.ExitNormal );
|
||||
Finish();
|
||||
|
||||
};
|
||||
}
|
||||
else*/
|
||||
{
|
||||
moveView.Visibility = ViewStates.Gone;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class PluginActionReceiver : BroadcastReceiver
|
||||
{
|
||||
@ -329,8 +308,9 @@ namespace keepass2android
|
||||
_showPassword =
|
||||
!prefs.GetBoolean(GetString(Resource.String.maskpass_key), Resources.GetBoolean(Resource.Boolean.maskpass_default));
|
||||
|
||||
base.OnCreate(savedInstanceState);
|
||||
RequestWindowFeature(WindowFeatures.IndeterminateProgress);
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
|
||||
new ActivityDesign(this).ApplyTheme();
|
||||
|
||||
@ -375,7 +355,6 @@ namespace keepass2android
|
||||
FillData();
|
||||
|
||||
SetupEditButtons();
|
||||
SetupMoveButtons ();
|
||||
|
||||
App.Kp2a.GetDb().LastOpenedEntry = new PwEntryOutput(Entry, App.Kp2a.GetDb().KpDatabase);
|
||||
|
||||
@ -455,12 +434,14 @@ namespace keepass2android
|
||||
private void PopulateExtraStrings()
|
||||
{
|
||||
ViewGroup extraGroup = (ViewGroup) FindViewById(Resource.Id.extra_strings);
|
||||
bool hasExtras = false;
|
||||
foreach (var pair in Entry.Strings.Where(pair => !PwDefs.IsStandardField(pair.Key)).OrderBy(pair => pair.Key))
|
||||
{
|
||||
hasExtras = true;
|
||||
var stringView = CreateExtraSection(pair.Key, pair.Value.ReadString(), pair.Value.IsProtected);
|
||||
extraGroup.AddView(stringView.View);
|
||||
}
|
||||
|
||||
FindViewById(Resource.Id.extra_strings_container).Visibility = hasExtras ? ViewStates.Visible : ViewStates.Gone;
|
||||
}
|
||||
|
||||
private ExtraStringView CreateExtraSection(string key, string value, bool isProtected)
|
||||
@ -690,7 +671,7 @@ namespace keepass2android
|
||||
protected void FillData()
|
||||
{
|
||||
_protectedTextViews = new List<TextView>();
|
||||
ImageView iv = (ImageView) FindViewById(Resource.Id.entry_icon);
|
||||
ImageView iv = (ImageView) FindViewById(Resource.Id.icon);
|
||||
if (iv != null)
|
||||
{
|
||||
iv.SetImageDrawable(Resources.GetDrawable(Resource.Drawable.ic00));
|
||||
@ -698,8 +679,9 @@ namespace keepass2android
|
||||
|
||||
|
||||
|
||||
ActionBar.Title = Entry.Strings.ReadSafe(PwDefs.TitleField);
|
||||
ActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
SupportActionBar.Title = Entry.Strings.ReadSafe(PwDefs.TitleField);
|
||||
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
SupportActionBar.SetHomeButtonEnabled(true);
|
||||
|
||||
PopulateGroupText (Resource.Id.entry_group_name, Resource.Id.entryfield_group_container, KeyGroupFullPath);
|
||||
|
||||
@ -914,6 +896,8 @@ namespace keepass2android
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void UpdateTogglePasswordMenu()
|
||||
{
|
||||
IMenuItem togglePassword = _menu.FindItem(Resource.Id.menu_toggle_pass);
|
||||
|
@ -33,12 +33,13 @@ using KeePassLib.Security;
|
||||
using Android.Content.PM;
|
||||
using System.IO;
|
||||
using System.Globalization;
|
||||
using Android.Util;
|
||||
using File = System.IO.File;
|
||||
using Uri = Android.Net.Uri;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden, Theme="@style/NoTitleBar")]
|
||||
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme_ActionBar")]
|
||||
public class EntryEditActivity : LockCloseActivity {
|
||||
public const String KeyEntry = "entry";
|
||||
public const String KeyParent = "parent";
|
||||
@ -215,8 +216,8 @@ namespace keepass2android
|
||||
|
||||
|
||||
// Generate password button
|
||||
Button generatePassword = (Button)FindViewById(Resource.Id.generate_button);
|
||||
generatePassword.Click += (sender, e) => {
|
||||
FindViewById(Resource.Id.generate_button).Click += (sender, e) =>
|
||||
{
|
||||
UpdateEntryFromUi(State.Entry);
|
||||
GeneratePasswordActivity.Launch(this);
|
||||
};
|
||||
@ -225,20 +226,19 @@ namespace keepass2android
|
||||
|
||||
|
||||
// Save button
|
||||
ActionBar.SetCustomView(Resource.Layout.SaveButton);
|
||||
ActionBar.SetDisplayShowCustomEnabled(true);
|
||||
ActionBar.SetDisplayShowTitleEnabled(false);
|
||||
ActionBar.SetDisplayUseLogoEnabled(false);
|
||||
ActionBar.SetDisplayShowHomeEnabled(false);
|
||||
ActionBar.SetDisplayOptions(ActionBarDisplayOptions.ShowCustom,
|
||||
ActionBarDisplayOptions.ShowCustom);
|
||||
var save = FindViewById(Resource.Id.entry_save);
|
||||
save.Click += (sender, e) =>
|
||||
{
|
||||
SaveEntry();
|
||||
};
|
||||
//SupportActionBar.SetCustomView(Resource.Layout.SaveButton);
|
||||
|
||||
FindViewById(Resource.Id.entry_save_cancel).Click += (sender, args) => Finish();
|
||||
if (State.IsNew)
|
||||
{
|
||||
SupportActionBar.Title = GetString(Resource.String.add_entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
SupportActionBar.Title = GetString(Resource.String.edit_entry);
|
||||
}
|
||||
|
||||
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
SupportActionBar.SetHomeButtonEnabled(true);
|
||||
|
||||
// Respect mask password setting
|
||||
MakePasswordVisibleOrHidden();
|
||||
@ -258,7 +258,7 @@ namespace keepass2android
|
||||
LinearLayout container = (LinearLayout) FindViewById(Resource.Id.advanced_container);
|
||||
|
||||
KeyValuePair<string, ProtectedString> pair = new KeyValuePair<string, ProtectedString>("" , new ProtectedString(true, ""));
|
||||
LinearLayout ees = CreateExtraStringView(pair);
|
||||
View ees = CreateExtraStringView(pair);
|
||||
container.AddView(ees);
|
||||
|
||||
State.EntryModified = true;
|
||||
@ -745,9 +745,11 @@ namespace keepass2android
|
||||
{
|
||||
label = "<attachment>";
|
||||
}
|
||||
Button binaryButton = new Button(this) {Text = label};
|
||||
//Button binaryButton = new Button(this, null, Resource.Style.EditEntryButton) {Text = label};
|
||||
Button binaryButton = (Button)LayoutInflater.Inflate(Resource.Layout.EntryEditButtonDelete, null);
|
||||
binaryButton.Text = label;
|
||||
|
||||
binaryButton.SetCompoundDrawablesWithIntrinsicBounds( Resources.GetDrawable(Android.Resource.Drawable.IcMenuDelete),null, null, null);
|
||||
//binaryButton.SetCompoundDrawablesWithIntrinsicBounds( Resources.GetDrawable(Android.Resource.Drawable.IcMenuDelete),null, null, null);
|
||||
binaryButton.Click += (sender, e) =>
|
||||
{
|
||||
State.EntryModified = true;
|
||||
@ -760,9 +762,13 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
Button addBinaryButton = new Button(this) {Text = GetString(Resource.String.add_binary)};
|
||||
addBinaryButton.SetCompoundDrawablesWithIntrinsicBounds( Resources.GetDrawable(Android.Resource.Drawable.IcMenuAdd) , null, null, null);
|
||||
//Button addBinaryButton = new Button(this, null, Resource.Style.EditEntryButton ) {Text = GetString(Resource.String.add_binary)};
|
||||
//addBinaryButton.SetCompoundDrawablesWithIntrinsicBounds( Resources.GetDrawable(Android.Resource.Drawable.IcMenuAdd) , null, null, null);
|
||||
Button addBinaryButton = (Button)LayoutInflater.Inflate(Resource.Layout.EntryEditButtonAdd, null);
|
||||
addBinaryButton.Text = GetString(Resource.String.add_binary);
|
||||
|
||||
addBinaryButton.Enabled = true;
|
||||
|
||||
if (!App.Kp2a.GetDb().DatabaseFormat.CanHaveMultipleAttachments)
|
||||
addBinaryButton.Enabled = !State.Entry.Binaries.Any();
|
||||
addBinaryButton.Click += (sender, e) =>
|
||||
@ -795,14 +801,19 @@ namespace keepass2android
|
||||
|
||||
public override bool OnOptionsItemSelected(IMenuItem item) {
|
||||
switch ( item.ItemId ) {
|
||||
case Resource.Id.menu_donate:
|
||||
return Util.GotoDonateUrl(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
case Resource.Id.menu_save:
|
||||
SaveEntry();
|
||||
return true;
|
||||
case Resource.Id.menu_cancel:
|
||||
Finish();
|
||||
return true;
|
||||
case Android.Resource.Id.Home:
|
||||
Finish();
|
||||
return true;
|
||||
default:
|
||||
return base.OnOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UpdateExpires()
|
||||
@ -819,15 +830,18 @@ namespace keepass2android
|
||||
FindViewById(Resource.Id.entry_expires).Enabled = State.Entry.Expires;
|
||||
}
|
||||
|
||||
public override Java.Lang.Object OnRetainNonConfigurationInstance()
|
||||
/*
|
||||
* TODO required??
|
||||
*
|
||||
* public override Java.Lang.Object OnRetainNonConfigurationInstance()
|
||||
{
|
||||
UpdateEntryFromUi(State.Entry);
|
||||
return this;
|
||||
}
|
||||
}*/
|
||||
|
||||
LinearLayout CreateExtraStringView(KeyValuePair<string, ProtectedString> pair)
|
||||
RelativeLayout CreateExtraStringView(KeyValuePair<string, ProtectedString> pair)
|
||||
{
|
||||
LinearLayout ees = (LinearLayout)LayoutInflater.Inflate(Resource.Layout.entry_edit_section, null);
|
||||
RelativeLayout ees = (RelativeLayout)LayoutInflater.Inflate(Resource.Layout.entry_edit_section, null);
|
||||
((TextView)ees.FindViewById(Resource.Id.title)).Text = pair.Key;
|
||||
((TextView)ees.FindViewById(Resource.Id.title)).TextChanged += (sender, e) => State.EntryModified = true;
|
||||
((TextView)ees.FindViewById(Resource.Id.value)).Text = pair.Value.ReadString();
|
||||
@ -928,8 +942,7 @@ namespace keepass2android
|
||||
}
|
||||
else
|
||||
{
|
||||
FindViewById(Resource.Id.entry_override_url_label).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.entry_override_url).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.entry_override_url_container).Visibility = ViewStates.Gone;
|
||||
}
|
||||
|
||||
if (App.Kp2a.GetDb().DatabaseFormat.SupportsTags)
|
||||
@ -1016,6 +1029,11 @@ namespace keepass2android
|
||||
|
||||
private void PopulateText(int viewId, String text) {
|
||||
TextView tv = (TextView) FindViewById(viewId);
|
||||
if (tv == null)
|
||||
{
|
||||
Kp2aLog.Log("Invalid viewId " + viewId);
|
||||
return;
|
||||
}
|
||||
tv.Text = text;
|
||||
tv.TextChanged += (sender, e) => {State.EntryModified = true;};
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace keepass2android
|
||||
|
||||
[Activity(Label = "@string/app_name",
|
||||
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/Base")]
|
||||
Theme = "@style/MyTheme_ActionBar")]
|
||||
[IntentFilter(new[] {"keepass2android.ExportDatabaseActivity"}, Categories = new[] {Intent.CategoryDefault})]
|
||||
public class ExportDatabaseActivity : LockCloseActivity
|
||||
{
|
||||
|
@ -1,18 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.Content.Res;
|
||||
using Android.Graphics;
|
||||
using Android.Graphics.Drawables;
|
||||
using Android.OS;
|
||||
using Android.Support.V4.Content;
|
||||
using Android.Support.V7.App;
|
||||
using Android.Text;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using keepass2android.Io;
|
||||
using keepass2android.view;
|
||||
using AlertDialog = Android.App.AlertDialog;
|
||||
using Object = Java.Lang.Object;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden , Theme="@style/NoTitleBar")]
|
||||
public class FileStorageSelectionActivity : ListActivity
|
||||
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme")]
|
||||
public class FileStorageSelectionActivity : AppCompatActivity
|
||||
{
|
||||
private readonly ActivityDesign _design;
|
||||
|
||||
@ -78,8 +87,53 @@ namespace keepass2android
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static float convertDpToPixel(float dp, Context context)
|
||||
{
|
||||
Resources resources = context.Resources;
|
||||
DisplayMetrics metrics = resources.DisplayMetrics;
|
||||
float px = dp * metrics.Density;
|
||||
return px;
|
||||
}
|
||||
|
||||
|
||||
public override View GetView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
|
||||
Button btn;
|
||||
|
||||
if (convertView == null)
|
||||
{ // if it's not recycled, initialize some attributes
|
||||
|
||||
btn = new Button(_context);
|
||||
btn.LayoutParameters = new GridView.LayoutParams((int)convertDpToPixel(80, _context), (int)convertDpToPixel(100, _context));
|
||||
btn.SetBackgroundResource(Resource.Drawable.storagetype_button_bg);
|
||||
btn.SetPadding(8, 8, 8, 8);
|
||||
btn.SetTextSize(ComplexUnitType.Sp, 12);
|
||||
btn.SetTextColor(new Color(115, 115, 115));
|
||||
btn.SetSingleLine(false);
|
||||
btn.Click += (sender, args) => _context.OnItemSelected( (string) ((Button)sender).Tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
btn = (Button)convertView;
|
||||
}
|
||||
|
||||
var protocolId = _protocolIds[position];
|
||||
btn.Tag = protocolId;
|
||||
Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + protocolId);
|
||||
|
||||
String title = App.Kp2a.GetResourceString("filestoragename_" + protocolId);
|
||||
var str = new SpannableString(title);
|
||||
|
||||
btn.TextFormatted = str;
|
||||
//var drawable = ContextCompat.GetDrawable(context, Resource.Drawable.Icon);
|
||||
btn.SetCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
|
||||
|
||||
//TODO kp2a
|
||||
return btn;
|
||||
/*
|
||||
if (_protocolIds[position] == "kp2a")
|
||||
{
|
||||
return new FileStorageViewKp2a(_context);
|
||||
@ -89,7 +143,7 @@ namespace keepass2android
|
||||
var view = new FileStorageView(_context, _protocolIds[position], position);
|
||||
return view;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@ -145,13 +199,29 @@ namespace keepass2android
|
||||
|
||||
SetContentView(Resource.Layout.filestorage_selection);
|
||||
|
||||
_fileStorageAdapter = new FileStorageAdapter(this);
|
||||
ListAdapter = _fileStorageAdapter;
|
||||
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
|
||||
|
||||
ListView listView = FindViewById<ListView>(Android.Resource.Id.List);
|
||||
listView.ItemClick +=
|
||||
SetSupportActionBar(toolbar);
|
||||
|
||||
SupportActionBar.Title = RemoveTrailingColon(GetString(Resource.String.select_storage_type));
|
||||
|
||||
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
SupportActionBar.SetDisplayShowHomeEnabled(true);
|
||||
toolbar.NavigationClick += (sender, args) => OnBackPressed();
|
||||
|
||||
_fileStorageAdapter = new FileStorageAdapter(this);
|
||||
var gridView = FindViewById<GridView>(Resource.Id.gridview);
|
||||
gridView.ItemClick +=
|
||||
(sender, args) => OnItemSelected((string)_fileStorageAdapter.GetItem(args.Position));
|
||||
//listView.ItemsCanFocus = true;
|
||||
gridView.Adapter = _fileStorageAdapter;
|
||||
|
||||
}
|
||||
|
||||
private string RemoveTrailingColon(string str)
|
||||
{
|
||||
if (str.EndsWith(":"))
|
||||
return str.Substring(0, str.Length - 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
|
@ -26,7 +26,7 @@ using Android.Widget;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar")]
|
||||
[Activity(Label = "@string/app_name", Theme = "@style/MyTheme_ActionBar")]
|
||||
public class GeneratePasswordActivity : LockCloseActivity {
|
||||
private readonly int[] _buttonIds = new[] {Resource.Id.btn_length6, Resource.Id.btn_length8, Resource.Id.btn_length12, Resource.Id.btn_length16};
|
||||
|
||||
|
@ -29,7 +29,7 @@ using Android.Content.PM;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden , Theme="@style/NoTitleBar")]
|
||||
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme_ActionBar")]
|
||||
[MetaData("android.app.default_searchable",Value="keepass2android.search.SearchResults")]
|
||||
public class GroupActivity : GroupBaseActivity {
|
||||
|
||||
@ -75,15 +75,10 @@ namespace keepass2android
|
||||
|
||||
public override void SetupNormalButtons()
|
||||
{
|
||||
GroupView.SetNormalButtonVisibility(AddGroupEnabled, AddEntryEnabled);
|
||||
GroupView.Invalidate();
|
||||
SetNormalButtonVisibility(AddGroupEnabled, AddEntryEnabled);
|
||||
}
|
||||
|
||||
private bool AddGroupEnabled
|
||||
{
|
||||
get { return App.Kp2a.GetDb().CanWrite; }
|
||||
}
|
||||
private bool AddEntryEnabled
|
||||
protected override bool AddEntryEnabled
|
||||
{
|
||||
get { return App.Kp2a.GetDb().CanWrite && ((this.Group.ParentGroup != null) || App.Kp2a.GetDb().DatabaseFormat.CanHaveEntriesInRootGroup); }
|
||||
}
|
||||
@ -121,26 +116,25 @@ namespace keepass2android
|
||||
|
||||
if (AddGroupEnabled) {
|
||||
// Add Group button
|
||||
View addGroup = FindViewById (Resource.Id.add_group);
|
||||
View addGroup = FindViewById (Resource.Id.fabAddNewGroup);
|
||||
addGroup.Click += (sender, e) => {
|
||||
GroupEditActivity.Launch (this, Group);
|
||||
};
|
||||
}
|
||||
|
||||
if (AddEntryEnabled) {
|
||||
// Add Entry button
|
||||
View addEntry = FindViewById (Resource.Id.add_entry);
|
||||
addEntry.Click += (sender, e) => {
|
||||
EntryEditActivity.Launch (this, Group, AppTask);
|
||||
|
||||
};
|
||||
if (AddEntryEnabled)
|
||||
{
|
||||
View addEntry = FindViewById (Resource.Id.fabAddNewEntry);
|
||||
addEntry.Click += (sender, e) => { EntryEditActivity.Launch (this, Group, AppTask); };
|
||||
|
||||
}
|
||||
|
||||
SetGroupTitle();
|
||||
SetGroupIcon();
|
||||
|
||||
ListAdapter = new PwGroupListAdapter(this, Group);
|
||||
RegisterForContextMenu(ListView);
|
||||
FragmentManager.FindFragmentById<GroupListFragment>(Resource.Id.list_fragment).ListAdapter = new PwGroupListAdapter(this, Group);
|
||||
/*TODO RegisterForContextMenu(ListView);*/
|
||||
Log.Warn(Tag, "Finished creating group");
|
||||
|
||||
}
|
||||
|
@ -33,11 +33,14 @@ using keepass2android.Io;
|
||||
using keepass2android.database.edit;
|
||||
using keepass2android.view;
|
||||
using Android.Graphics.Drawables;
|
||||
using Android.Support.V4.View;
|
||||
using CursorAdapter = Android.Support.V4.Widget.CursorAdapter;
|
||||
using Object = Java.Lang.Object;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
|
||||
public abstract class GroupBaseActivity : LockCloseListActivity {
|
||||
public abstract class GroupBaseActivity : LockCloseActivity {
|
||||
public const String KeyEntry = "entry";
|
||||
public const String KeyMode = "mode";
|
||||
|
||||
@ -65,9 +68,61 @@ namespace keepass2android
|
||||
|
||||
public virtual void SetupNormalButtons()
|
||||
{
|
||||
GroupView.SetNormalButtonVisibility(App.Kp2a.GetDb().CanWrite, App.Kp2a.GetDb().CanWrite);
|
||||
SetNormalButtonVisibility(AddGroupEnabled, AddEntryEnabled);
|
||||
}
|
||||
|
||||
|
||||
protected virtual bool AddGroupEnabled
|
||||
{
|
||||
get { return App.Kp2a.GetDb().CanWrite; }
|
||||
}
|
||||
protected virtual bool AddEntryEnabled
|
||||
{
|
||||
get { return App.Kp2a.GetDb().CanWrite; }
|
||||
}
|
||||
|
||||
public void SetNormalButtonVisibility(bool showAddGroup, bool showAddEntry)
|
||||
{
|
||||
FindViewById(Resource.Id.bottom_bar).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.divider2).Visibility = ViewStates.Gone;
|
||||
|
||||
FindViewById(Resource.Id.fabCancelAddNew).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNewGroup).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone;
|
||||
|
||||
FindViewById(Resource.Id.fabAddNew).Visibility = (showAddGroup || showAddEntry) ? ViewStates.Visible : ViewStates.Gone;
|
||||
|
||||
|
||||
/*TODO Remove
|
||||
View insertElement = FindViewById(Resource.Id.insert_element);
|
||||
insertElement.Visibility = ViewStates.Gone;
|
||||
|
||||
View insertElementCancel = FindViewById(Resource.Id.cancel_insert_element);
|
||||
insertElementCancel.Visibility = ViewStates.Gone;
|
||||
|
||||
View addGroup = FindViewById(Resource.Id.add_group);
|
||||
addGroup.Visibility = showAddGroup ? ViewStates.Visible : ViewStates.Gone;
|
||||
|
||||
|
||||
View addEntry = FindViewById(Resource.Id.add_entry);
|
||||
addEntry.Visibility = showAddEntry ? ViewStates.Visible : ViewStates.Gone;
|
||||
*/
|
||||
/*
|
||||
if (!showAddEntry && !showAddGroup)
|
||||
{
|
||||
View divider2 = FindViewById(Resource.Id.divider2);
|
||||
divider2.Visibility = ViewStates.Gone;
|
||||
|
||||
FindViewById(Resource.Id.bottom_bar).Visibility = ViewStates.Gone;
|
||||
|
||||
View list = FindViewById(Android.Resource.Id.List);
|
||||
var lp = (RelativeLayout.LayoutParams)list.LayoutParameters;
|
||||
|
||||
lp.AddRule(LayoutRules.AlignParentBottom, (int)LayoutRules.True);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
||||
{
|
||||
base.OnActivityResult(requestCode, resultCode, data);
|
||||
@ -122,7 +177,7 @@ namespace keepass2android
|
||||
protected PwGroup Group;
|
||||
|
||||
internal AppTask AppTask;
|
||||
protected GroupView GroupView;
|
||||
//TODO protected GroupView GroupView;
|
||||
|
||||
private String strCachedGroupUuid = null;
|
||||
public String UuidGroup {
|
||||
@ -155,13 +210,14 @@ namespace keepass2android
|
||||
Database db = App.Kp2a.GetDb();
|
||||
if ( db.Dirty.Contains(Group) ) {
|
||||
db.Dirty.Remove(Group);
|
||||
BaseAdapter adapter = (BaseAdapter) ListAdapter;
|
||||
adapter.NotifyDataSetChanged();
|
||||
/*TODO BaseAdapter adapter = (BaseAdapter) ListAdapter;
|
||||
adapter.NotifyDataSetChanged();*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnListItemClick(ListView l, View v, int position, long id) {
|
||||
/*TODO
|
||||
* protected override void OnListItemClick(ListView l, View v, int position, long id) {
|
||||
base.OnListItemClick(l, v, position, id);
|
||||
|
||||
IListAdapter adapt = ListAdapter;
|
||||
@ -169,7 +225,7 @@ namespace keepass2android
|
||||
cv.OnClick();
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
protected override void OnCreate(Bundle savedInstanceState) {
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
@ -183,15 +239,33 @@ namespace keepass2android
|
||||
|
||||
_prefs = PreferenceManager.GetDefaultSharedPreferences(this);
|
||||
|
||||
GroupView = new GroupView(this);
|
||||
SetContentView(GroupView);
|
||||
|
||||
SetContentView(Resource.Layout.group);
|
||||
|
||||
FindViewById(Resource.Id.fabAddNew).Click += (sender, args) =>
|
||||
{
|
||||
FindViewById(Resource.Id.fabCancelAddNew).Visibility = ViewStates.Visible;
|
||||
FindViewById(Resource.Id.fabAddNewGroup).Visibility = AddGroupEnabled ? ViewStates.Visible : ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNewEntry).Visibility = AddEntryEnabled ? ViewStates.Visible : ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Gone;
|
||||
};
|
||||
|
||||
FindViewById(Resource.Id.fabCancelAddNew).Click += (sender, args) =>
|
||||
{
|
||||
FindViewById(Resource.Id.fabCancelAddNew).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNewGroup).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Visible;
|
||||
};
|
||||
|
||||
|
||||
|
||||
FindViewById(Resource.Id.cancel_insert_element).Click += (sender, args) => StopMovingElement();
|
||||
FindViewById(Resource.Id.insert_element).Click += (sender, args) => InsertElement();
|
||||
|
||||
SetResult(KeePass.ExitNormal);
|
||||
|
||||
StyleScrollBars();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -207,12 +281,6 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
protected void StyleScrollBars() {
|
||||
ListView lv = ListView;
|
||||
lv.ScrollBarStyle =ScrollbarStyles.InsideInset;
|
||||
lv.TextFilterEnabled = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected void SetGroupTitle()
|
||||
@ -228,31 +296,33 @@ namespace keepass2android
|
||||
titleText = GetText(Resource.String.root);
|
||||
}
|
||||
|
||||
ActionBar.Title = titleText;
|
||||
SupportActionBar.Title = titleText;
|
||||
if (clickable)
|
||||
ActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
{
|
||||
SupportActionBar.SetHomeButtonEnabled(true);
|
||||
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
SupportActionBar.SetDisplayShowHomeEnabled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected void SetGroupIcon() {
|
||||
if (Group != null) {
|
||||
Drawable drawable = App.Kp2a.GetDb().DrawableFactory.GetIconDrawable(Resources, App.Kp2a.GetDb().KpDatabase, Group.IconId, Group.CustomIconUuid);
|
||||
ImageView iv = (ImageView) FindViewById(Resource.Id.icon);
|
||||
if (iv != null)
|
||||
iv.SetImageDrawable(drawable);
|
||||
if (Util.HasActionBar(this))
|
||||
ActionBar.SetIcon(drawable);
|
||||
SupportActionBar.SetDisplayShowHomeEnabled(true);
|
||||
//SupportActionBar.SetIcon(drawable);
|
||||
}
|
||||
}
|
||||
|
||||
class SuggestionListener: Java.Lang.Object, SearchView.IOnSuggestionListener
|
||||
class SuggestionListener: Java.Lang.Object, SearchView.IOnSuggestionListener, Android.Support.V7.Widget.SearchView.IOnSuggestionListener
|
||||
{
|
||||
private readonly CursorAdapter _suggestionsAdapter;
|
||||
private readonly GroupBaseActivity _activity;
|
||||
private readonly IMenuItem _searchItem;
|
||||
|
||||
|
||||
public SuggestionListener(CursorAdapter suggestionsAdapter, GroupBaseActivity activity, IMenuItem searchItem)
|
||||
public SuggestionListener(Android.Support.V4.Widget.CursorAdapter suggestionsAdapter, GroupBaseActivity activity, IMenuItem searchItem)
|
||||
{
|
||||
_suggestionsAdapter = suggestionsAdapter;
|
||||
_activity = activity;
|
||||
@ -275,7 +345,7 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
class OnQueryTextListener: Java.Lang.Object, SearchView.IOnQueryTextListener
|
||||
class OnQueryTextListener: Java.Lang.Object, Android.Support.V7.Widget.SearchView.IOnQueryTextListener
|
||||
{
|
||||
private readonly GroupBaseActivity _activity;
|
||||
|
||||
@ -311,16 +381,15 @@ namespace keepass2android
|
||||
|
||||
MenuInflater inflater = MenuInflater;
|
||||
inflater.Inflate(Resource.Menu.group, menu);
|
||||
if (Util.HasActionBar(this))
|
||||
{
|
||||
var searchManager = (SearchManager) GetSystemService(SearchService);
|
||||
IMenuItem searchItem = menu.FindItem(Resource.Id.menu_search);
|
||||
var searchView = (SearchView) searchItem.ActionView;
|
||||
var view = MenuItemCompat.GetActionView(searchItem);
|
||||
var searchView = view.JavaCast<Android.Support.V7.Widget.SearchView>();
|
||||
|
||||
searchView.SetSearchableInfo(searchManager.GetSearchableInfo(ComponentName));
|
||||
searchView.SetOnSuggestionListener(new SuggestionListener(searchView.SuggestionsAdapter, this, searchItem));
|
||||
searchView.SetOnQueryTextListener(new OnQueryTextListener(this));
|
||||
}
|
||||
|
||||
var item = menu.FindItem(Resource.Id.menu_sync);
|
||||
if (item != null)
|
||||
{
|
||||
@ -425,10 +494,11 @@ namespace keepass2android
|
||||
if (!String.IsNullOrEmpty(message))
|
||||
Toast.MakeText(this, message, ToastLength.Long).Show();
|
||||
|
||||
/*TODO
|
||||
// Tell the adapter to refresh it's list
|
||||
BaseAdapter adapter = (BaseAdapter)ListAdapter;
|
||||
adapter.NotifyDataSetChanged();
|
||||
|
||||
*/
|
||||
if (App.Kp2a.GetDb().OtpAuxFileIoc != null)
|
||||
{
|
||||
var task2 = new SyncOtpAuxFile(App.Kp2a.GetDb().OtpAuxFileIoc);
|
||||
@ -486,9 +556,10 @@ namespace keepass2android
|
||||
db.Dirty.Remove(Group);
|
||||
|
||||
// Tell the adapter to refresh it's list
|
||||
/*TODO
|
||||
BaseAdapter adapter = (BaseAdapter)ListAdapter;
|
||||
adapter.NotifyDataSetChanged();
|
||||
|
||||
*/
|
||||
|
||||
})
|
||||
.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => ((Dialog)sender).Dismiss())
|
||||
@ -555,15 +626,22 @@ namespace keepass2android
|
||||
|
||||
public void StartMovingElement()
|
||||
{
|
||||
|
||||
ShowInsertElementButtons();
|
||||
GroupView.ListView.InvalidateViews();
|
||||
/*TODOGroupView.ListView.InvalidateViews();
|
||||
BaseAdapter adapter = (BaseAdapter)ListAdapter;
|
||||
adapter.NotifyDataSetChanged();
|
||||
adapter.NotifyDataSetChanged();*/
|
||||
}
|
||||
|
||||
public void ShowInsertElementButtons()
|
||||
{
|
||||
GroupView.ShowInsertButtons();
|
||||
FindViewById(Resource.Id.fabCancelAddNew).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNewGroup).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNewEntry).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.fabAddNew).Visibility = ViewStates.Gone;
|
||||
|
||||
FindViewById(Resource.Id.bottom_bar).Visibility = ViewStates.Visible;
|
||||
FindViewById(Resource.Id.divider2).Visibility = ViewStates.Visible;
|
||||
}
|
||||
|
||||
public void StopMovingElement()
|
||||
@ -583,9 +661,9 @@ namespace keepass2android
|
||||
|
||||
AppTask = new NullTask();
|
||||
AppTask.SetupGroupBaseActivityButtons(this);
|
||||
GroupView.ListView.InvalidateViews();
|
||||
/*TODO GroupView.ListView.InvalidateViews();
|
||||
BaseAdapter adapter = (BaseAdapter)ListAdapter;
|
||||
adapter.NotifyDataSetChanged();
|
||||
adapter.NotifyDataSetChanged();*/
|
||||
}
|
||||
|
||||
|
||||
@ -594,5 +672,126 @@ namespace keepass2android
|
||||
GroupEditActivity.Launch(this, pwGroup.ParentGroup, pwGroup);
|
||||
}
|
||||
}
|
||||
|
||||
public class GroupListFragment : ListFragment, AbsListView.IMultiChoiceModeListener
|
||||
{
|
||||
public override void OnActivityCreated(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnActivityCreated(savedInstanceState);
|
||||
if (App.Kp2a.GetDb().CanWrite)
|
||||
{
|
||||
ListView.ChoiceMode = ChoiceMode.MultipleModal;
|
||||
ListView.SetMultiChoiceModeListener(this);
|
||||
ListView.ItemLongClick += delegate(object sender, AdapterView.ItemLongClickEventArgs args)
|
||||
{
|
||||
ListView.SetItemChecked(args.Position, true);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
ListView.ItemClick += (sender, args) => ((GroupListItemView) args.View).OnClick();
|
||||
|
||||
StyleScrollBars();
|
||||
|
||||
}
|
||||
|
||||
protected void StyleScrollBars()
|
||||
{
|
||||
ListView lv = ListView;
|
||||
lv.ScrollBarStyle =ScrollbarStyles.InsideInset;
|
||||
lv.TextFilterEnabled = true;
|
||||
}
|
||||
|
||||
public bool OnActionItemClicked(ActionMode mode, IMenuItem item)
|
||||
{
|
||||
switch (item.ItemId)
|
||||
{
|
||||
|
||||
case Resource.Id.menu_delete:
|
||||
/*Handler handler = new Handler();
|
||||
DeleteEntry task = new DeleteEntry(Activity, App.Kp2a, _entry,
|
||||
new GroupBaseActivity.RefreshTask(handler, ((GroupBaseActivity)Activity)));
|
||||
task.Start();*/
|
||||
Toast.MakeText(((GroupBaseActivity) Activity), "todo delete", ToastLength.Long).Show();
|
||||
return true;
|
||||
case Resource.Id.menu_move:
|
||||
/*NavigateToFolderAndLaunchMoveElementTask navMove =
|
||||
new NavigateToFolderAndLaunchMoveElementTask(_entry.ParentGroup, _entry.Uuid, _isSearchResult);
|
||||
((GroupBaseActivity)Activity).StartTask(navMove);*/
|
||||
Toast.MakeText(((GroupBaseActivity)Activity), "todo move", ToastLength.Long).Show();
|
||||
return true;
|
||||
/*TODO for search results case Resource.Id.menu_navigate:
|
||||
NavigateToFolder navNavigate = new NavigateToFolder(_entry.ParentGroup, true);
|
||||
((GroupBaseActivity)Activity).StartTask(navNavigate);
|
||||
return true;*/
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnCreateActionMode(ActionMode mode, IMenu menu)
|
||||
{
|
||||
MenuInflater inflater = Activity.MenuInflater;
|
||||
inflater.Inflate(Resource.Menu.group_entriesselected, menu);
|
||||
//mode.Title = "Select Items";
|
||||
Android.Util.Log.Debug("KP2A", "Create action mode" + mode);
|
||||
((PwGroupListAdapter)ListView.Adapter).NotifyDataSetChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDestroyActionMode(ActionMode mode)
|
||||
{
|
||||
Android.Util.Log.Debug("KP2A", "Destroy action mode" + mode);
|
||||
|
||||
((PwGroupListAdapter)ListView.Adapter).NotifyDataSetChanged();
|
||||
}
|
||||
|
||||
public bool OnPrepareActionMode(ActionMode mode, IMenu menu)
|
||||
{
|
||||
Android.Util.Log.Debug("KP2A", "Prepare action mode" + mode);
|
||||
((PwGroupListAdapter)ListView.Adapter).NotifyDataSetChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnItemCheckedStateChanged(ActionMode mode, int position, long id, bool @checked)
|
||||
{
|
||||
var menuItem = mode.Menu.FindItem(Resource.Id.menu_edit);
|
||||
if (menuItem != null)
|
||||
{
|
||||
menuItem.SetVisible(IsOnlyOneGroupChecked());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private bool IsOnlyOneGroupChecked()
|
||||
{
|
||||
var checkedItems = ListView.CheckedItemPositions;
|
||||
bool hadCheckedGroup = false;
|
||||
if (checkedItems != null)
|
||||
{
|
||||
for (int i = 0; i < checkedItems.Size(); i++)
|
||||
{
|
||||
if (checkedItems.ValueAt(i))
|
||||
{
|
||||
if (hadCheckedGroup)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((PwGroupListAdapter) ListAdapter).IsGroupAtPosition(checkedItems.KeyAt(i)))
|
||||
{
|
||||
hadCheckedGroup = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hadCheckedGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,7 @@ namespace keepass2android
|
||||
SetContentView (Resource.Layout.group_edit);
|
||||
|
||||
ImageButton iconButton = (ImageButton)FindViewById (Resource.Id.icon_button);
|
||||
iconButton.SetScaleType(ImageView.ScaleType.FitXy);
|
||||
iconButton.Click += (sender, e) =>
|
||||
{
|
||||
IconPickerActivity.Launch (this);
|
||||
|
@ -24,7 +24,7 @@ using Android.Widget;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar")]
|
||||
[Activity(Label = "@string/app_name", Theme = "@style/MyTheme_ActionBar")]
|
||||
public class IconPickerActivity : LockCloseActivity
|
||||
{
|
||||
public const String KeyIconId = "icon_id";
|
||||
|
@ -71,7 +71,7 @@ namespace keepass2android
|
||||
/// <summary>
|
||||
/// Launcher activity of Keepass2Android. This activity usually forwards to FileSelect but may show the revision dialog after installation or updates.
|
||||
/// </summary>
|
||||
[Activity (Label = AppNames.AppName, MainLauncher = true, Theme="@style/Base")]
|
||||
[Activity(Label = AppNames.AppName, MainLauncher = true, Theme = "@style/MyTheme_ActionBar")]
|
||||
public class KeePass : LifecycleDebugActivity
|
||||
{
|
||||
public const Result ExitNormal = Result.FirstUser;
|
||||
@ -167,6 +167,9 @@ namespace keepass2android
|
||||
{
|
||||
|
||||
}
|
||||
#if DEBUG
|
||||
showChangeLog = false;
|
||||
#endif
|
||||
|
||||
if (showChangeLog)
|
||||
{
|
||||
|
@ -19,11 +19,12 @@ using System;
|
||||
using Android.App;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Support.V7.App;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
|
||||
public abstract class LifecycleDebugActivity : Activity
|
||||
public abstract class LifecycleDebugActivity : AppCompatActivity
|
||||
{
|
||||
protected LifecycleDebugActivity (IntPtr javaReference, JniHandleOwnership transfer)
|
||||
: base(javaReference, transfer)
|
||||
|
@ -34,6 +34,11 @@ using Java.Net;
|
||||
using Android.Preferences;
|
||||
using Android.Text;
|
||||
using Android.Content.PM;
|
||||
using Android.Graphics;
|
||||
using Android.Support.Design.Widget;
|
||||
using Android.Support.V4.Widget;
|
||||
using Android.Support.V7.App;
|
||||
using keepass2android;
|
||||
using KeePassLib.Keys;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
@ -41,21 +46,23 @@ using Keepass2android.Pluginsdk;
|
||||
using OtpKeyProv;
|
||||
using keepass2android.Io;
|
||||
using keepass2android.Utils;
|
||||
using Exception = System.Exception;
|
||||
|
||||
using File = Java.IO.File;
|
||||
using FileNotFoundException = Java.IO.FileNotFoundException;
|
||||
using MemoryStream = System.IO.MemoryStream;
|
||||
|
||||
using Object = Java.Lang.Object;
|
||||
using Process = Android.OS.Process;
|
||||
using String = System.String;
|
||||
|
||||
using KeeChallenge;
|
||||
using AlertDialog = Android.App.AlertDialog;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = "@string/app_name",
|
||||
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
|
||||
LaunchMode = LaunchMode.SingleInstance,
|
||||
Theme = "@style/Base")]
|
||||
Theme = "@style/MyTheme")] /*caution: also contained in AndroidManifest.xml*/
|
||||
//TODO: rotating device crashes the app
|
||||
public class PasswordActivity : LockingActivity {
|
||||
|
||||
enum KeyProviders
|
||||
@ -144,6 +151,10 @@ namespace keepass2android
|
||||
private ActivityDesign _design;
|
||||
private bool _performingLoad;
|
||||
private bool _keepPasswordInOnResume;
|
||||
private Typeface _passwordFont;
|
||||
|
||||
private ActionBarDrawerToggle mDrawerToggle;
|
||||
private DrawerLayout _drawerLayout;
|
||||
|
||||
|
||||
public PasswordActivity (IntPtr javaReference, JniHandleOwnership transfer)
|
||||
@ -300,6 +311,8 @@ namespace keepass2android
|
||||
{
|
||||
if (KeyProviderType == KeyProviders.KeyFile)
|
||||
{
|
||||
//TODO: if the user has not yet selected a keyfile, _keyFileOrProvider is empty which
|
||||
//gives an (unhandled) exception here
|
||||
var iocKeyfile = IOConnectionInfo.UnserializeFromString(_keyFileOrProvider);
|
||||
|
||||
App.Kp2a.GetFileStorage(iocKeyfile)
|
||||
@ -679,7 +692,6 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
|
||||
|
||||
Intent i = Intent;
|
||||
|
||||
//only load the AppTask if this is the "first" OnCreate (not because of kill/resume, i.e. savedInstanceState==null)
|
||||
@ -748,6 +760,10 @@ namespace keepass2android
|
||||
|
||||
|
||||
SetContentView(Resource.Layout.password);
|
||||
|
||||
InitializeToolbar();
|
||||
|
||||
|
||||
InitializeFilenameView();
|
||||
|
||||
if (KeyProviderType == KeyProviders.KeyFile)
|
||||
@ -756,33 +772,44 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
|
||||
|
||||
FindViewById<EditText>(Resource.Id.password).TextChanged +=
|
||||
var passwordEdit = FindViewById<EditText>(Resource.Id.password);
|
||||
passwordEdit.TextChanged +=
|
||||
(sender, args) =>
|
||||
{
|
||||
_password = FindViewById<EditText>(Resource.Id.password).Text;
|
||||
_password = passwordEdit.Text;
|
||||
UpdateOkButtonState();
|
||||
};
|
||||
FindViewById<EditText>(Resource.Id.password).EditorAction += (sender, args) =>
|
||||
passwordEdit.EditorAction += (sender, args) =>
|
||||
{
|
||||
if ((args.ActionId == ImeAction.Done) || ((args.ActionId == ImeAction.ImeNull) && (args.Event.Action == KeyEventActions.Down)))
|
||||
OnOk();
|
||||
};
|
||||
passwordEdit.FocusChange += (sender, args) =>
|
||||
{
|
||||
FindViewById(Resource.Id.unlock_img_button).Visibility = args.HasFocus ? ViewStates.Visible : ViewStates.Gone;
|
||||
};
|
||||
|
||||
FindViewById<EditText>(Resource.Id.pass_otpsecret).TextChanged += (sender, args) => UpdateOkButtonState();
|
||||
|
||||
|
||||
EditText passwordEdit = FindViewById<EditText>(Resource.Id.password);
|
||||
passwordEdit.Text = _password;
|
||||
passwordEdit.RequestFocus();
|
||||
Window.SetSoftInputMode(SoftInput.StateVisible);
|
||||
|
||||
InitializeOkButton();
|
||||
|
||||
var passwordFont = Typeface.CreateFromAsset(Assets, "SourceCodePro-Regular.ttf");
|
||||
passwordEdit.Typeface = passwordFont;
|
||||
|
||||
|
||||
FindViewById(Resource.Id.unlock_img_button).Click += (sender, args) => OnOk();
|
||||
|
||||
InitializeBottomBarButtons();
|
||||
|
||||
InitializePasswordModeSpinner();
|
||||
|
||||
InitializeOtpSecretSpinner();
|
||||
|
||||
InitializeNavDrawerButtons();
|
||||
|
||||
UpdateOkButtonState();
|
||||
|
||||
InitializeTogglePasswordButton();
|
||||
@ -800,6 +827,69 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeNavDrawerButtons()
|
||||
{
|
||||
FindViewById(Resource.Id.btn_nav_change_db).Click += (sender, args) =>
|
||||
{
|
||||
GoToFileSelectActivity();
|
||||
};
|
||||
|
||||
FindViewById(Resource.Id.btn_nav_donate).Click += (sender, args) =>
|
||||
{
|
||||
Util.GotoDonateUrl(this);
|
||||
};
|
||||
FindViewById(Resource.Id.btn_nav_about).Click += (sender, args) =>
|
||||
{
|
||||
AboutDialog dialog = new AboutDialog(this);
|
||||
dialog.Show();
|
||||
};
|
||||
|
||||
FindViewById(Resource.Id.btn_nav_settings).Click += (sender, args) =>
|
||||
{
|
||||
AppSettingsActivity.Launch(this);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private void InitializeToolbar()
|
||||
{
|
||||
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
|
||||
|
||||
SetSupportActionBar(toolbar);
|
||||
|
||||
var collapsingToolbar = FindViewById<CollapsingToolbarLayout>(Resource.Id.collapsing_toolbar);
|
||||
collapsingToolbar.SetTitle(GetString(Resource.String.unlock_database_title));
|
||||
|
||||
_drawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
|
||||
mDrawerToggle = new ActionBarDrawerToggle(this, _drawerLayout,
|
||||
Resource.String.menu_open,
|
||||
Resource.String.menu_close);
|
||||
|
||||
|
||||
_drawerLayout.SetDrawerListener(mDrawerToggle);
|
||||
|
||||
|
||||
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
SupportActionBar.SetHomeButtonEnabled(true);
|
||||
mDrawerToggle.SyncState();
|
||||
|
||||
//TODO REMOVE
|
||||
//SupportActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
//SupportActionBar.SetDisplayShowHomeEnabled(true);
|
||||
|
||||
//toolbar.NavigationClick += (sender, args) => OnBackPressed();
|
||||
}
|
||||
|
||||
public override void OnBackPressed()
|
||||
{
|
||||
if (_drawerLayout.IsDrawerOpen((int) GravityFlags.Start))
|
||||
{
|
||||
_drawerLayout.CloseDrawer((int)GravityFlags.Start);
|
||||
return;
|
||||
}
|
||||
base.OnBackPressed();
|
||||
}
|
||||
|
||||
private void InitializeOtpSecretSpinner()
|
||||
{
|
||||
Spinner spinner = FindViewById<Spinner>(Resource.Id.otpsecret_format_spinner);
|
||||
@ -892,13 +982,15 @@ namespace keepass2android
|
||||
return true;
|
||||
}
|
||||
|
||||
private void InitializeOkButton()
|
||||
private void InitializeBottomBarButtons()
|
||||
{
|
||||
Button confirmButton = (Button) FindViewById(Resource.Id.pass_ok);
|
||||
confirmButton.Click += (sender, e) =>
|
||||
{
|
||||
OnOk();
|
||||
};
|
||||
|
||||
FindViewById(Resource.Id.change_db).Click += (sender, args) => GoToFileSelectActivity();
|
||||
}
|
||||
|
||||
private void OnOk()
|
||||
@ -1012,17 +1104,18 @@ namespace keepass2android
|
||||
|
||||
private void UpdateOkButtonState()
|
||||
{
|
||||
bool enabled = false;
|
||||
switch (KeyProviderType)
|
||||
{
|
||||
case KeyProviders.None:
|
||||
FindViewById(Resource.Id.pass_ok).Enabled = true;
|
||||
enabled = true;
|
||||
break;
|
||||
case KeyProviders.KeyFile:
|
||||
FindViewById(Resource.Id.pass_ok).Enabled = _keyFileOrProvider != "" || _password != "";
|
||||
enabled = _keyFileOrProvider != "" || _password != "";
|
||||
break;
|
||||
case KeyProviders.Otp:
|
||||
|
||||
bool enabled = true;
|
||||
enabled = true;
|
||||
if (_otpInfo == null)
|
||||
enabled = false;
|
||||
else
|
||||
@ -1040,18 +1133,20 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
FindViewById(Resource.Id.pass_ok).Enabled = enabled;
|
||||
|
||||
break;
|
||||
case KeyProviders.OtpRecovery:
|
||||
case KeyProviders.ChalRecovery:
|
||||
FindViewById(Resource.Id.pass_ok).Enabled = FindViewById<EditText>(Resource.Id.pass_otpsecret).Text != "";
|
||||
enabled = FindViewById<EditText>(Resource.Id.pass_otpsecret).Text != "";
|
||||
break;
|
||||
case KeyProviders.Challenge:
|
||||
FindViewById(Resource.Id.pass_ok).Enabled = _challengeSecret != null;
|
||||
enabled = _challengeSecret != null;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
FindViewById(Resource.Id.pass_ok).Enabled = enabled;
|
||||
FindViewById(Resource.Id.unlock_img_button).Enabled = enabled;
|
||||
}
|
||||
|
||||
private void UpdateKeyProviderUiState()
|
||||
@ -1216,11 +1311,22 @@ namespace keepass2android
|
||||
if (_showPassword)
|
||||
{
|
||||
password.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
|
||||
SetPasswordTypeface(password);
|
||||
}
|
||||
else
|
||||
{
|
||||
password.InputType = InputTypes.ClassText | InputTypes.TextVariationPassword;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SetPasswordTypeface(TextView textView)
|
||||
{
|
||||
if (_passwordFont == null)
|
||||
{
|
||||
_passwordFont = Typeface.CreateFromAsset(Assets, "SourceCodePro-Regular.ttf");
|
||||
}
|
||||
textView.Typeface = _passwordFont;
|
||||
}
|
||||
|
||||
private void SetNewDefaultFile()
|
||||
@ -1514,14 +1620,6 @@ namespace keepass2android
|
||||
|
||||
private void InitializeFilenameView() {
|
||||
SetEditText(Resource.Id.filename, App.Kp2a.GetFileStorage(_ioConnection).GetDisplayName(_ioConnection));
|
||||
if (App.Kp2a.FileDbHelper.NumberOfRecentFiles() < 2)
|
||||
{
|
||||
FindViewById(Resource.Id.filename_group).Visibility = ViewStates.Gone;
|
||||
}
|
||||
else
|
||||
{
|
||||
FindViewById(Resource.Id.filename_group).Visibility = ViewStates.Visible;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1548,28 +1646,11 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnCreateOptionsMenu(IMenu menu) {
|
||||
base.OnCreateOptionsMenu(menu);
|
||||
|
||||
MenuInflater inflate = MenuInflater;
|
||||
inflate.Inflate(Resource.Menu.password, menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnOptionsItemSelected(IMenuItem item) {
|
||||
switch ( item.ItemId ) {
|
||||
case Resource.Id.menu_about:
|
||||
AboutDialog dialog = new AboutDialog(this);
|
||||
dialog.Show();
|
||||
return true;
|
||||
|
||||
case Resource.Id.menu_app_settings:
|
||||
AppSettingsActivity.Launch(this);
|
||||
return true;
|
||||
|
||||
case Resource.Id.menu_change_db:
|
||||
GoToFileSelectActivity();
|
||||
case Android.Resource.Id.Home:
|
||||
_drawerLayout.OpenDrawer(Android.Support.V4.View.GravityCompat.Start);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/Base" android:name="keepass2android.PasswordActivity">
|
||||
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/MyTheme" android:name="keepass2android.PasswordActivity">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
@ -57,7 +57,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/Base" android:name="keepass2android.PasswordActivity">
|
||||
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/MyTheme" android:name="keepass2android.PasswordActivity">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
@ -40,7 +40,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/Base" android:name="keepass2android.PasswordActivity">
|
||||
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/MyTheme" android:name="keepass2android.PasswordActivity">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
@ -276,6 +276,11 @@ namespace keepass2android
|
||||
return position;
|
||||
}
|
||||
|
||||
public bool IsGroupAtPosition(int position)
|
||||
{
|
||||
return position < _groupsForViewing.Count;
|
||||
}
|
||||
|
||||
public override long GetItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
@ -288,6 +293,7 @@ namespace keepass2android
|
||||
} else {
|
||||
return CreateEntryView(position - size, convertView);
|
||||
}
|
||||
//TODO remove right arrow in actionmode
|
||||
}
|
||||
|
||||
private View CreateGroupView(int position, View convertView) {
|
||||
|
@ -16,7 +16,7 @@ namespace keepass2android
|
||||
{
|
||||
[Activity(Label = "@string/app_name",
|
||||
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/Base")]
|
||||
Theme = "@style/MyTheme_ActionBar")]
|
||||
[IntentFilter(new[] { Strings.ActionQueryCredentials},
|
||||
Categories = new[] { Intent.CategoryDefault })]
|
||||
[IntentFilter(new[] { Strings.ActionQueryCredentialsForOwnPackage },
|
||||
|
@ -30,7 +30,7 @@ using KeePassLib.Serialization;
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
|
||||
Theme = "@style/Base")]
|
||||
Theme = "@style/MyTheme")]
|
||||
public class QuickUnlock : LifecycleDebugActivity
|
||||
{
|
||||
private IOConnectionInfo _ioc;
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 773 B |
Before Width: | Height: | Size: 968 B |
Before Width: | Height: | Size: 196 B |