Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use pin dialog with keyboard support #54

Merged
merged 1 commit into from
Mar 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion pretixprint/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
2 changes: 1 addition & 1 deletion pretixprint/app/src/main/assets/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<strong>libpretixprint</strong> (c) rami.io GmbH – Apache License 2.0<br><br>
<strong>cups4j</strong> (c) harwey – GNU Lesser General Public License 3<br><br>
<strong>escpos-coffee</strong> (c) Michael Billington, Marco Antonio Anastacio Cintra – MIT License<br><br>
<strong>pinlockview</strong> (c) aritraroyApache License 2.0<br><br>
<strong>LolliPin</strong> (c) OrangeGangstersMIT License<br><br>
<strong>Fonts</strong><br><br>
Roboto, Christian Robertson, Apache License 2.0<br>
Lato, Lukasz Dziedzic, SIL Open Font License<br>
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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()!!)
}
}
51 changes: 11 additions & 40 deletions pretixprint/app/src/main/java/eu/pretix/pretixprint/ui/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M22,3L7,3c-0.69,0 -1.23,0.35 -1.59,0.88L0,12l5.41,8.11c0.36,0.53 0.9,0.89 1.59,0.89h15c1.1,0 2,-0.9 2,-2L24,5c0,-1.1 -0.9,-2 -2,-2zM19,15.59L17.59,17 14,13.41 10.41,17 9,15.59 12.59,12 9,8.41 10.41,7 14,10.59 17.59,7 19,8.41 15.41,12 19,15.59z"/>
</vector>
Loading