From 023aba2b60d576855fc544b26e4b7a8499615be1 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 18 Sep 2018 11:40:06 +0200 Subject: [PATCH 1/8] Remove Magikeyboard and Model modules for easier integration --- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 26 ++ .../magikeyboard/EntryRetrieverActivity.java | 5 +- .../KeyboardEntryNotificationService.java | 9 +- .../keepass}/magikeyboard/MagikIME.java | 9 +- .../keepass/magikeyboard/Utility.java | 6 + .../receiver/LockBroadcastReceiver.java | 2 +- .../NotificationDeleteBroadcastReceiver.java | 8 +- .../settings/MagikIMESettings.java | 4 +- .../settings/MagikIMESettingsFragment.java | 6 +- .../com/kunzisoft/keepass/model}/Entry.java | 2 +- .../selection/EntrySelectionHelper.java | 2 +- .../settings/NestedSettingsFragment.java | 2 +- .../res/drawable/ic_backspace_white_24dp.xml | 0 .../res/drawable/ic_comment_white_24dp.xml | 0 .../ic_keyboard_return_white_24dp.xml | 0 .../res/drawable/ic_keyboard_white_24dp.xml | 0 .../main/res/drawable/ic_link_black_24dp.xml | 0 .../main/res/drawable/ic_list_white_24dp.xml | 0 .../res/drawable/ic_password_white_24dp.xml | 0 .../res/drawable/ic_person_white_24dp.xml | 0 .../res/drawable/ic_vpn_key_white_24dp.xml | 0 .../src/main/res/drawable/key_background.xml | 0 .../res/drawable/key_background_normal.xml | 0 .../res/drawable/key_background_pressed.xml | 0 .../src/main/res/layout/empty.xml | 0 .../src/main/res/layout/key_preview.xml | 0 .../src/main/res/layout/keyboard.xml | 0 app/src/main/res/values/colors.xml | 5 + app/src/main/res/values/strings.xml | 44 ++ .../src/main/res/xml/keyboard_fields_list.xml | 0 .../src/main/res/xml/keyboard_password.xml | 0 .../main/res/xml/keyboard_password_entry.xml | 0 .../src/main/res/xml/keyboard_preferences.xml | 0 .../src/main/res/xml/method.xml | 0 .../com/kunzisoft/keepass/.gitignore | 1 - .../bouncycastle/asn1/util/ASN1Dump.java.orig | 440 ------------------ keepass-model/.gitignore | 1 - keepass-model/build.gradle | 26 -- keepass-model/proguard-rules.pro | 21 - keepass-model/src/main/AndroidManifest.xml | 2 - magikeyboard/.gitignore | 1 - magikeyboard/build.gradle | 33 -- magikeyboard/proguard-rules.pro | 21 - magikeyboard/src/main/AndroidManifest.xml | 31 -- .../com/kunzisoft/magikeyboard/Utility.java | 6 - .../res/drawable/ic_lock_open_white_24dp.xml | 5 - .../main/res/drawable/ic_lock_white_24dp.xml | 9 - .../src/main/res/layout/activity_toolbar.xml | 16 - .../src/main/res/layout/list_fields.xml | 8 - .../src/main/res/layout/toolbar_default.xml | 9 - magikeyboard/src/main/res/values/colors.xml | 25 - magikeyboard/src/main/res/values/strings.xml | 64 --- settings.gradle | 2 +- 54 files changed, 109 insertions(+), 746 deletions(-) rename {magikeyboard/src/main/java/com/kunzisoft => app/src/main/java/com/kunzisoft/keepass}/magikeyboard/EntryRetrieverActivity.java (94%) rename {magikeyboard/src/main/java/com/kunzisoft => app/src/main/java/com/kunzisoft/keepass}/magikeyboard/KeyboardEntryNotificationService.java (93%) rename {magikeyboard/src/main/java/com/kunzisoft => app/src/main/java/com/kunzisoft/keepass}/magikeyboard/MagikIME.java (96%) create mode 100644 app/src/main/java/com/kunzisoft/keepass/magikeyboard/Utility.java rename {magikeyboard/src/main/java/com/kunzisoft => app/src/main/java/com/kunzisoft/keepass}/magikeyboard/receiver/LockBroadcastReceiver.java (91%) rename {magikeyboard/src/main/java/com/kunzisoft => app/src/main/java/com/kunzisoft/keepass}/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java (80%) rename {magikeyboard/src/main/java/com/kunzisoft => app/src/main/java/com/kunzisoft/keepass}/magikeyboard/settings/MagikIMESettings.java (97%) rename {magikeyboard/src/main/java/com/kunzisoft => app/src/main/java/com/kunzisoft/keepass}/magikeyboard/settings/MagikIMESettingsFragment.java (67%) rename {keepass-model/src/main/java/com/kunzisoft/keepass_model => app/src/main/java/com/kunzisoft/keepass/model}/Entry.java (98%) rename {magikeyboard => app}/src/main/res/drawable/ic_backspace_white_24dp.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/ic_comment_white_24dp.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/ic_keyboard_return_white_24dp.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/ic_keyboard_white_24dp.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/ic_link_black_24dp.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/ic_list_white_24dp.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/ic_password_white_24dp.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/ic_person_white_24dp.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/ic_vpn_key_white_24dp.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/key_background.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/key_background_normal.xml (100%) rename {magikeyboard => app}/src/main/res/drawable/key_background_pressed.xml (100%) rename {magikeyboard => app}/src/main/res/layout/empty.xml (100%) rename {magikeyboard => app}/src/main/res/layout/key_preview.xml (100%) rename {magikeyboard => app}/src/main/res/layout/keyboard.xml (100%) rename {magikeyboard => app}/src/main/res/xml/keyboard_fields_list.xml (100%) rename {magikeyboard => app}/src/main/res/xml/keyboard_password.xml (100%) rename {magikeyboard => app}/src/main/res/xml/keyboard_password_entry.xml (100%) rename magikeyboard/src/main/res/xml/ime_preferences.xml => app/src/main/res/xml/keyboard_preferences.xml (100%) rename {magikeyboard => app}/src/main/res/xml/method.xml (100%) delete mode 100644 app/src/main/resources/com/kunzisoft/keepass/.gitignore delete mode 100644 app/src/main/resources/org/bouncycastle/asn1/util/ASN1Dump.java.orig delete mode 100644 keepass-model/.gitignore delete mode 100644 keepass-model/build.gradle delete mode 100644 keepass-model/proguard-rules.pro delete mode 100644 keepass-model/src/main/AndroidManifest.xml delete mode 100644 magikeyboard/.gitignore delete mode 100644 magikeyboard/build.gradle delete mode 100644 magikeyboard/proguard-rules.pro delete mode 100644 magikeyboard/src/main/AndroidManifest.xml delete mode 100644 magikeyboard/src/main/java/com/kunzisoft/magikeyboard/Utility.java delete mode 100644 magikeyboard/src/main/res/drawable/ic_lock_open_white_24dp.xml delete mode 100644 magikeyboard/src/main/res/drawable/ic_lock_white_24dp.xml delete mode 100644 magikeyboard/src/main/res/layout/activity_toolbar.xml delete mode 100644 magikeyboard/src/main/res/layout/list_fields.xml delete mode 100644 magikeyboard/src/main/res/layout/toolbar_default.xml delete mode 100644 magikeyboard/src/main/res/values/colors.xml delete mode 100644 magikeyboard/src/main/res/values/strings.xml diff --git a/app/build.gradle b/app/build.gradle index e53c02032..52915c4e8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -107,9 +107,7 @@ dependencies { implementation 'biz.source_code:base64coder:2010-12-19' implementation 'com.google.code.gson:gson:2.8.4' implementation 'com.google.guava:guava:23.0-android' - // Icon pack, classic for all, material for libre and pro + // Icon pack implementation project(path: ':icon-pack-classic') implementation project(path: ':icon-pack-material') - implementation project(path: ':magikeyboard') - implementation project(path: ':keepass-model') } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 36986775d..158909098 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -132,7 +132,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/EntryRetrieverActivity.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/EntryRetrieverActivity.java similarity index 94% rename from magikeyboard/src/main/java/com/kunzisoft/magikeyboard/EntryRetrieverActivity.java rename to app/src/main/java/com/kunzisoft/keepass/magikeyboard/EntryRetrieverActivity.java index 8b2b1fc76..607316b5c 100644 --- a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/EntryRetrieverActivity.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/EntryRetrieverActivity.java @@ -1,4 +1,4 @@ -package com.kunzisoft.magikeyboard; +package com.kunzisoft.keepass.magikeyboard; import android.app.Activity; import android.content.Intent; @@ -9,7 +9,8 @@ import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.util.Log; -import com.kunzisoft.keepass_model.Entry; +import com.kunzisoft.keepass.R; +import com.kunzisoft.keepass.model.Entry; public class EntryRetrieverActivity extends AppCompatActivity { diff --git a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/KeyboardEntryNotificationService.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java similarity index 93% rename from magikeyboard/src/main/java/com/kunzisoft/magikeyboard/KeyboardEntryNotificationService.java rename to app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java index e7f53f765..f31823c26 100644 --- a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/KeyboardEntryNotificationService.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java @@ -1,4 +1,4 @@ -package com.kunzisoft.magikeyboard; +package com.kunzisoft.keepass.magikeyboard; import android.app.NotificationChannel; import android.app.NotificationManager; @@ -12,11 +12,12 @@ import android.os.IBinder; import android.support.v4.app.NotificationCompat; import android.util.Log; -import com.kunzisoft.magikeyboard.receiver.LockBroadcastReceiver; -import com.kunzisoft.magikeyboard.receiver.NotificationDeleteBroadcastReceiver; +import com.kunzisoft.keepass.R; +import com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver; +import com.kunzisoft.keepass.magikeyboard.receiver.NotificationDeleteBroadcastReceiver; import static android.content.ContentValues.TAG; -import static com.kunzisoft.magikeyboard.receiver.LockBroadcastReceiver.LOCK_ACTION; +import static com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver.LOCK_ACTION; public class KeyboardEntryNotificationService extends Service { diff --git a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/MagikIME.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java similarity index 96% rename from magikeyboard/src/main/java/com/kunzisoft/magikeyboard/MagikIME.java rename to app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java index 8ae649b93..eaba92a89 100644 --- a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/MagikIME.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java @@ -17,7 +17,7 @@ * along with KeePass DX. If not, see . * */ -package com.kunzisoft.magikeyboard; +package com.kunzisoft.keepass.magikeyboard; import android.content.Context; import android.content.Intent; @@ -36,10 +36,11 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; -import com.kunzisoft.keepass_model.Entry; -import com.kunzisoft.magikeyboard.receiver.LockBroadcastReceiver; +import com.kunzisoft.keepass.R; +import com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver; +import com.kunzisoft.keepass.model.Entry; -import static com.kunzisoft.magikeyboard.receiver.LockBroadcastReceiver.LOCK_ACTION; +import static com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver.LOCK_ACTION; public class MagikIME extends InputMethodService implements KeyboardView.OnKeyboardActionListener { diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/Utility.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/Utility.java new file mode 100644 index 000000000..5eecdae92 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/Utility.java @@ -0,0 +1,6 @@ +package com.kunzisoft.keepass.magikeyboard; + +public class Utility { + + +} diff --git a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/receiver/LockBroadcastReceiver.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/LockBroadcastReceiver.java similarity index 91% rename from magikeyboard/src/main/java/com/kunzisoft/magikeyboard/receiver/LockBroadcastReceiver.java rename to app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/LockBroadcastReceiver.java index bb4ac5841..721ff5220 100644 --- a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/receiver/LockBroadcastReceiver.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/LockBroadcastReceiver.java @@ -1,4 +1,4 @@ -package com.kunzisoft.magikeyboard.receiver; +package com.kunzisoft.keepass.magikeyboard.receiver; import android.content.BroadcastReceiver; import android.content.Context; diff --git a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java similarity index 80% rename from magikeyboard/src/main/java/com/kunzisoft/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java rename to app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java index e429b388b..80c71db13 100644 --- a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java @@ -1,13 +1,13 @@ -package com.kunzisoft.magikeyboard.receiver; +package com.kunzisoft.keepass.magikeyboard.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import com.kunzisoft.magikeyboard.KeyboardEntryNotificationService; -import com.kunzisoft.magikeyboard.MagikIME; -import com.kunzisoft.magikeyboard.R; +import com.kunzisoft.keepass.R; +import com.kunzisoft.keepass.magikeyboard.KeyboardEntryNotificationService; +import com.kunzisoft.keepass.magikeyboard.MagikIME; public class NotificationDeleteBroadcastReceiver extends BroadcastReceiver { diff --git a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/settings/MagikIMESettings.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettings.java similarity index 97% rename from magikeyboard/src/main/java/com/kunzisoft/magikeyboard/settings/MagikIMESettings.java rename to app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettings.java index e053954c5..493971306 100644 --- a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/settings/MagikIMESettings.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettings.java @@ -17,7 +17,7 @@ * along with KeePass DX. If not, see . * */ -package com.kunzisoft.magikeyboard.settings; +package com.kunzisoft.keepass.magikeyboard.settings; import android.os.Bundle; import android.support.v4.app.FragmentManager; @@ -25,7 +25,7 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.MenuItem; -import com.kunzisoft.magikeyboard.R; +import com.kunzisoft.keepass.R; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; diff --git a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/settings/MagikIMESettingsFragment.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettingsFragment.java similarity index 67% rename from magikeyboard/src/main/java/com/kunzisoft/magikeyboard/settings/MagikIMESettingsFragment.java rename to app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettingsFragment.java index a4727175f..7144cee68 100644 --- a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/settings/MagikIMESettingsFragment.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettingsFragment.java @@ -1,15 +1,15 @@ -package com.kunzisoft.magikeyboard.settings; +package com.kunzisoft.keepass.magikeyboard.settings; import android.os.Bundle; import android.support.v7.preference.PreferenceFragmentCompat; -import com.kunzisoft.magikeyboard.R; +import com.kunzisoft.keepass.R; public class MagikIMESettingsFragment extends PreferenceFragmentCompat { @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { // Load the preferences from an XML resource - setPreferencesFromResource(R.xml.ime_preferences, rootKey); + setPreferencesFromResource(R.xml.keyboard_preferences, rootKey); } } diff --git a/keepass-model/src/main/java/com/kunzisoft/keepass_model/Entry.java b/app/src/main/java/com/kunzisoft/keepass/model/Entry.java similarity index 98% rename from keepass-model/src/main/java/com/kunzisoft/keepass_model/Entry.java rename to app/src/main/java/com/kunzisoft/keepass/model/Entry.java index 02f334c50..db722499a 100644 --- a/keepass-model/src/main/java/com/kunzisoft/keepass_model/Entry.java +++ b/app/src/main/java/com/kunzisoft/keepass/model/Entry.java @@ -1,4 +1,4 @@ -package com.kunzisoft.keepass_model; +package com.kunzisoft.keepass.model; import android.os.Parcel; import android.os.Parcelable; diff --git a/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java b/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java index 70caafe3b..a70873b67 100644 --- a/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java +++ b/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java @@ -5,7 +5,7 @@ import android.content.Intent; import android.util.Log; import com.kunzisoft.keepass.database.PwEntry; -import com.kunzisoft.keepass_model.Entry; +import com.kunzisoft.keepass.model.Entry; public class EntrySelectionHelper { diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java index 48167cea2..6ccda6254 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java @@ -60,7 +60,7 @@ import com.kunzisoft.keepass.settings.preferenceDialogFragment.MemoryUsagePrefer import com.kunzisoft.keepass.settings.preferenceDialogFragment.ParallelismPreferenceDialogFragmentCompat; import com.kunzisoft.keepass.settings.preferenceDialogFragment.RoundsPreferenceDialogFragmentCompat; import com.kunzisoft.keepass.stylish.Stylish; -import com.kunzisoft.magikeyboard.settings.MagikIMESettings; +import com.kunzisoft.keepass.magikeyboard.settings.MagikIMESettings; public class NestedSettingsFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceClickListener { diff --git a/magikeyboard/src/main/res/drawable/ic_backspace_white_24dp.xml b/app/src/main/res/drawable/ic_backspace_white_24dp.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/ic_backspace_white_24dp.xml rename to app/src/main/res/drawable/ic_backspace_white_24dp.xml diff --git a/magikeyboard/src/main/res/drawable/ic_comment_white_24dp.xml b/app/src/main/res/drawable/ic_comment_white_24dp.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/ic_comment_white_24dp.xml rename to app/src/main/res/drawable/ic_comment_white_24dp.xml diff --git a/magikeyboard/src/main/res/drawable/ic_keyboard_return_white_24dp.xml b/app/src/main/res/drawable/ic_keyboard_return_white_24dp.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/ic_keyboard_return_white_24dp.xml rename to app/src/main/res/drawable/ic_keyboard_return_white_24dp.xml diff --git a/magikeyboard/src/main/res/drawable/ic_keyboard_white_24dp.xml b/app/src/main/res/drawable/ic_keyboard_white_24dp.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/ic_keyboard_white_24dp.xml rename to app/src/main/res/drawable/ic_keyboard_white_24dp.xml diff --git a/magikeyboard/src/main/res/drawable/ic_link_black_24dp.xml b/app/src/main/res/drawable/ic_link_black_24dp.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/ic_link_black_24dp.xml rename to app/src/main/res/drawable/ic_link_black_24dp.xml diff --git a/magikeyboard/src/main/res/drawable/ic_list_white_24dp.xml b/app/src/main/res/drawable/ic_list_white_24dp.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/ic_list_white_24dp.xml rename to app/src/main/res/drawable/ic_list_white_24dp.xml diff --git a/magikeyboard/src/main/res/drawable/ic_password_white_24dp.xml b/app/src/main/res/drawable/ic_password_white_24dp.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/ic_password_white_24dp.xml rename to app/src/main/res/drawable/ic_password_white_24dp.xml diff --git a/magikeyboard/src/main/res/drawable/ic_person_white_24dp.xml b/app/src/main/res/drawable/ic_person_white_24dp.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/ic_person_white_24dp.xml rename to app/src/main/res/drawable/ic_person_white_24dp.xml diff --git a/magikeyboard/src/main/res/drawable/ic_vpn_key_white_24dp.xml b/app/src/main/res/drawable/ic_vpn_key_white_24dp.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/ic_vpn_key_white_24dp.xml rename to app/src/main/res/drawable/ic_vpn_key_white_24dp.xml diff --git a/magikeyboard/src/main/res/drawable/key_background.xml b/app/src/main/res/drawable/key_background.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/key_background.xml rename to app/src/main/res/drawable/key_background.xml diff --git a/magikeyboard/src/main/res/drawable/key_background_normal.xml b/app/src/main/res/drawable/key_background_normal.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/key_background_normal.xml rename to app/src/main/res/drawable/key_background_normal.xml diff --git a/magikeyboard/src/main/res/drawable/key_background_pressed.xml b/app/src/main/res/drawable/key_background_pressed.xml similarity index 100% rename from magikeyboard/src/main/res/drawable/key_background_pressed.xml rename to app/src/main/res/drawable/key_background_pressed.xml diff --git a/magikeyboard/src/main/res/layout/empty.xml b/app/src/main/res/layout/empty.xml similarity index 100% rename from magikeyboard/src/main/res/layout/empty.xml rename to app/src/main/res/layout/empty.xml diff --git a/magikeyboard/src/main/res/layout/key_preview.xml b/app/src/main/res/layout/key_preview.xml similarity index 100% rename from magikeyboard/src/main/res/layout/key_preview.xml rename to app/src/main/res/layout/key_preview.xml diff --git a/magikeyboard/src/main/res/layout/keyboard.xml b/app/src/main/res/layout/keyboard.xml similarity index 100% rename from magikeyboard/src/main/res/layout/keyboard.xml rename to app/src/main/res/layout/keyboard.xml diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 6d1f08c8a..2a25749df 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -68,4 +68,9 @@ #c7c7c7 #999999 #565656 + + #3c474c + #263238 + #3c464c + #263238 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 643f3e375..fc7af7090 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -288,6 +288,50 @@ Lock the database. Go back to your main keyboard. + Magikeyboard + Magikeyboard (KeePass DX) + Magikeyboard settings + + Entry + + erase_entry_timeout_key + Timeout + Timeout to clear the keyboard entry + + notification_entry_key + Notification information + Show a notification when an entry is available + true + + Entry + %1$s available on Magikeyboard + %1$s + + notification_entry_slide_close_key + Clear at closing + Clear the keyboard entry when closing the notification + true + + Appearance + + theme_key + Theme + + Keys + key_vibrate_key + Vibrate on keypress + true + + key_vibrate_duration_key + Keypress vibration duration + + key_sound_key + Sound on keypress + false + + key_long_press_delay_key + Key long press delay + Allow no password Enable the open button if no password identification is selected Read only diff --git a/magikeyboard/src/main/res/xml/keyboard_fields_list.xml b/app/src/main/res/xml/keyboard_fields_list.xml similarity index 100% rename from magikeyboard/src/main/res/xml/keyboard_fields_list.xml rename to app/src/main/res/xml/keyboard_fields_list.xml diff --git a/magikeyboard/src/main/res/xml/keyboard_password.xml b/app/src/main/res/xml/keyboard_password.xml similarity index 100% rename from magikeyboard/src/main/res/xml/keyboard_password.xml rename to app/src/main/res/xml/keyboard_password.xml diff --git a/magikeyboard/src/main/res/xml/keyboard_password_entry.xml b/app/src/main/res/xml/keyboard_password_entry.xml similarity index 100% rename from magikeyboard/src/main/res/xml/keyboard_password_entry.xml rename to app/src/main/res/xml/keyboard_password_entry.xml diff --git a/magikeyboard/src/main/res/xml/ime_preferences.xml b/app/src/main/res/xml/keyboard_preferences.xml similarity index 100% rename from magikeyboard/src/main/res/xml/ime_preferences.xml rename to app/src/main/res/xml/keyboard_preferences.xml diff --git a/magikeyboard/src/main/res/xml/method.xml b/app/src/main/res/xml/method.xml similarity index 100% rename from magikeyboard/src/main/res/xml/method.xml rename to app/src/main/res/xml/method.xml diff --git a/app/src/main/resources/com/kunzisoft/keepass/.gitignore b/app/src/main/resources/com/kunzisoft/keepass/.gitignore deleted file mode 100644 index 48c029696..000000000 --- a/app/src/main/resources/com/kunzisoft/keepass/.gitignore +++ /dev/null @@ -1 +0,0 @@ -R.java diff --git a/app/src/main/resources/org/bouncycastle/asn1/util/ASN1Dump.java.orig b/app/src/main/resources/org/bouncycastle/asn1/util/ASN1Dump.java.orig deleted file mode 100644 index 68c65cbe1..000000000 --- a/app/src/main/resources/org/bouncycastle/asn1/util/ASN1Dump.java.orig +++ /dev/null @@ -1,440 +0,0 @@ -package org.bouncycastle.asn1.util; - -import org.bouncycastle.asn1.ASN1OctetString; -import org.bouncycastle.asn1.ASN1Sequence; -import org.bouncycastle.asn1.ASN1Set; -import org.bouncycastle.asn1.BERConstructedOctetString; -import org.bouncycastle.asn1.BERConstructedSequence; -import org.bouncycastle.asn1.BERSequence; -import org.bouncycastle.asn1.BERSet; -import org.bouncycastle.asn1.BERTaggedObject; -import org.bouncycastle.asn1.DERBMPString; -import org.bouncycastle.asn1.DERBitString; -import org.bouncycastle.asn1.DERBoolean; -import org.bouncycastle.asn1.DERConstructedSequence; -import org.bouncycastle.asn1.DERConstructedSet; -import org.bouncycastle.asn1.DEREncodable; -import org.bouncycastle.asn1.DERGeneralizedTime; -import org.bouncycastle.asn1.DERIA5String; -import org.bouncycastle.asn1.DERInteger; -import org.bouncycastle.asn1.DERNull; -import org.bouncycastle.asn1.DERObject; -import org.bouncycastle.asn1.DERObjectIdentifier; -import org.bouncycastle.asn1.DEROctetString; -import org.bouncycastle.asn1.DERPrintableString; -import org.bouncycastle.asn1.DERSequence; -import org.bouncycastle.asn1.DERSet; -import org.bouncycastle.asn1.DERT61String; -import org.bouncycastle.asn1.DERTaggedObject; -import org.bouncycastle.asn1.DERUTCTime; -import org.bouncycastle.asn1.DERUTF8String; -import org.bouncycastle.asn1.DERUnknownTag; -import org.bouncycastle.asn1.DERVisibleString; -import org.bouncycastle.asn1.DERApplicationSpecific; -import org.bouncycastle.asn1.DERTags; -import org.bouncycastle.asn1.BERApplicationSpecific; -import org.bouncycastle.util.encoders.Hex; - -import java.util.Enumeration; -import java.io.IOException; - -public class ASN1Dump -{ - private static final String TAB = " "; - private static final int SAMPLE_SIZE = 32; - - /** - * dump a DER object as a formatted string with indentation - * - * @param obj the DERObject to be dumped out. - */ - static String _dumpAsString( - String indent, - boolean verbose, - DERObject obj) - { - String nl = System.getProperty("line.separator"); - if (obj instanceof ASN1Sequence) - { - StringBuffer buf = new StringBuffer(); - Enumeration e = ((ASN1Sequence)obj).getObjects(); - String tab = indent + TAB; - - buf.append(indent); - if (obj instanceof BERConstructedSequence) - { - buf.append("BER ConstructedSequence"); - } - else if (obj instanceof DERConstructedSequence) - { - buf.append("DER ConstructedSequence"); - } - else if (obj instanceof BERSequence) - { - buf.append("BER Sequence"); - } - else if (obj instanceof DERSequence) - { - buf.append("DER Sequence"); - } - else - { - buf.append("Sequence"); - } - - buf.append(nl); - - while (e.hasMoreElements()) - { - Object o = e.nextElement(); - - if (o == null || o.equals(new DERNull())) - { - buf.append(tab); - buf.append("NULL"); - buf.append(nl); - } - else if (o instanceof DERObject) - { - buf.append(_dumpAsString(tab, verbose, (DERObject)o)); - } - else - { - buf.append(_dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject())); - } - } - return buf.toString(); - } - else if (obj instanceof DERTaggedObject) - { - StringBuffer buf = new StringBuffer(); - String tab = indent + TAB; - - buf.append(indent); - if (obj instanceof BERTaggedObject) - { - buf.append("BER Tagged ["); - } - else - { - buf.append("Tagged ["); - } - - DERTaggedObject o = (DERTaggedObject)obj; - - buf.append(Integer.toString(o.getTagNo())); - buf.append(']'); - - if (!o.isExplicit()) - { - buf.append(" IMPLICIT "); - } - - buf.append(nl); - - if (o.isEmpty()) - { - buf.append(tab); - buf.append("EMPTY"); - buf.append(nl); - } - else - { - buf.append(_dumpAsString(tab, verbose, o.getObject())); - } - - return buf.toString(); - } - else if (obj instanceof DERConstructedSet) - { - StringBuffer buf = new StringBuffer(); - Enumeration e = ((ASN1Set)obj).getObjects(); - String tab = indent + TAB; - - buf.append(indent); - buf.append("ConstructedSet"); - buf.append(nl); - - while (e.hasMoreElements()) - { - Object o = e.nextElement(); - - if (o == null) - { - buf.append(tab); - buf.append("NULL"); - buf.append(nl); - } - else if (o instanceof DERObject) - { - buf.append(_dumpAsString(tab, verbose, (DERObject)o)); - } - else - { - buf.append(_dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject())); - } - } - return buf.toString(); - } - else if (obj instanceof BERSet) - { - StringBuffer buf = new StringBuffer(); - Enumeration e = ((ASN1Set)obj).getObjects(); - String tab = indent + TAB; - - buf.append(indent); - buf.append("BER Set"); - buf.append(nl); - - while (e.hasMoreElements()) - { - Object o = e.nextElement(); - - if (o == null) - { - buf.append(tab); - buf.append("NULL"); - buf.append(nl); - } - else if (o instanceof DERObject) - { - buf.append(_dumpAsString(tab, verbose, (DERObject)o)); - } - else - { - buf.append(_dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject())); - } - } - return buf.toString(); - } - else if (obj instanceof DERSet) - { - StringBuffer buf = new StringBuffer(); - Enumeration e = ((ASN1Set)obj).getObjects(); - String tab = indent + TAB; - - buf.append(indent); - buf.append("DER Set"); - buf.append(nl); - - while (e.hasMoreElements()) - { - Object o = e.nextElement(); - - if (o == null) - { - buf.append(tab); - buf.append("NULL"); - buf.append(nl); - } - else if (o instanceof DERObject) - { - buf.append(_dumpAsString(tab, verbose, (DERObject)o)); - } - else - { - buf.append(_dumpAsString(tab, verbose, ((DEREncodable)o).getDERObject())); - } - } - return buf.toString(); - } - else if (obj instanceof DERObjectIdentifier) - { - return indent + "ObjectIdentifier(" + ((DERObjectIdentifier)obj).getId() + ")" + nl; - } - else if (obj instanceof DERBoolean) - { - return indent + "Boolean(" + ((DERBoolean)obj).isTrue() + ")" + nl; - } - else if (obj instanceof DERInteger) - { - return indent + "Integer(" + ((DERInteger)obj).getValue() + ")" + nl; - } - else if (obj instanceof BERConstructedOctetString) - { - ASN1OctetString oct = (ASN1OctetString)obj; - if (verbose) - { - return indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] " + dumpBinaryDataAsString(indent, oct.getOctets()) + nl; - } - return indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] " + nl; - } - else if (obj instanceof DEROctetString) - { - ASN1OctetString oct = (ASN1OctetString)obj; - if (verbose) - { - return indent + "DER Octet String" + "[" + oct.getOctets().length + "] " + dumpBinaryDataAsString(indent, oct.getOctets()) + nl; - } - return indent + "DER Octet String" + "[" + oct.getOctets().length + "] " + nl; - } - else if (obj instanceof DERBitString) - { - DERBitString bt = (DERBitString)obj; - if (verbose) - { - return indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] " + dumpBinaryDataAsString(indent, bt.getBytes()) + nl; - } - return indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] " + nl; - } - else if (obj instanceof DERIA5String) - { - return indent + "IA5String(" + ((DERIA5String)obj).getString() + ") " + nl; - } - else if (obj instanceof DERUTF8String) - { - return indent + "UTF8String(" + ((DERUTF8String)obj).getString() + ") " + nl; - } - else if (obj instanceof DERPrintableString) - { - return indent + "PrintableString(" + ((DERPrintableString)obj).getString() + ") " + nl; - } - else if (obj instanceof DERVisibleString) - { - return indent + "VisibleString(" + ((DERVisibleString)obj).getString() + ") " + nl; - } - else if (obj instanceof DERBMPString) - { - return indent + "BMPString(" + ((DERBMPString)obj).getString() + ") " + nl; - } - else if (obj instanceof DERT61String) - { - return indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl; - } - else if (obj instanceof DERUTCTime) - { - return indent + "UTCTime(" + ((DERUTCTime)obj).getTime() + ") " + nl; - } - else if (obj instanceof DERGeneralizedTime) - { - return indent + "GeneralizedTime(" + ((DERGeneralizedTime)obj).getTime() + ") " + nl; - } - else if (obj instanceof DERUnknownTag) - { - return indent + "Unknown " + Integer.toString(((DERUnknownTag)obj).getTag(), 16) + " " + new String(Hex.encode(((DERUnknownTag)obj).getData())) + nl; - } - else if (obj instanceof BERApplicationSpecific) - { - return outputApplicationSpecific("BER", indent, verbose, obj, nl); - } - else if (obj instanceof DERApplicationSpecific) - { - return outputApplicationSpecific("DER", indent, verbose, obj, nl); - } - else - { - return indent + obj.toString() + nl; - } - } - - private static String outputApplicationSpecific(String type, String indent, boolean verbose, DERObject obj, String nl) - { - DERApplicationSpecific app = (DERApplicationSpecific)obj; - StringBuffer buf = new StringBuffer(); - - if (app.isConstructed()) - { - try - { - ASN1Sequence s = ASN1Sequence.getInstance(app.getObject(DERTags.SEQUENCE)); - buf.append(indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "]" + nl); - for (Enumeration e = s.getObjects(); e.hasMoreElements();) - { - buf.append(_dumpAsString(indent + TAB, verbose, (DERObject)e.nextElement())); - } - } - catch (IOException e) - { - buf.append(e); - } - return buf.toString(); - } - - return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + new String(Hex.encode(app.getContents())) + ")" + nl; - } - - /** - * dump out a DER object as a formatted string, in non-verbose mode. - * - * @param obj the DERObject to be dumped out. - * @return the resulting string. - */ - public static String dumpAsString( - Object obj) - { - return dumpAsString(obj, false); - } - - /** - * Dump out the object as a string. - * - * @param obj the object to be dumped - * @param verbose if true, dump out the contents of octet and bit strings. - * @return the resulting string. - */ - public static String dumpAsString( - Object obj, - boolean verbose) - { - if (obj instanceof DERObject) - { - return _dumpAsString("", verbose, (DERObject)obj); - } - else if (obj instanceof DEREncodable) - { - return _dumpAsString("", verbose, ((DEREncodable)obj).getDERObject()); - } - - return "unknown object type " + obj.toString(); - } - - private static String dumpBinaryDataAsString(String indent, byte[] bytes) - { - String nl = System.getProperty("line.separator"); - StringBuffer buf = new StringBuffer(); - - indent += TAB; - - buf.append(nl); - for (int i = 0; i < bytes.length; i += SAMPLE_SIZE) - { - if (bytes.length - i > SAMPLE_SIZE) - { - buf.append(indent); - buf.append(new String(Hex.encode(bytes, i, SAMPLE_SIZE))); - buf.append(TAB); - buf.append(calculateAscString(bytes, i, SAMPLE_SIZE)); - buf.append(nl); - } - else - { - buf.append(indent); - buf.append(new String(Hex.encode(bytes, i, bytes.length - i))); - for (int j = bytes.length - i; j != SAMPLE_SIZE; j++) - { - buf.append(" "); - } - buf.append(TAB); - buf.append(calculateAscString(bytes, i, bytes.length - i)); - buf.append(nl); - } - } - - return buf.toString(); - } - - private static String calculateAscString(byte[] bytes, int off, int len) - { - StringBuffer buf = new StringBuffer(); - - for (int i = off; i != off + len; i++) - { - if (bytes[i] >= ' ' && bytes[i] <= '~') - { - buf.append((char)bytes[i]); - } - } - - return buf.toString(); - } -} diff --git a/keepass-model/.gitignore b/keepass-model/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/keepass-model/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/keepass-model/build.gradle b/keepass-model/build.gradle deleted file mode 100644 index 176fe1e78..000000000 --- a/keepass-model/build.gradle +++ /dev/null @@ -1,26 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 27 - - - - defaultConfig { - minSdkVersion 14 - targetSdkVersion 27 - versionCode 1 - versionName "1.0" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) -} diff --git a/keepass-model/proguard-rules.pro b/keepass-model/proguard-rules.pro deleted file mode 100644 index f1b424510..000000000 --- a/keepass-model/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/keepass-model/src/main/AndroidManifest.xml b/keepass-model/src/main/AndroidManifest.xml deleted file mode 100644 index 4bb046d14..000000000 --- a/keepass-model/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - diff --git a/magikeyboard/.gitignore b/magikeyboard/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/magikeyboard/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/magikeyboard/build.gradle b/magikeyboard/build.gradle deleted file mode 100644 index 42a36a60a..000000000 --- a/magikeyboard/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 27 - - defaultConfig { - minSdkVersion 14 - targetSdkVersion 27 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - -} - -def supportVersion = "27.1.1" - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "com.android.support:appcompat-v7:$supportVersion" - implementation "com.android.support:preference-v7:$supportVersion" - implementation "com.android.support:preference-v14:$supportVersion" - implementation project(path: ':keepass-model') -} diff --git a/magikeyboard/proguard-rules.pro b/magikeyboard/proguard-rules.pro deleted file mode 100644 index f1b424510..000000000 --- a/magikeyboard/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/magikeyboard/src/main/AndroidManifest.xml b/magikeyboard/src/main/AndroidManifest.xml deleted file mode 100644 index 5e678663b..000000000 --- a/magikeyboard/src/main/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/Utility.java b/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/Utility.java deleted file mode 100644 index 8095f1246..000000000 --- a/magikeyboard/src/main/java/com/kunzisoft/magikeyboard/Utility.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.kunzisoft.magikeyboard; - -public class Utility { - - -} diff --git a/magikeyboard/src/main/res/drawable/ic_lock_open_white_24dp.xml b/magikeyboard/src/main/res/drawable/ic_lock_open_white_24dp.xml deleted file mode 100644 index 6c09b2a90..000000000 --- a/magikeyboard/src/main/res/drawable/ic_lock_open_white_24dp.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/magikeyboard/src/main/res/drawable/ic_lock_white_24dp.xml b/magikeyboard/src/main/res/drawable/ic_lock_white_24dp.xml deleted file mode 100644 index 27a2aa1dc..000000000 --- a/magikeyboard/src/main/res/drawable/ic_lock_white_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/magikeyboard/src/main/res/layout/activity_toolbar.xml b/magikeyboard/src/main/res/layout/activity_toolbar.xml deleted file mode 100644 index 382cffe0b..000000000 --- a/magikeyboard/src/main/res/layout/activity_toolbar.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/magikeyboard/src/main/res/layout/list_fields.xml b/magikeyboard/src/main/res/layout/list_fields.xml deleted file mode 100644 index 87e80311c..000000000 --- a/magikeyboard/src/main/res/layout/list_fields.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/magikeyboard/src/main/res/layout/toolbar_default.xml b/magikeyboard/src/main/res/layout/toolbar_default.xml deleted file mode 100644 index 56fba7001..000000000 --- a/magikeyboard/src/main/res/layout/toolbar_default.xml +++ /dev/null @@ -1,9 +0,0 @@ - - \ No newline at end of file diff --git a/magikeyboard/src/main/res/values/colors.xml b/magikeyboard/src/main/res/values/colors.xml deleted file mode 100644 index b33fb36a5..000000000 --- a/magikeyboard/src/main/res/values/colors.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - #3c474c - #263238 - #3c464c - #263238 - diff --git a/magikeyboard/src/main/res/values/strings.xml b/magikeyboard/src/main/res/values/strings.xml deleted file mode 100644 index 6619f8735..000000000 --- a/magikeyboard/src/main/res/values/strings.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - Magikeyboard - Magikeyboard (KeePass DX) - Magikeyboard settings - - Entry - - erase_entry_timeout_key - Timeout - Timeout to clear the keyboard entry - - notification_entry_key - Notification information - Show a notification when an entry is available - true - - Entry - %1$s available on Magikeyboard - %1$s - - notification_entry_slide_close_key - Clear at closing - Clear the keyboard entry when closing the notification - true - - Appearance - - theme_key - Theme - - Keys - key_vibrate_key - Vibrate on keypress - true - - key_vibrate_duration_key - Keypress vibration duration - - key_sound_key - Sound on keypress - false - - key_long_press_delay_key - Key long press delay - - diff --git a/settings.gradle b/settings.gradle index a214e0b2d..48a1ac76b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':icon-pack-classic', ':icon-pack-material', ':magikeyboard', ':keepass-model' +include ':app', ':icon-pack-classic', ':icon-pack-material' From 3c0835f725a517af272b80cf0937323bbbd1fde2 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 18 Sep 2018 15:52:38 +0200 Subject: [PATCH 2/8] Fix keyboard settings --- app/src/main/AndroidManifest.xml | 6 +- .../magikeyboard/EntryRetrieverActivity.java | 4 +- .../KeyboardEntryNotificationService.java | 6 +- .../keepass/magikeyboard/MagikIME.java | 4 +- .../NotificationDeleteBroadcastReceiver.java | 4 +- .../settings/MagikIMESettings.java | 31 +--------- .../settings/MagikIMESettingsFragment.java | 2 +- .../settings/NestedSettingsFragment.java | 5 +- app/src/main/res/values/strings.xml | 58 +++++++++---------- .../xml/{method.xml => keyboard_method.xml} | 2 +- .../main/res/xml/keyboard_password_entry.xml | 9 +-- app/src/main/res/xml/keyboard_preferences.xml | 54 ++++++++--------- 12 files changed, 76 insertions(+), 109 deletions(-) rename app/src/main/java/com/kunzisoft/keepass/{magikeyboard => }/settings/MagikIMESettings.java (59%) rename app/src/main/java/com/kunzisoft/keepass/{magikeyboard => }/settings/MagikIMESettingsFragment.java (88%) rename app/src/main/res/xml/{method.xml => keyboard_method.xml} (92%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 158909098..9d2d4dafe 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -132,10 +132,10 @@ - - @@ -169,7 +169,7 @@ android:label="@string/keyboard_label" android:permission="android.permission.BIND_INPUT_METHOD" > + android:resource="@xml/keyboard_method"/> diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/EntryRetrieverActivity.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/EntryRetrieverActivity.java index 607316b5c..0b4c9fa1b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/EntryRetrieverActivity.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/EntryRetrieverActivity.java @@ -44,8 +44,8 @@ public class EntryRetrieverActivity extends AppCompatActivity { // Show the notification if allowed in Preferences SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - if (sharedPreferences.getBoolean(getString(R.string.notification_entry_key), - getResources().getBoolean(R.bool.notification_entry_default))) { + if (sharedPreferences.getBoolean(getString(R.string.keyboard_notification_entry_key), + getResources().getBoolean(R.bool.keyboard_notification_entry_default))) { Intent notificationIntent = new Intent(this, KeyboardEntryNotificationService.class); startService(notificationIntent); } diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java index f31823c26..6a540197a 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java @@ -81,7 +81,7 @@ public class KeyboardEntryNotificationService extends Service { PendingIntent.getBroadcast(getApplicationContext(), 0, deleteIntent, 0); if (MagikIME.getEntryKey() != null) { - String entryTitle = getString(R.string.notification_entry_content_title_text); + String entryTitle = getString(R.string.keyboard_notification_entry_content_title_text); String entryUsername = ""; if (!MagikIME.getEntryKey().getTitle().isEmpty()) entryTitle = MagikIME.getEntryKey().getTitle(); @@ -90,10 +90,10 @@ public class KeyboardEntryNotificationService extends Service { NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID_KEYBOARD) .setSmallIcon(R.drawable.ic_vpn_key_white_24dp) - .setContentTitle(getString(R.string.notification_entry_content_title, entryTitle)) + .setContentTitle(getString(R.string.keyboard_notification_entry_content_title, entryTitle)) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setVisibility(NotificationCompat.VISIBILITY_SECRET) - .setContentText(getString(R.string.notification_entry_content_text, entryUsername)) + .setContentText(getString(R.string.keyboard_notification_entry_content_text, entryUsername)) .setAutoCancel(false) .setContentIntent(null) .setDeleteIntent(pendingDeleteIntent); diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java index eaba92a89..8a60597f6 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java @@ -190,10 +190,10 @@ public class MagikIME extends InputMethodService SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - if (sharedPreferences.getBoolean(getString(R.string.key_vibrate_key), getResources().getBoolean(R.bool.key_vibrate_default))) + if (sharedPreferences.getBoolean(getString(R.string.keyboard_key_vibrate_key), getResources().getBoolean(R.bool.keyboard_key_vibrate_default))) vibrate(); - if (sharedPreferences.getBoolean(getString(R.string.key_sound_key), getResources().getBoolean(R.bool.key_sound_default))) + if (sharedPreferences.getBoolean(getString(R.string.keyboard_key_sound_key), getResources().getBoolean(R.bool.keyboard_key_sound_default))) playClick(primaryCode); } diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java index 80c71db13..f56352adf 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/receiver/NotificationDeleteBroadcastReceiver.java @@ -15,8 +15,8 @@ public class NotificationDeleteBroadcastReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { // Clear the entry if define in preferences SharedPreferences sharedPreferences = android.preference.PreferenceManager.getDefaultSharedPreferences(context); - if (sharedPreferences.getBoolean(context.getString(R.string.notification_entry_clear_close_key), - context.getResources().getBoolean(R.bool.notification_entry_clear_close_default))) { + if (sharedPreferences.getBoolean(context.getString(R.string.keyboard_notification_entry_clear_close_key), + context.getResources().getBoolean(R.bool.keyboard_notification_entry_clear_close_default))) { MagikIME.deleteEntryKey(context); } diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettings.java b/app/src/main/java/com/kunzisoft/keepass/settings/MagikIMESettings.java similarity index 59% rename from app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettings.java rename to app/src/main/java/com/kunzisoft/keepass/settings/MagikIMESettings.java index 493971306..db84fd41c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettings.java +++ b/app/src/main/java/com/kunzisoft/keepass/settings/MagikIMESettings.java @@ -17,21 +17,16 @@ * along with KeePass DX. If not, see . * */ -package com.kunzisoft.keepass.magikeyboard.settings; +package com.kunzisoft.keepass.settings; import android.os.Bundle; -import android.support.v4.app.FragmentManager; -import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.MenuItem; import com.kunzisoft.keepass.R; +import com.kunzisoft.keepass.lock.LockingActivity; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -public class MagikIMESettings extends AppCompatActivity { +public class MagikIMESettings extends LockingActivity { @Override protected void onCreate(Bundle savedInstanceState) { @@ -49,26 +44,6 @@ public class MagikIMESettings extends AppCompatActivity { .replace(R.id.fragment_container, new MagikIMESettingsFragment()) .commit(); } - - // TODO Remove after all dev - try { - Class underDevClass = Class.forName("com.kunzisoft.keepass.dialogs.UnderDevelopmentFeatureDialogFragment"); - Constructor constructor = underDevClass.getConstructor(); - Object object = constructor.newInstance(); - Method showMethod = underDevClass.getMethod("show", FragmentManager.class, String.class); - showMethod.invoke(object, getSupportFragmentManager(), "magikeyboard_dev_dialog"); - - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } } @Override diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettingsFragment.java b/app/src/main/java/com/kunzisoft/keepass/settings/MagikIMESettingsFragment.java similarity index 88% rename from app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettingsFragment.java rename to app/src/main/java/com/kunzisoft/keepass/settings/MagikIMESettingsFragment.java index 7144cee68..e99e6dd0c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/settings/MagikIMESettingsFragment.java +++ b/app/src/main/java/com/kunzisoft/keepass/settings/MagikIMESettingsFragment.java @@ -1,4 +1,4 @@ -package com.kunzisoft.keepass.magikeyboard.settings; +package com.kunzisoft.keepass.settings; import android.os.Bundle; import android.support.v7.preference.PreferenceFragmentCompat; diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java index 6ccda6254..dfdbd3a5b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java @@ -60,7 +60,6 @@ import com.kunzisoft.keepass.settings.preferenceDialogFragment.MemoryUsagePrefer import com.kunzisoft.keepass.settings.preferenceDialogFragment.ParallelismPreferenceDialogFragmentCompat; import com.kunzisoft.keepass.settings.preferenceDialogFragment.RoundsPreferenceDialogFragmentCompat; import com.kunzisoft.keepass.stylish.Stylish; -import com.kunzisoft.keepass.magikeyboard.settings.MagikIMESettings; public class NestedSettingsFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceClickListener { @@ -303,8 +302,8 @@ public class NestedSettingsFragment extends PreferenceFragmentCompat Preference keyboardPreference = findPreference(getString(R.string.magic_keyboard_key)); keyboardPreference.setOnPreferenceClickListener(preference -> { if (getFragmentManager() != null) { - KeyboardExplanationDialog fingerPrintDialog = new KeyboardExplanationDialog(); - fingerPrintDialog.show(getFragmentManager(), "keyboardExplanationDialog"); + KeyboardExplanationDialog keyboardDialog = new KeyboardExplanationDialog(); + keyboardDialog.show(getFragmentManager(), "keyboardExplanationDialog"); } return false; }); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fc7af7090..ccc25d843 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -292,45 +292,45 @@ Magikeyboard (KeePass DX) Magikeyboard settings - Entry + Entry - erase_entry_timeout_key - Timeout - Timeout to clear the keyboard entry + erase_entry_timeout_key + Timeout + Timeout to clear the keyboard entry - notification_entry_key - Notification information - Show a notification when an entry is available - true + notification_entry_key + Notification information + Show a notification when an entry is available + true - Entry - %1$s available on Magikeyboard - %1$s + Entry + %1$s available on Magikeyboard + %1$s - notification_entry_slide_close_key - Clear at closing - Clear the keyboard entry when closing the notification - true + notification_entry_slide_close_key + Clear at closing + Clear the keyboard entry when closing the notification + true - Appearance + Appearance - theme_key - Theme + keyboard_theme_key + Keyboard theme - Keys - key_vibrate_key - Vibrate on keypress - true + Keys + keyboard_key_vibrate_key + Vibrate on keypress + true - key_vibrate_duration_key - Keypress vibration duration + keyboard_key_vibrate_duration_key + Keypress vibration duration - key_sound_key - Sound on keypress - false + key_sound_key + Sound on keypress + false - key_long_press_delay_key - Key long press delay + key_long_press_delay_key + Key long press delay Allow no password Enable the open button if no password identification is selected diff --git a/app/src/main/res/xml/method.xml b/app/src/main/res/xml/keyboard_method.xml similarity index 92% rename from app/src/main/res/xml/method.xml rename to app/src/main/res/xml/keyboard_method.xml index d2396e4ff..18c026733 100644 --- a/app/src/main/res/xml/method.xml +++ b/app/src/main/res/xml/keyboard_method.xml @@ -20,7 +20,7 @@ - + android:title="@string/keyboard_entry_category"> + android:key="@string/keyboard_notification_entry_key" + android:title="@string/keyboard_notification_entry_title" + android:summary="@string/keyboard_notification_entry_summary" + android:defaultValue="@bool/keyboard_notification_entry_default"/> + android:key="@string/keyboard_notification_entry_clear_close_key" + android:title="@string/keyboard_notification_entry_clear_close_title" + android:summary="@string/keyboard_notification_entry_clear_close_summary" + android:dependency="@string/keyboard_notification_entry_key" + android:defaultValue="@bool/keyboard_notification_entry_clear_close_default"/> + android:title="@string/keyboard_appearance_category"> + android:title="@string/keyboard_keys_category"> + android:key="@string/keyboard_key_sound_key" + android:defaultValue="@bool/keyboard_key_sound_default" + android:title="@string/keyboard_key_sound_title" /> \ No newline at end of file From c1e84b3bf1918b39243707da4223a3f8541f3f61 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 18 Sep 2018 21:27:36 +0200 Subject: [PATCH 3/8] Add popup view for custom fields --- .../keepass/magikeyboard/MagikIME.java | 42 +++++++-- .../magikeyboard/view/MagikeyboardView.java | 39 +++++++++ app/src/main/res/layout/key_preview.xml | 31 ------- .../main/res/layout/keyboard_popup_fields.xml | 86 +++++++++++++++++++ .../{keyboard.xml => keyboard_view.xml} | 4 +- app/src/main/res/values/colors.xml | 2 +- app/src/main/res/xml/keyboard_fields_list.xml | 24 ------ .../main/res/xml/keyboard_password_entry.xml | 3 +- 8 files changed, 165 insertions(+), 66 deletions(-) create mode 100644 app/src/main/java/com/kunzisoft/keepass/magikeyboard/view/MagikeyboardView.java delete mode 100644 app/src/main/res/layout/key_preview.xml create mode 100644 app/src/main/res/layout/keyboard_popup_fields.xml rename app/src/main/res/layout/{keyboard.xml => keyboard_view.xml} (91%) delete mode 100644 app/src/main/res/xml/keyboard_fields_list.xml diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java index 8a60597f6..5faf4d400 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java @@ -29,15 +29,21 @@ import android.inputmethodservice.KeyboardView; import android.media.AudioManager; import android.support.v7.preference.PreferenceManager; import android.util.Log; +import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; +import android.view.LayoutInflater; import android.view.View; +import android.view.WindowManager; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; +import android.widget.FrameLayout; +import android.widget.PopupWindow; import com.kunzisoft.keepass.R; import com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver; +import com.kunzisoft.keepass.magikeyboard.view.MagikeyboardView; import com.kunzisoft.keepass.model.Entry; import static com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver.LOCK_ACTION; @@ -46,7 +52,8 @@ public class MagikIME extends InputMethodService implements KeyboardView.OnKeyboardActionListener { private static final String TAG = MagikIME.class.getName(); - private static final int KEY_CHANGE_KEYBOARD = 600; + public static final int KEY_BACK_KEYBOARD = 600; + public static final int KEY_CHANGE_KEYBOARD = 601; private static final int KEY_UNLOCK = 610; private static final int KEY_LOCK = 611; private static final int KEY_ENTRY = 620; @@ -60,6 +67,7 @@ public class MagikIME extends InputMethodService private KeyboardView keyboardView; private Keyboard keyboard; private Keyboard keyboard_entry; + private PopupWindow popupCustomKeys; private LockBroadcastReceiver lockBroadcastReceiver; @@ -81,19 +89,29 @@ public class MagikIME extends InputMethodService @Override public void onDestroy() { unregisterReceiver(lockBroadcastReceiver); + popupCustomKeys.dismiss(); super.onDestroy(); } @Override public View onCreateInputView() { - keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.keyboard, null); + keyboardView = (MagikeyboardView) getLayoutInflater().inflate(R.layout.keyboard_view, null); keyboard = new Keyboard(this, R.xml.keyboard_password); keyboard_entry = new Keyboard(this, R.xml.keyboard_password_entry); assignKeyboardView(); keyboardView.setOnKeyboardActionListener(this); keyboardView.setPreviewEnabled(false); - keyboardView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + + Context context = getBaseContext(); + View custom = LayoutInflater.from(context) + .inflate(R.layout.keyboard_popup_fields, new FrameLayout(context)); + popupCustomKeys = new PopupWindow(context); + popupCustomKeys.setWidth(WindowManager.LayoutParams.WRAP_CONTENT); + popupCustomKeys.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); + popupCustomKeys.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + popupCustomKeys.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); + popupCustomKeys.setContentView(custom); return keyboardView; } @@ -110,6 +128,10 @@ public class MagikIME extends InputMethodService } } + private void assignKeyboardPopupView() { + + } + @Override public void onStartInputView(EditorInfo info, boolean restarting) { super.onStartInputView(info, restarting); @@ -133,8 +155,9 @@ public class MagikIME extends InputMethodService @Override public void onKey(int primaryCode, int[] keyCodes) { InputConnection ic = getCurrentInputConnection(); + keyboardView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); switch(primaryCode){ - case KEY_CHANGE_KEYBOARD: + case KEY_BACK_KEYBOARD: try { InputMethodManager imeManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); assert imeManager != null; @@ -148,6 +171,11 @@ public class MagikIME extends InputMethodService } // TODO Add a long press to choose the keyboard break; + case KEY_CHANGE_KEYBOARD: + InputMethodManager imeManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); + if (imeManager != null) + imeManager.showInputMethodPicker(); + break; case KEY_UNLOCK: // TODO Unlock key break; @@ -178,7 +206,9 @@ public class MagikIME extends InputMethodService } break; case KEY_FIELDS: - // TODO Fields key + // TODO listen the close an open only one time + popupCustomKeys.showAtLocation(keyboardView, Gravity.END | Gravity.TOP, 0, 0); + break; case Keyboard.KEYCODE_DELETE : ic.deleteSurroundingText(1, 0); break; @@ -202,7 +232,7 @@ public class MagikIME extends InputMethodService public void onPress(int primaryCode) { } - @Override + @Override public void onRelease(int primaryCode) { } diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/view/MagikeyboardView.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/view/MagikeyboardView.java new file mode 100644 index 000000000..b962f4b62 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/view/MagikeyboardView.java @@ -0,0 +1,39 @@ +package com.kunzisoft.keepass.magikeyboard.view; + +import android.content.Context; +import android.inputmethodservice.Keyboard; +import android.inputmethodservice.KeyboardView; +import android.os.Build; +import android.support.annotation.RequiresApi; +import android.util.AttributeSet; + +import static com.kunzisoft.keepass.magikeyboard.MagikIME.KEY_BACK_KEYBOARD; +import static com.kunzisoft.keepass.magikeyboard.MagikIME.KEY_CHANGE_KEYBOARD; + +public class MagikeyboardView extends KeyboardView { + + public MagikeyboardView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public MagikeyboardView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public MagikeyboardView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected boolean onLongPress(Keyboard.Key key) { + // TODO Action on long press + if (key.codes[0] == KEY_BACK_KEYBOARD) { + getOnKeyboardActionListener().onKey(KEY_CHANGE_KEYBOARD, null); + return true; + } else { + //Log.d("LatinKeyboardView", "KEY: " + key.codes[0]); + return super.onLongPress(key); + } + } +} diff --git a/app/src/main/res/layout/key_preview.xml b/app/src/main/res/layout/key_preview.xml deleted file mode 100644 index 465238093..000000000 --- a/app/src/main/res/layout/key_preview.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/keyboard_popup_fields.xml b/app/src/main/res/layout/keyboard_popup_fields.xml new file mode 100644 index 000000000..b4433b792 --- /dev/null +++ b/app/src/main/res/layout/keyboard_popup_fields.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/keyboard.xml b/app/src/main/res/layout/keyboard_view.xml similarity index 91% rename from app/src/main/res/layout/keyboard.xml rename to app/src/main/res/layout/keyboard_view.xml index 7d95cbd5c..68b846ea4 100644 --- a/app/src/main/res/layout/keyboard.xml +++ b/app/src/main/res/layout/keyboard_view.xml @@ -17,16 +17,16 @@ You should have received a copy of the GNU General Public License along with KeePass DX. If not, see . --> - \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 2a25749df..f881ef58b 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -73,4 +73,4 @@ #263238 #3c464c #263238 - + diff --git a/app/src/main/res/xml/keyboard_fields_list.xml b/app/src/main/res/xml/keyboard_fields_list.xml deleted file mode 100644 index 7871db5bd..000000000 --- a/app/src/main/res/xml/keyboard_fields_list.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - \ No newline at end of file diff --git a/app/src/main/res/xml/keyboard_password_entry.xml b/app/src/main/res/xml/keyboard_password_entry.xml index 9a5939501..44fdc6fa8 100644 --- a/app/src/main/res/xml/keyboard_password_entry.xml +++ b/app/src/main/res/xml/keyboard_password_entry.xml @@ -32,10 +32,9 @@ - From a9c87ea2b82f92e22fea390127d65be24ff8b1c9 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Sat, 13 Oct 2018 16:10:45 +0200 Subject: [PATCH 4/8] Add custom fields selection in keyboard --- .../KeyboardExplanationDialogFragment.java} | 6 +- .../keepass/magikeyboard/MagikIME.java | 121 +++++++++--------- .../keepass/magikeyboard/Utility.java | 6 - .../magikeyboard/adapter/FieldsAdapter.java | 76 +++++++++++ .../com/kunzisoft/keepass/model/Entry.java | 25 ++-- .../com/kunzisoft/keepass/model/Field.java | 59 +++++++++ .../selection/EntrySelectionHelper.java | 7 +- .../settings/NestedSettingsFragment.java | 4 +- .../main/res/layout/keyboard_popup_fields.xml | 68 +--------- .../res/layout/keyboard_popup_fields_item.xml | 15 +++ app/src/main/res/xml/keyboard_preferences.xml | 3 +- 11 files changed, 237 insertions(+), 153 deletions(-) rename app/src/main/java/com/kunzisoft/keepass/{keyboard/KeyboardExplanationDialog.java => dialogs/KeyboardExplanationDialogFragment.java} (93%) delete mode 100644 app/src/main/java/com/kunzisoft/keepass/magikeyboard/Utility.java create mode 100644 app/src/main/java/com/kunzisoft/keepass/magikeyboard/adapter/FieldsAdapter.java create mode 100644 app/src/main/java/com/kunzisoft/keepass/model/Field.java create mode 100644 app/src/main/res/layout/keyboard_popup_fields_item.xml diff --git a/app/src/main/java/com/kunzisoft/keepass/keyboard/KeyboardExplanationDialog.java b/app/src/main/java/com/kunzisoft/keepass/dialogs/KeyboardExplanationDialogFragment.java similarity index 93% rename from app/src/main/java/com/kunzisoft/keepass/keyboard/KeyboardExplanationDialog.java rename to app/src/main/java/com/kunzisoft/keepass/dialogs/KeyboardExplanationDialogFragment.java index 2f2008be6..f6f992aaf 100644 --- a/app/src/main/java/com/kunzisoft/keepass/keyboard/KeyboardExplanationDialog.java +++ b/app/src/main/java/com/kunzisoft/keepass/dialogs/KeyboardExplanationDialogFragment.java @@ -17,7 +17,7 @@ * along with KeePass DX. If not, see . * */ -package com.kunzisoft.keepass.keyboard; +package com.kunzisoft.keepass.dialogs; import android.app.Dialog; import android.content.Intent; @@ -28,16 +28,14 @@ import android.support.v4.app.DialogFragment; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; -import android.view.inputmethod.InputMethodManager; import com.kunzisoft.keepass.BuildConfig; import com.kunzisoft.keepass.R; import com.kunzisoft.keepass.utils.Util; -import static android.content.Context.INPUT_METHOD_SERVICE; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; -public class KeyboardExplanationDialog extends DialogFragment { +public class KeyboardExplanationDialogFragment extends DialogFragment { @NonNull @Override diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java index 5faf4d400..a77aba062 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java @@ -28,6 +28,8 @@ import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; import android.media.AudioManager; import android.support.v7.preference.PreferenceManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; @@ -42,6 +44,7 @@ import android.widget.FrameLayout; import android.widget.PopupWindow; import com.kunzisoft.keepass.R; +import com.kunzisoft.keepass.magikeyboard.adapter.FieldsAdapter; import com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver; import com.kunzisoft.keepass.magikeyboard.view.MagikeyboardView; import com.kunzisoft.keepass.model.Entry; @@ -68,6 +71,8 @@ public class MagikIME extends InputMethodService private Keyboard keyboard; private Keyboard keyboard_entry; private PopupWindow popupCustomKeys; + private FieldsAdapter fieldsAdapter; + private boolean playSoundDuringCLick; private LockBroadcastReceiver lockBroadcastReceiver; @@ -86,13 +91,6 @@ public class MagikIME extends InputMethodService registerReceiver(lockBroadcastReceiver, new IntentFilter(LOCK_ACTION)); } - @Override - public void onDestroy() { - unregisterReceiver(lockBroadcastReceiver); - popupCustomKeys.dismiss(); - super.onDestroy(); - } - @Override public View onCreateInputView() { keyboardView = (MagikeyboardView) getLayoutInflater().inflate(R.layout.keyboard_view, null); @@ -104,14 +102,37 @@ public class MagikIME extends InputMethodService keyboardView.setPreviewEnabled(false); Context context = getBaseContext(); - View custom = LayoutInflater.from(context) + View popupFieldsView = LayoutInflater.from(context) .inflate(R.layout.keyboard_popup_fields, new FrameLayout(context)); + + if (popupCustomKeys != null) + popupCustomKeys.dismiss(); + popupCustomKeys = new PopupWindow(context); popupCustomKeys.setWidth(WindowManager.LayoutParams.WRAP_CONTENT); popupCustomKeys.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); popupCustomKeys.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); popupCustomKeys.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); - popupCustomKeys.setContentView(custom); + popupCustomKeys.setContentView(popupFieldsView); + + RecyclerView recyclerView = popupFieldsView.findViewById(R.id.keyboard_popup_fields_list); + fieldsAdapter = new FieldsAdapter(this); + fieldsAdapter.setOnItemClickListener(item -> getCurrentInputConnection().commitText(item.getValue(), 1)); + recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true)); + recyclerView.setAdapter(fieldsAdapter); + + View closeView = popupFieldsView.findViewById(R.id.keyboard_popup_close); + closeView.setOnClickListener(v -> popupCustomKeys.dismiss()); + + // Define preferences + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + keyboardView.setHapticFeedbackEnabled( + sharedPreferences.getBoolean( + getString(R.string.keyboard_key_vibrate_key), + getResources().getBoolean(R.bool.keyboard_key_vibrate_default))); + playSoundDuringCLick = sharedPreferences.getBoolean( + getString(R.string.keyboard_key_sound_key), + getResources().getBoolean(R.bool.keyboard_key_sound_default)); return keyboardView; } @@ -128,10 +149,6 @@ public class MagikIME extends InputMethodService } } - private void assignKeyboardPopupView() { - - } - @Override public void onStartInputView(EditorInfo info, boolean restarting) { super.onStartInputView(info, restarting); @@ -154,8 +171,14 @@ public class MagikIME extends InputMethodService @Override public void onKey(int primaryCode, int[] keyCodes) { - InputConnection ic = getCurrentInputConnection(); - keyboardView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + InputConnection inputConnection = getCurrentInputConnection(); + + // Vibrate + keyboardView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + // Play a sound + if (playSoundDuringCLick) + playClick(primaryCode); + switch(primaryCode){ case KEY_BACK_KEYBOARD: try { @@ -186,89 +209,57 @@ public class MagikIME extends InputMethodService break; case KEY_LOCK: deleteEntryKey(this); + dismissCustomKeys(); break; case KEY_USERNAME: if (entryKey != null) { - InputConnection inputConnection = getCurrentInputConnection(); inputConnection.commitText(entryKey.getUsername(), 1); } break; case KEY_PASSWORD: if (entryKey != null) { - InputConnection inputConnection = getCurrentInputConnection(); inputConnection.commitText(entryKey.getPassword(), 1); } break; case KEY_URL: if (entryKey != null) { - InputConnection inputConnection = getCurrentInputConnection(); inputConnection.commitText(entryKey.getUrl(), 1); } break; case KEY_FIELDS: - // TODO listen the close an open only one time + fieldsAdapter.setFields(entryKey.getCustomFields()); popupCustomKeys.showAtLocation(keyboardView, Gravity.END | Gravity.TOP, 0, 0); break; case Keyboard.KEYCODE_DELETE : - ic.deleteSurroundingText(1, 0); + inputConnection.deleteSurroundingText(1, 0); break; case Keyboard.KEYCODE_DONE: - ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)); + inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)); break; default: } - - SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - - if (sharedPreferences.getBoolean(getString(R.string.keyboard_key_vibrate_key), getResources().getBoolean(R.bool.keyboard_key_vibrate_default))) - vibrate(); - - if (sharedPreferences.getBoolean(getString(R.string.keyboard_key_sound_key), getResources().getBoolean(R.bool.keyboard_key_sound_default))) - playClick(primaryCode); - } @Override - public void onPress(int primaryCode) { - } + public void onPress(int primaryCode) {} @Override - public void onRelease(int primaryCode) { - } + public void onRelease(int primaryCode) {} @Override - public void onText(CharSequence text) { - } + public void onText(CharSequence text) {} @Override - public void swipeDown() { - } + public void swipeDown() {} @Override - public void swipeLeft() { - } + public void swipeLeft() {} @Override - public void swipeRight() { - } + public void swipeRight() {} @Override - public void swipeUp() { - } - - private void vibrate() { - // TODO better vibration - /* - Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); - if (vibrator != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - vibrator.vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE)); - } else { - vibrator.vibrate(50); - } - } - */ - } + public void swipeUp() {} private void playClick(int keyCode){ AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE); @@ -284,4 +275,18 @@ public class MagikIME extends InputMethodService default: am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD); } } + + private void dismissCustomKeys() { + if (popupCustomKeys != null) + popupCustomKeys.dismiss(); + if (fieldsAdapter != null) + fieldsAdapter.clear(); + } + + @Override + public void onDestroy() { + unregisterReceiver(lockBroadcastReceiver); + dismissCustomKeys(); + super.onDestroy(); + } } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/Utility.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/Utility.java deleted file mode 100644 index 5eecdae92..000000000 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/Utility.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.kunzisoft.keepass.magikeyboard; - -public class Utility { - - -} diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/adapter/FieldsAdapter.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/adapter/FieldsAdapter.java new file mode 100644 index 000000000..e1d3cb1c2 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/adapter/FieldsAdapter.java @@ -0,0 +1,76 @@ +package com.kunzisoft.keepass.magikeyboard.adapter; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.kunzisoft.keepass.R; +import com.kunzisoft.keepass.model.Field; + +import java.util.ArrayList; +import java.util.List; + +public class FieldsAdapter extends RecyclerView.Adapter { + + private LayoutInflater inflater; + private List fields; + private OnItemClickListener listener; + + public FieldsAdapter(Context context) { + this.inflater = LayoutInflater.from(context); + this.fields = new ArrayList<>(); + } + + public void setFields(List fields) { + this.fields = fields; + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.listener = listener; + } + + @NonNull + @Override + public FieldViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = inflater.inflate(R.layout.keyboard_popup_fields_item, parent, false); + return new FieldViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull FieldViewHolder holder, int position) { + Field field = fields.get(position); + holder.name.setText(field.getName()); + holder.bind(field, listener); + } + + @Override + public int getItemCount() { + return fields.size(); + } + + public void clear() { + fields.clear(); + } + + public interface OnItemClickListener { + void onItemClick(Field item); + } + + class FieldViewHolder extends RecyclerView.ViewHolder { + + TextView name; + + FieldViewHolder(View itemView) { + super(itemView); + name = itemView.findViewById(R.id.keyboard_popup_field_item_name); + } + + void bind(final Field item, final OnItemClickListener listener) { + itemView.setOnClickListener(v -> listener.onItemClick(item)); + } + } +} diff --git a/app/src/main/java/com/kunzisoft/keepass/model/Entry.java b/app/src/main/java/com/kunzisoft/keepass/model/Entry.java index db722499a..9cb01e9e3 100644 --- a/app/src/main/java/com/kunzisoft/keepass/model/Entry.java +++ b/app/src/main/java/com/kunzisoft/keepass/model/Entry.java @@ -3,9 +3,8 @@ package com.kunzisoft.keepass.model; import android.os.Parcel; import android.os.Parcelable; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; public class Entry implements Parcelable { @@ -13,14 +12,14 @@ public class Entry implements Parcelable { private String username; private String password; private String url; - private Map customFields; + private List customFields; public Entry() { this.title = ""; this.username = ""; this.password = ""; this.url = ""; - this.customFields = new HashMap<>(); + this.customFields = new ArrayList<>(); } protected Entry(Parcel in) { @@ -29,7 +28,7 @@ public class Entry implements Parcelable { password = in.readString(); url = in.readString(); //noinspection unchecked - customFields = in.readHashMap(String.class.getClassLoader()); + customFields = in.readArrayList(Field.class.getClassLoader()); } public static final Creator CREATOR = new Creator() { @@ -76,16 +75,12 @@ public class Entry implements Parcelable { this.url = url; } - public Set getCustomFieldsKeys() { - return customFields.keySet(); + public List getCustomFields() { + return customFields; } - public String getCustomField(String key) { - return customFields.get(key); - } - - public void setCustomField(String key, String value) { - this.customFields.put(key, value); + public void addCustomField(Field field) { + this.customFields.add(field); } @Override @@ -99,6 +94,6 @@ public class Entry implements Parcelable { parcel.writeString(username); parcel.writeString(password); parcel.writeString(url); - parcel.writeMap(customFields); + parcel.writeArray(customFields.toArray()); } } diff --git a/app/src/main/java/com/kunzisoft/keepass/model/Field.java b/app/src/main/java/com/kunzisoft/keepass/model/Field.java new file mode 100644 index 000000000..69b5e0996 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/model/Field.java @@ -0,0 +1,59 @@ +package com.kunzisoft.keepass.model; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Field implements Parcelable { + + private String name; + private String value; + + public Field(String name, String value) { + this.name = name; + this.value = value; + } + + public Field(Parcel in) { + this.name = in.readString(); + this.value = in.readString(); + } + + public static final Creator CREATOR = new Creator() { + @Override + public Field createFromParcel(Parcel in) { + return new Field(in); + } + + @Override + public Field[] newArray(int size) { + return new Field[size]; + } + }; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(name); + dest.writeString(value); + } +} diff --git a/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java b/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java index a70873b67..ee365981c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java +++ b/app/src/main/java/com/kunzisoft/keepass/selection/EntrySelectionHelper.java @@ -6,6 +6,7 @@ import android.util.Log; import com.kunzisoft.keepass.database.PwEntry; import com.kunzisoft.keepass.model.Entry; +import com.kunzisoft.keepass.model.Field; public class EntrySelectionHelper { @@ -37,9 +38,11 @@ public class EntrySelectionHelper { entryModel.setUsername(entry.getUsername()); entryModel.setPassword(entry.getPassword()); entryModel.setUrl(entry.getUrl()); - // TODO Fields if (entry.containsCustomFields()) { - //entryModel.setCustomField(entry.getFields()); + entry.getFields() + .doActionToAllCustomProtectedField( + (key, value) -> entryModel.addCustomField( + new Field(key, value.toString()))); } mReplyIntent.putExtra( diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java index dfdbd3a5b..8c1f6f0c7 100644 --- a/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java +++ b/app/src/main/java/com/kunzisoft/keepass/settings/NestedSettingsFragment.java @@ -51,7 +51,7 @@ import com.kunzisoft.keepass.dialogs.UnavailableFeatureDialogFragment; import com.kunzisoft.keepass.dialogs.UnderDevelopmentFeatureDialogFragment; import com.kunzisoft.keepass.fingerprint.FingerPrintHelper; import com.kunzisoft.keepass.icons.IconPackChooser; -import com.kunzisoft.keepass.keyboard.KeyboardExplanationDialog; +import com.kunzisoft.keepass.dialogs.KeyboardExplanationDialogFragment; import com.kunzisoft.keepass.settings.preferenceDialogFragment.DatabaseDescriptionPreferenceDialogFragmentCompat; import com.kunzisoft.keepass.settings.preferenceDialogFragment.DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat; import com.kunzisoft.keepass.settings.preferenceDialogFragment.DatabaseKeyDerivationPreferenceDialogFragmentCompat; @@ -302,7 +302,7 @@ public class NestedSettingsFragment extends PreferenceFragmentCompat Preference keyboardPreference = findPreference(getString(R.string.magic_keyboard_key)); keyboardPreference.setOnPreferenceClickListener(preference -> { if (getFragmentManager() != null) { - KeyboardExplanationDialog keyboardDialog = new KeyboardExplanationDialog(); + KeyboardExplanationDialogFragment keyboardDialog = new KeyboardExplanationDialogFragment(); keyboardDialog.show(getFragmentManager(), "keyboardExplanationDialog"); } return false; diff --git a/app/src/main/res/layout/keyboard_popup_fields.xml b/app/src/main/res/layout/keyboard_popup_fields.xml index b4433b792..a681b9c60 100644 --- a/app/src/main/res/layout/keyboard_popup_fields.xml +++ b/app/src/main/res/layout/keyboard_popup_fields.xml @@ -1,76 +1,16 @@ - - - - - - - - - - - + android:layout_toLeftOf="@+id/keyboard_popup_close" /> + + + \ No newline at end of file diff --git a/app/src/main/res/xml/keyboard_preferences.xml b/app/src/main/res/xml/keyboard_preferences.xml index 342044d74..07c4bd17c 100644 --- a/app/src/main/res/xml/keyboard_preferences.xml +++ b/app/src/main/res/xml/keyboard_preferences.xml @@ -50,8 +50,7 @@ + android:defaultValue="@bool/keyboard_key_vibrate_default"/> Date: Sat, 20 Oct 2018 12:48:44 +0200 Subject: [PATCH 5/8] Add alpha channel to capture_keyboard images --- .../drawable/capture_keyboard_entry_key.png | Bin 1001 -> 1314 bytes .../drawable/capture_keyboard_fields_keys.png | Bin 2447 -> 3829 bytes .../drawable/capture_keyboard_lock_key.png | Bin 1029 -> 1549 bytes .../drawable/capture_keyboard_switch_key.png | Bin 801 -> 1100 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/app/src/main/res/drawable/capture_keyboard_entry_key.png b/app/src/main/res/drawable/capture_keyboard_entry_key.png index 95f020e8436be4887b5f9c56dc20d6cb4323546d..0f934700eb08c6ca56320d4e43e0f72ae90b1132 100644 GIT binary patch delta 1278 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 literal 2447 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 delta 1018 zcmeC>Y2}z8SQzCOZ^BFFFNL`Rh^Q>!`Bc7(gN>e8n|!4BV^4nh87-R#2p zQXDRn>j}NXMVp|e=p_4#cO5`%mM<8O%4JaOpXd1EE|K3pOpzZtf`XaM4GIGFsk2_{w3PHGOkreT_hVUP&&A-t;>2>Ok(pt!PHkVkLqMPi%OT6_ zs!eMYPFRYwIJp|~a}>L>GBli1Oqp>q;}o;gNx@zB`BwEaG@MLvk!@_^0=w|^=C-tB z8o6b1#W&tEY>?up`B>ZQ5mec@A*gEe`saUc8b|(pH`8C(zkdE(Za!zg8rBU+s*V;wzx%n6b?%lXCU)Ip1V)4;R8HPWN3HRSBZa=l{aZ9X}$bg^B2btOe zB9%CFwMC>}bR7J5Z}MC9khdF@qq$q}7~d1mzc+PHpTwK@drLkxP2I?J)FN5exBfWi z1lIdWnXfrQE#4eES2|bkr^LZ;PU51^!X$JAS(-Gi9`gC+=#lTH{j0h^#5gBd&F&SQB75EW;mZEYlh=1I-S_>i&<}>l zw2xxVs%g9|jS2!RO&TmNT2q_WE|>k~Ki7!8!Nq7MyNiyTzOt+%1A|bfi=04^iPmW& z#!0_F6nobPbumm#jhs4FQo-W+DaOpntk>0aX8Nct4onvjI+>z0@yGh|`7iC7te99un;e|M8KvXx8}si> X?sZdyk9jjNFfe$!`njxgN@xNATXebz diff --git a/app/src/main/res/drawable/capture_keyboard_switch_key.png b/app/src/main/res/drawable/capture_keyboard_switch_key.png index 5862f3e997977535f098358dc8b296182e98587d..a19f4049d3ee1d8a892b40fbc702adba64b36144 100644 GIT binary patch delta 1086 zcmZ3;c80^aGr-TCmrII^fq{Y7)59f*fq@~Bfq}t`gN=cKVRf!m7y|&_I@(I;h;-z z!9o*m@vdDnDmEUwvUu528LslY2?Y%;!kiD8*qt~;dRpadsxBPSXqP%QUt>wZmMVjb z3wZ0_oVjuL=FH=X+n3&cqqAlA@3fZp>X~Kg)+bf&pWkjRH(%dfP9aO6yNEnpx-e)oBL9E=C)s4*~~DB--q!oqD?7 z_Wu8H&8rr#-DHcWrykrm*MF%`g@U%TD;L8x4^6#wr|O^IXDY~9$+2?_i{-Y>ya!TQQ#mv>7Pz*E2n0DeG9Cy# zUS=0PD|0T3_4MW`k9vYu&3?E&vP~es%h9Xw)VZfAYgn{r-(`KEZ1CT2(@~Q%{K={* zMlVq~+h-YxR{j zEBRtoZ(GqYUoHR8R~xU0GrQmK=`~jOS9pITYMuG(DvOFA9Cd%+mQPz;`R%>*B{c?y zPkp_Af45b1@0#)G-M;Wgv-Fi30}dJM_15<;zG2^x^q)bmw>NzM&aID={yTU-4`5o@ zvL)#IhwHCjUkjBNyu9a#&BwduC+`ScIW;XTi~r$YTVrLZube9%zPnO;XXY+;h8q`m z%eLN|w`-Q2kKBq$baxU|8S1OKYQhc7j8FC z+}q6kp0Qp>W_uN%dYa!EUiGwT%F`AWZU3%WQk*Ma2sgZPs{gpxPM7Fdh=h)t4LR^{KmXG{zXOb0w&978H@y}i9Z|FVM!`-k_|w+mktM`*hV zByj~ME_6NHWi-Kl!9v+t_6>ra`x!cU)s9@?3wbMlfI%pUYf);})G`-?MT_!&=m@FX zu?4Fy)!d?_SNMMK%O#urKDmFt_jf|yy8E+OkFOB$Ibh;*7>dMI-fVGox%Byt)4@$T z#sBu-e_y^URtC1Zv&=Lz)j9oX*|M%Y!+?YRe$UHiEqWcNHI*S_t)qew zhsSZL27xIYJg+&FJ}u>UaGtENIEG<@g3ywMj6W{P|EpEB_2;-0HM^~drNbjzm&NnE z^o1R*Objzl7pchHmb{?ydg94owX-@5eaWBqwQa9~JIm*=iHuKi(T$mX@4PMT%YT3R z@+HFU_pbf_>pmwh2zi&eE_UyyHzyxY(m!tT?7M?)#g7-4pX>khTk$L?d5<20*S;J* z)1vt7RmGbvrKX+!@Z{o}b-5wgU$fTk+qI2RAu~Mtt8wYaM`wS}>g1obzncHVlUsYf zJ_`+F-4}K~C5D&bJ|Ew?ub<5L@9i$#KIvSi z!^($06CZ!jU8cWOKwJdH jw89Vj;I^wx|0wL2C3|J!Pv^r73=9mOu6{1-oD!M Date: Sat, 20 Oct 2018 12:57:26 +0200 Subject: [PATCH 6/8] Remove keyboard sound and vibration duration settings --- app/src/main/res/values/strings.xml | 6 ------ app/src/main/res/xml/keyboard_preferences.xml | 8 -------- 2 files changed, 14 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ccc25d843..af75610c9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -322,16 +322,10 @@ Vibrate on keypress true - keyboard_key_vibrate_duration_key - Keypress vibration duration - key_sound_key Sound on keypress false - key_long_press_delay_key - Key long press delay - Allow no password Enable the open button if no password identification is selected Read only diff --git a/app/src/main/res/xml/keyboard_preferences.xml b/app/src/main/res/xml/keyboard_preferences.xml index 07c4bd17c..817da1d1a 100644 --- a/app/src/main/res/xml/keyboard_preferences.xml +++ b/app/src/main/res/xml/keyboard_preferences.xml @@ -51,17 +51,9 @@ android:key="@string/keyboard_key_vibrate_key" android:title="@string/keyboard_key_vibrate_title" android:defaultValue="@bool/keyboard_key_vibrate_default"/> - - \ No newline at end of file From e8d0d03ad9f360a1bcb039bc56dbf2a88e44b5e9 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Sat, 27 Oct 2018 13:56:08 +0200 Subject: [PATCH 7/8] Add keyboard Timeout --- .../KeyboardEntryNotificationService.java | 71 ++++++++++++------- .../keepass/magikeyboard/MagikIME.java | 8 ++- .../keepass/timeout/TimeoutHelper.java | 11 +-- app/src/main/res/values/donottranslate.xml | 2 +- .../main/res/xml/application_preferences.xml | 2 +- app/src/main/res/xml/keyboard_preferences.xml | 9 ++- 6 files changed, 66 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java index 6a540197a..602f02fb2 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/KeyboardEntryNotificationService.java @@ -7,20 +7,24 @@ import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.os.Build; import android.os.IBinder; import android.support.v4.app.NotificationCompat; +import android.support.v7.preference.PreferenceManager; import android.util.Log; import com.kunzisoft.keepass.R; import com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver; import com.kunzisoft.keepass.magikeyboard.receiver.NotificationDeleteBroadcastReceiver; +import com.kunzisoft.keepass.timeout.TimeoutHelper; -import static android.content.ContentValues.TAG; import static com.kunzisoft.keepass.magikeyboard.receiver.LockBroadcastReceiver.LOCK_ACTION; public class KeyboardEntryNotificationService extends Service { + private static final String TAG = KeyboardEntryNotificationService.class.getName(); + private static final String CHANNEL_ID_KEYBOARD = "com.kunzisoft.keyboard.notification.entry.channel"; private static final String CHANNEL_NAME_KEYBOARD = "Magikeyboard notification"; @@ -100,30 +104,40 @@ public class KeyboardEntryNotificationService extends Service { notificationManager.cancel(notificationId); notificationManager.notify(notificationId, builder.build()); - } - // TODO Get timeout - /* - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - notificationTimeoutMilliSecs = prefs.getInt(getString(R.string.entry_timeout_key), 100000); - */ - - /* - stopTask(cleanNotificationTimer); - cleanNotificationTimer = new Thread(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(notificationTimeoutMilliSecs); - } catch (InterruptedException e) { - cleanNotificationTimer = null; - return; - } - notificationManager.cancel(notificationId); + // Timeout + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + String keyboardTimeout = prefs.getString(getString(R.string.keyboard_entry_timeout_key), + getString(R.string.timeout_default)); + try { + notificationTimeoutMilliSecs = Long.parseLong(keyboardTimeout); + } catch (NumberFormatException e) { + notificationTimeoutMilliSecs = TimeoutHelper.DEFAULT_TIMEOUT; } - }); - cleanNotificationTimer.start(); - */ + + if (notificationTimeoutMilliSecs != TimeoutHelper.TIMEOUT_NEVER) { + stopTask(cleanNotificationTimer); + cleanNotificationTimer = new Thread(() -> { + int maxPos = 100; + long posDurationMills = notificationTimeoutMilliSecs / maxPos; + for (int pos = maxPos; pos > 0; --pos) { + builder.setProgress(maxPos, pos, false); + notificationManager.notify(notificationId, builder.build()); + try { + Thread.sleep(posDurationMills); + } catch (InterruptedException e) { + break; + } + } + try { + pendingDeleteIntent.send(); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, e.getLocalizedMessage()); + } + }); + cleanNotificationTimer.start(); + } + } } private void stopTask(Thread task) { @@ -131,12 +145,19 @@ public class KeyboardEntryNotificationService extends Service { task.interrupt(); } - @Override - public void onDestroy() { + private void destroyKeyboardNotification() { + stopTask(cleanNotificationTimer); + cleanNotificationTimer = null; unregisterReceiver(lockBroadcastReceiver); pendingDeleteIntent.cancel(); notificationManager.cancel(notificationId); + } + + @Override + public void onDestroy() { + + destroyKeyboardNotification(); super.onDestroy(); } diff --git a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java index a77aba062..4fb7c1b55 100644 --- a/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java +++ b/app/src/main/java/com/kunzisoft/keepass/magikeyboard/MagikIME.java @@ -143,8 +143,10 @@ public class MagikIME extends InputMethodService if (keyboard_entry != null) keyboardView.setKeyboard(keyboard_entry); } else { - if (keyboard != null) + if (keyboard != null) { + dismissCustomKeys(); keyboardView.setKeyboard(keyboard); + } } } } @@ -192,7 +194,6 @@ public class MagikIME extends InputMethodService if (imeManager != null) imeManager.showInputMethodPicker(); } - // TODO Add a long press to choose the keyboard break; case KEY_CHANGE_KEYBOARD: InputMethodManager imeManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); @@ -203,6 +204,7 @@ public class MagikIME extends InputMethodService // TODO Unlock key break; case KEY_ENTRY: + deleteEntryKey(this); Intent intent = new Intent(this, EntryRetrieverActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); @@ -285,8 +287,8 @@ public class MagikIME extends InputMethodService @Override public void onDestroy() { - unregisterReceiver(lockBroadcastReceiver); dismissCustomKeys(); + unregisterReceiver(lockBroadcastReceiver); super.onDestroy(); } } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/timeout/TimeoutHelper.java b/app/src/main/java/com/kunzisoft/keepass/timeout/TimeoutHelper.java index a9e7f51f0..f37c07bd1 100644 --- a/app/src/main/java/com/kunzisoft/keepass/timeout/TimeoutHelper.java +++ b/app/src/main/java/com/kunzisoft/keepass/timeout/TimeoutHelper.java @@ -31,8 +31,9 @@ public class TimeoutHelper { private static final String TAG = "TimeoutHelper"; - private static final long DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes - + public static final long DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes + public static final long TIMEOUT_NEVER = -1; // Infinite + public static void recordTime(Activity act) { // Record timeout time in case timeout service is killed long time = System.currentTimeMillis(); @@ -56,9 +57,9 @@ public class TimeoutHelper { long cur_time = System.currentTimeMillis(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(act); - long timeout_start = prefs.getLong(act.getString(R.string.timeout_key), -1); + long timeout_start = prefs.getLong(act.getString(R.string.timeout_key), TIMEOUT_NEVER); // The timeout never started - if (timeout_start == -1) { + if (timeout_start == TIMEOUT_NEVER) { return true; } @@ -71,7 +72,7 @@ public class TimeoutHelper { } // We are set to never timeout - if (timeout == -1) { + if (timeout == TIMEOUT_NEVER) { return true; } diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 05acfad4e..83164db6e 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -144,7 +144,7 @@ true false - 300000 + 300000 60000 diff --git a/app/src/main/res/xml/application_preferences.xml b/app/src/main/res/xml/application_preferences.xml index c445cea78..152e7c253 100644 --- a/app/src/main/res/xml/application_preferences.xml +++ b/app/src/main/res/xml/application_preferences.xml @@ -57,7 +57,7 @@ android:entries="@array/timeout_options" android:entryValues="@array/timeout_values" android:dialogTitle="@string/app_timeout" - android:defaultValue="@string/app_timeout_default"/> + android:defaultValue="@string/timeout_default"/> - + android:entries="@array/timeout_options" + android:entryValues="@array/timeout_values" + android:dialogTitle="@string/keyboard_entry_timeout_title" + android:defaultValue="@string/timeout_default"/> + Date: Sat, 27 Oct 2018 14:17:59 +0200 Subject: [PATCH 8/8] Fix image --- .../drawable/capture_keyboard_fields_keys.png | Bin 3829 -> 3905 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/src/main/res/drawable/capture_keyboard_fields_keys.png b/app/src/main/res/drawable/capture_keyboard_fields_keys.png index 6dcb387b277ee150fdb43f3d70266c8f7f02f5f9..c3604dca1ae5ade3a740d092bc8c5f221d1ed5c8 100644 GIT binary patch delta 3894 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 delta 3817 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