Skip to content

Commit

Permalink
[4.0.4] Android drawing is different from the rest, Fixes #88
Browse files Browse the repository at this point in the history
  • Loading branch information
g0dkar committed Nov 10, 2023
1 parent 888b0bb commit 09c13c8
Show file tree
Hide file tree
Showing 36 changed files with 861 additions and 68 deletions.
11 changes: 7 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ plugins {

// Docs Plugins
alias(libs.plugins.dokka)

// Here because of the Android Examples
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
}

repositories {
Expand All @@ -41,7 +45,7 @@ val javaVersion = JavaVersion.VERSION_17
val javaVersionNumber = javaVersion.majorVersion.toInt()

kotlin {
applyDefaultHierarchyTemplate()
//applyDefaultHierarchyTemplate()

jvm {
jvmToolchain(javaVersionNumber)
Expand All @@ -53,7 +57,8 @@ kotlin {
}
}

androidTarget {
android {
// androidTarget {
jvmToolchain(javaVersionNumber)
publishLibraryVariants("release")
}
Expand All @@ -69,15 +74,13 @@ kotlin {
commonWebpackConfig {
mode = PRODUCTION
sourceMaps = true
// output?.library = "qrcodeKotlin"
}

testTask {
enabled = false
}

binaries.library()
// binaries.executable()
generateTypeScriptDefinitions()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.github.g0dkar.qrcode

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class AboutActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_about)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package io.github.g0dkar.qrcode

import android.content.Intent
import android.graphics.Bitmap
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.postDelayed
import androidx.core.widget.doOnTextChanged
import qrcode.QRCode

class NewQRCodeActivity : AppCompatActivity() {
private lateinit var qrCodeData: EditText
private lateinit var qrCodeImageView: ImageView
private lateinit var saveButton: Button
private var qrCodeIsValid = false

private val handler = Handler(Looper.getMainLooper())

companion object {
const val QRCODE_DATA = "qrCodeData"
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new_qrcode)

qrCodeData = findViewById(R.id.newQRCodeData)
qrCodeImageView = findViewById(R.id.newQRCodePreviewImage)
saveButton = findViewById(R.id.newQRCodeBtn)

qrCodeData.doOnTextChanged { text, _, _, _ ->
val string = text?.toString()?.trim()

qrCodeIsValid = if (string.isNullOrBlank()) {
qrCodeImageView.setImageBitmap(null)

false
} else {
try {
handler.removeCallbacksAndMessages(null)
handler.postDelayed(250) {
val qrCodeBitmap = QRCode(string).render().nativeImage() as Bitmap
qrCodeImageView.setImageBitmap(qrCodeBitmap)
}

true
} catch (t: Throwable) {
Toast.makeText(
this@NewQRCodeActivity,
R.string.new_qrcode_error_preview,
Toast.LENGTH_LONG,
).show()

qrCodeImageView.setImageBitmap(null)

false
}
}
}

saveButton.setOnClickListener {
save()
}
}

private fun save() {
val resultIntent = Intent()
val qrCodeDataText = qrCodeData.text.toString()

if (qrCodeDataText.isBlank() || !qrCodeIsValid) {
setResult(RESULT_CANCELED, resultIntent)
} else {
resultIntent.putExtra(QRCODE_DATA, qrCodeDataText)
setResult(RESULT_OK, resultIntent)
}

finish()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.github.g0dkar.qrcode

import android.content.SharedPreferences
import android.graphics.Bitmap
import qrcode.QRCode
import java.time.OffsetDateTime
import java.time.ZoneOffset

data class QRCodeData(
val data: String,
val timestamp: OffsetDateTime = OffsetDateTime.now(ZoneOffset.UTC),
val bitmap: Bitmap = QRCode(data).render().nativeImage() as Bitmap,
) : Comparable<QRCodeData> {
fun persist(sharedPreferencesEditor: SharedPreferences.Editor) {
val key = timestamp.toEpochSecond().toString()
sharedPreferencesEditor.putString(key, data)
}

override fun compareTo(other: QRCodeData): Int = timestamp.compareTo(other.timestamp)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.github.g0dkar.qrcode

import android.os.Bundle
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import java.time.Instant
import java.time.OffsetDateTime
import java.time.ZoneOffset

class QRCodeDetailActivity : AppCompatActivity() {
companion object {
const val QRCODE_DATA = "qrCodeData"
const val QRCODE_TIMESTAMP = "qrCodeTimestamp"
}

private lateinit var qrCodeDetailText: TextView
private lateinit var qrCodeDetailImage: ImageView
private lateinit var qrCodeDetailFab: View

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_qrcode_detail)

qrCodeDetailText = findViewById(R.id.qrCodeDetailText)
qrCodeDetailImage = findViewById(R.id.qrCodeDetailImage)
qrCodeDetailFab = findViewById(R.id.qrCodeDetailFab)

setBrightness()

val qrCodeData = intent.getStringExtra(QRCODE_DATA) ?: "ERROR"
val qrCodeTimestamp = intent.getLongExtra(QRCODE_TIMESTAMP, Instant.now().epochSecond)
val qrCode = QRCodeData(qrCodeData, OffsetDateTime.ofInstant(Instant.ofEpochSecond(qrCodeTimestamp), ZoneOffset.UTC))

qrCodeDetailText.text = qrCode.data
qrCodeDetailImage.setImageBitmap(qrCode.bitmap)
}

private fun setBrightness() {
try {
val layout = window.attributes
layout.screenBrightness = 1.0f
window.attributes = layout
} catch (_: Exception) {
// NOOP
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package io.github.g0dkar.qrcode

import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import io.github.g0dkar.qrcode.NewQRCodeActivity.Companion.QRCODE_DATA
import io.github.g0dkar.qrcode.extra.QRCodeListAdapter
import io.github.g0dkar.qrcode.extra.QRCodeListDatasource

class QRCodeListActivity : AppCompatActivity() {
private val listAdapter = QRCodeListAdapter {
val intent = Intent(this@QRCodeListActivity, QRCodeDetailActivity::class.java)
intent.putExtra(QRCodeDetailActivity.QRCODE_DATA, it.data)
intent.putExtra(QRCodeDetailActivity.QRCODE_TIMESTAMP, it.timestamp.toEpochSecond())
startActivity(intent)
}

private lateinit var recyclerView: RecyclerView
private lateinit var fab: View
private lateinit var newQRCodeActivity: ActivityResultLauncher<Intent>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

fab = findViewById(R.id.fab)
recyclerView = findViewById(R.id.recycler_view)

QRCodeListDatasource.fromContext(this)

recyclerView.adapter = listAdapter

fab.setOnClickListener {
startNewQRCodeActivity()
}

newQRCodeActivity = registerForActivityResult(StartActivityForResult()) {
if (it.data != null) {
val result = it.resultCode

if (result == RESULT_OK) {
val qrCodeData = it.data?.getStringExtra(QRCODE_DATA)

if (qrCodeData != null) {
QRCodeListDatasource.add(qrCodeData)
} else {
Toast.makeText(
this@QRCodeListActivity,
R.string.new_qrcode_error,
Toast.LENGTH_LONG
).show()
}
} else {
Toast.makeText(
this@QRCodeListActivity,
R.string.new_qrcode_error,
Toast.LENGTH_LONG
).show()
}
}
}
}

override fun onResume() {
super.onResume()

QRCodeListDatasource.liveData.observe(this) {
if (it != null) {
listAdapter.submitList(it)
}
}
}

override fun onStop() {
super.onStop()

QRCodeListDatasource.liveData.removeObservers(this)
}

private fun startNewQRCodeActivity() {
val intent = Intent(this, NewQRCodeActivity::class.java)
newQRCodeActivity.launch(intent)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.github.g0dkar.qrcode.extra

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import io.github.g0dkar.qrcode.QRCodeData
import io.github.g0dkar.qrcode.R

class QRCodeListAdapter(
private val onClick: (QRCodeData) -> Unit
) : ListAdapter<QRCodeData, QRCodeListViewHolder>(QRCodeListDiffCallback) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QRCodeListViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.qrcode_list_item, parent, false)
return QRCodeListViewHolder(view, onClick)
}

override fun onBindViewHolder(holder: QRCodeListViewHolder, position: Int) {
val qrCodeData = getItem(position)
holder.bind(qrCodeData)
}

}

class QRCodeListViewHolder(
itemView: View,
val onClick: (QRCodeData) -> Unit
) : RecyclerView.ViewHolder(itemView) {
private val qrCodeListItemTextView: TextView = itemView.findViewById(R.id.qrcode_data)
private val qrCodeListItemImageView: ImageView = itemView.findViewById(R.id.qrcode_image)
private var currentQrCodeData: QRCodeData? = null

init {
itemView.setOnClickListener {
currentQrCodeData?.let {
onClick(it)
}
}
}

fun bind(qrCodeData: QRCodeData) {
currentQrCodeData = qrCodeData

qrCodeListItemTextView.text = qrCodeData.data
qrCodeListItemImageView.setImageBitmap(qrCodeData.bitmap)
}
}

object QRCodeListDiffCallback : DiffUtil.ItemCallback<QRCodeData>() {
override fun areItemsTheSame(oldItem: QRCodeData, newItem: QRCodeData): Boolean {
return oldItem == newItem
}

override fun areContentsTheSame(oldItem: QRCodeData, newItem: QRCodeData): Boolean {
return oldItem.data == newItem.data
}
}
Loading

0 comments on commit 09c13c8

Please sign in to comment.