diff --git a/pretixprint/app/build.gradle b/pretixprint/app/build.gradle
index 8cce85f1..8584d763 100644
--- a/pretixprint/app/build.gradle
+++ b/pretixprint/app/build.gradle
@@ -110,7 +110,6 @@ dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'com.tom_roush:pdfbox-android:1.8.10.0'
implementation "androidx.viewpager2:viewpager2:1.0.0"
- implementation 'com.andrognito.pinlockview:pinlockview:2.1.0'
// libpretixprint
implementation 'com.github.librepdf:openpdf:1.3.24'
diff --git a/pretixprint/app/src/main/assets/about.html b/pretixprint/app/src/main/assets/about.html
index 31bfda93..b7718b9d 100644
--- a/pretixprint/app/src/main/assets/about.html
+++ b/pretixprint/app/src/main/assets/about.html
@@ -21,7 +21,7 @@
libpretixprint (c) rami.io GmbH – Apache License 2.0
cups4j (c) harwey – GNU Lesser General Public License 3
escpos-coffee (c) Michael Billington, Marco Antonio Anastacio Cintra – MIT License
-pinlockview (c) aritraroy – Apache License 2.0
+LolliPin (c) OrangeGangsters – MIT License
Fonts
Roboto, Christian Robertson, Apache License 2.0
Lato, Lukasz Dziedzic, SIL Open Font License
diff --git a/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/KeyboardButtonView.kt b/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/KeyboardButtonView.kt
new file mode 100644
index 00000000..86d9843a
--- /dev/null
+++ b/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/KeyboardButtonView.kt
@@ -0,0 +1,88 @@
+package eu.pretix.pretixprint.ui
+
+import android.content.Context
+import android.os.Build
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.widget.ImageView
+import android.widget.RelativeLayout
+import android.widget.TextView
+import eu.pretix.pretixprint.R
+
+
+// (c) 2015 OrangeGangsters
+// MIT License
+// https://github.com/omadahealth/LolliPin/blob/0c523dfb7e9ee5dfcf37ad047cbb970ccd8794fb/lib/src/main/java/com/github/omadahealth/lollipin/lib/views/KeyboardButtonView.java
+
+interface KeyboardButtonClickedListener {
+
+}
+
+class KeyboardButtonView @JvmOverloads constructor(private val mContext: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : RelativeLayout(mContext, attrs, defStyleAttr) {
+
+ private var mKeyboardButtonClickedListener: KeyboardButtonClickedListener? = null
+ private var mRippleView: View? = null
+
+ init {
+ initializeView(attrs, defStyleAttr)
+ }
+
+ private fun initializeView(attrs: AttributeSet?, defStyleAttr: Int) {
+ if (attrs != null && !isInEditMode) {
+ val attributes = mContext.getTheme().obtainStyledAttributes(attrs, R.styleable.KeyboardButtonView,
+ defStyleAttr, 0)
+ val text = attributes.getString(R.styleable.KeyboardButtonView_lp_keyboard_button_text)
+ val image = attributes.getDrawable(R.styleable.KeyboardButtonView_lp_keyboard_button_image)
+ val rippleEnabled = attributes.getBoolean(R.styleable.KeyboardButtonView_lp_keyboard_button_ripple_enabled, true)
+
+ attributes.recycle()
+
+ val inflater = mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
+ val view = inflater.inflate(R.layout.view_keyboard_button, this) as KeyboardButtonView
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ view.focusable = NOT_FOCUSABLE
+ }
+
+ if (text != null) {
+ val textView = view.findViewById(R.id.keyboard_button_textview) as TextView
+ textView?.setText(text)
+ }
+ if (image != null) {
+ val imageView = view.findViewById(R.id.keyboard_button_imageview) as ImageView
+ if (imageView != null) {
+ imageView!!.setImageDrawable(image)
+ imageView!!.setVisibility(View.VISIBLE)
+ }
+ }
+
+ mRippleView = view.findViewById(R.id.pin_code_keyboard_button_ripple) as View
+ //mRippleView!!.setRippleAnimationListener(this)
+ if (mRippleView != null) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ mRippleView!!.focusable = NOT_FOCUSABLE
+ }
+ if (!rippleEnabled) {
+ mRippleView!!.setVisibility(View.INVISIBLE)
+ }
+ }
+ }
+ }
+
+ fun setOnRippleAnimationEndListener(keyboardButtonClickedListener: KeyboardButtonClickedListener) {
+ mKeyboardButtonClickedListener = keyboardButtonClickedListener
+ }
+
+ fun onRippleAnimationEnd() {
+ if (mKeyboardButtonClickedListener != null) {
+ //mKeyboardButtonClickedListener!!.onRippleAnimationEnd()
+ }
+ }
+
+ override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
+ onTouchEvent(event)
+ return false
+ }
+}
diff --git a/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/PinDialog.kt b/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/PinDialog.kt
new file mode 100644
index 00000000..4df83a49
--- /dev/null
+++ b/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/PinDialog.kt
@@ -0,0 +1,87 @@
+package eu.pretix.pretixprint.ui
+
+import android.app.Dialog
+import android.app.DialogFragment
+import android.os.Bundle
+import android.view.KeyEvent
+import android.view.View
+import androidx.databinding.ObservableField
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import eu.pretix.pretixprint.databinding.DialogPinBinding
+import java.util.Collections
+
+
+class PINInputDataHolder() {
+ val input = ObservableField("")
+ val text = ObservableField("")
+}
+
+interface ChecksPinFragment {
+ fun checkPin(pin: String)
+}
+
+// PinDialog, backported for old android.app.DialogFragment (no androidx yet)
+class PinDialog : DialogFragment() {
+ companion object {
+ const val TAG = "PinDialogFragment"
+ }
+
+ val data = PINInputDataHolder()
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ data.input.set("")
+
+ val binding = DialogPinBinding.inflate(parentFragment.layoutInflater)
+ binding.data = data
+
+ binding.keyboardButtonView0.setOnClickListener { pushDigit("0") }
+ binding.keyboardButtonView00.visibility = View.INVISIBLE
+ binding.keyboardButtonView1.setOnClickListener { pushDigit("1") }
+ binding.keyboardButtonView2.setOnClickListener { pushDigit("2") }
+ binding.keyboardButtonView3.setOnClickListener { pushDigit("3") }
+ binding.keyboardButtonView4.setOnClickListener { pushDigit("4") }
+ binding.keyboardButtonView5.setOnClickListener { pushDigit("5") }
+ binding.keyboardButtonView6.setOnClickListener { pushDigit("6") }
+ binding.keyboardButtonView7.setOnClickListener { pushDigit("7") }
+ binding.keyboardButtonView8.setOnClickListener { pushDigit("8") }
+ binding.keyboardButtonView9.setOnClickListener { pushDigit("9") }
+ binding.keyboardButtonViewBackspace.setOnClickListener { pushBackspace() }
+
+ return MaterialAlertDialogBuilder(context!!)
+ .setView(binding.root)
+ .setOnKeyListener { _, keyCode, event ->
+ if (event.action != KeyEvent.ACTION_DOWN) return@setOnKeyListener false
+
+ if (event.displayLabel.toString().matches(Regex("^[0-9]$"))) {
+ pushDigit(event.displayLabel.toString())
+ return@setOnKeyListener true
+ }
+ if (keyCode == KeyEvent.KEYCODE_DEL) {
+ pushBackspace()
+ return@setOnKeyListener true
+ }
+ if (keyCode == KeyEvent.KEYCODE_ESCAPE) {
+ dismiss()
+ return@setOnKeyListener true
+ }
+
+ return@setOnKeyListener false
+ }
+ .create()
+ }
+
+ protected fun pushBackspace() {
+ val current = data.input.get()!!
+ if (current.isNotBlank()) {
+ data.input.set(current.substring(0, current.length - 1))
+ }
+ data.text.set(Collections.nCopies(data.input.get()!!.length, "*").joinToString(""))
+ }
+
+ protected fun pushDigit(digit: String) {
+ val current = data.input.get()!!
+ data.input.set(current + digit)
+ data.text.set(Collections.nCopies(data.input.get()!!.length, "*").joinToString(""))
+ (parentFragment as ChecksPinFragment).checkPin(data.input.get()!!)
+ }
+}
\ No newline at end of file
diff --git a/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/Settings.kt b/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/Settings.kt
index 95f9f1ee..e2c5aedb 100644
--- a/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/Settings.kt
+++ b/pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/Settings.kt
@@ -13,23 +13,19 @@ import android.view.LayoutInflater
import android.webkit.WebView
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
-import com.andrognito.pinlockview.IndicatorDots
-import com.andrognito.pinlockview.PinLockListener
-import com.andrognito.pinlockview.PinLockView
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.pretix.pretixprint.BuildConfig
import eu.pretix.pretixprint.R
import org.jetbrains.anko.defaultSharedPreferences
import org.jetbrains.anko.intentFor
import org.jetbrains.anko.selector
-import java.lang.RuntimeException
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.min
-class SettingsFragment : PreferenceFragment() {
+class SettingsFragment : ChecksPinFragment, PreferenceFragment() {
val types = listOf("ticket", "badge", "receipt")
+ var pendingPinAction: ((pin: String) -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -180,46 +176,21 @@ class SettingsFragment : PreferenceFragment() {
valid("")
return
}
- val pinLength = defaultSharedPreferences.getString("pref_pin", "")!!.length
- val view = activity.layoutInflater.inflate(R.layout.dialog_pin, null)
- val dialog = MaterialAlertDialogBuilder(activity)
- .setView(view)
- .create()
- dialog.setOnShowListener {
- val mPinLockListener: PinLockListener = object : PinLockListener {
- override fun onComplete(pin: String) {
- this.onPinChange(pin.length, pin)
- }
-
- override fun onEmpty() {
- }
-
- override fun onPinChange(pinLength: Int, intermediatePin: String) {
- if (defaultSharedPreferences.getString("pref_pin", "") == intermediatePin) {
- dialog.dismiss()
- valid(intermediatePin)
- }
- }
- }
+ pendingPinAction = valid
+ PinDialog().show(childFragmentManager, PinDialog.TAG)
+ }
- val lockView = view.findViewById(R.id.pin_lock_view) as PinLockView
- lockView.pinLength = pinLength
- lockView.setPinLockListener(mPinLockListener)
- val idots = view.findViewById(R.id.indicator_dots) as IndicatorDots
- idots.pinLength = pinLength
- lockView.attachIndicatorDots(idots);
+ override fun checkPin(pin: String) {
+ if (defaultSharedPreferences.getString("pref_pin", "") == pin) {
+ (childFragmentManager.findFragmentByTag(PinDialog.TAG) as? PinDialog)?.dismiss()
+ pendingPinAction?.let { it(pin) }
}
- dialog.show()
}
- fun startWithPIN(intent: Intent, resultCode: Int? = null, bundle: Bundle? = null) {
+ fun startWithPIN(intent: Intent) {
pinProtect { pin ->
intent.putExtra("pin", pin)
- if (resultCode != null) {
- startActivityForResult(intent, resultCode, bundle)
- } else {
- startActivity(intent)
- }
+ startActivity(intent)
}
}
}
diff --git a/pretixprint/app/src/main/res/drawable/ic_backspace_black_24dp.xml b/pretixprint/app/src/main/res/drawable/ic_backspace_black_24dp.xml
new file mode 100644
index 00000000..35b3af30
--- /dev/null
+++ b/pretixprint/app/src/main/res/drawable/ic_backspace_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/pretixprint/app/src/main/res/layout/dialog_pin.xml b/pretixprint/app/src/main/res/layout/dialog_pin.xml
index 7f1afb19..ba6a2bbf 100644
--- a/pretixprint/app/src/main/res/layout/dialog_pin.xml
+++ b/pretixprint/app/src/main/res/layout/dialog_pin.xml
@@ -1,30 +1,197 @@
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+ android:minWidth="@dimen/dialog_minwidth">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pretixprint/app/src/main/res/layout/view_keyboard_button.xml b/pretixprint/app/src/main/res/layout/view_keyboard_button.xml
new file mode 100644
index 00000000..6191a8ab
--- /dev/null
+++ b/pretixprint/app/src/main/res/layout/view_keyboard_button.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pretixprint/app/src/main/res/values-de/strings.xml b/pretixprint/app/src/main/res/values-de/strings.xml
index 9b537de1..a79c9807 100644
--- a/pretixprint/app/src/main/res/values-de/strings.xml
+++ b/pretixprint/app/src/main/res/values-de/strings.xml
@@ -134,4 +134,5 @@
Druck bereit. Antippen um Druckdialog zu öffnen.
Einstellungen-PIN setzen
Einstellungen mit einer selbstgewählten PIN sperren, die zum Ändern der Drucker-Konfiguration eingegeben werden muss
+ PIN eingeben
\ No newline at end of file
diff --git a/pretixprint/app/src/main/res/values-w820dp/dimens.xml b/pretixprint/app/src/main/res/values-w820dp/dimens.xml
index 63fc8164..39bd0ff7 100644
--- a/pretixprint/app/src/main/res/values-w820dp/dimens.xml
+++ b/pretixprint/app/src/main/res/values-w820dp/dimens.xml
@@ -3,4 +3,5 @@
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
64dp
+ 420dp
diff --git a/pretixprint/app/src/main/res/values/attrs.xml b/pretixprint/app/src/main/res/values/attrs.xml
new file mode 100644
index 00000000..2dcbe121
--- /dev/null
+++ b/pretixprint/app/src/main/res/values/attrs.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pretixprint/app/src/main/res/values/dimens.xml b/pretixprint/app/src/main/res/values/dimens.xml
index c48c9dc5..879b0c15 100644
--- a/pretixprint/app/src/main/res/values/dimens.xml
+++ b/pretixprint/app/src/main/res/values/dimens.xml
@@ -5,4 +5,5 @@
30sp
15dp
30dp
+ 300dp
diff --git a/pretixprint/app/src/main/res/values/strings.xml b/pretixprint/app/src/main/res/values/strings.xml
index 83bd194e..cd8378c2 100644
--- a/pretixprint/app/src/main/res/values/strings.xml
+++ b/pretixprint/app/src/main/res/values/strings.xml
@@ -133,4 +133,5 @@
continuous
Set settings PIN
Lock settings with a custom PIN that must be entered if you want to change printer configuration
+ Enter PIN