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

Settings copy paste testv2 #12

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
7 changes: 5 additions & 2 deletions enigma-machine-android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-parcelize'
id 'kotlinx-serialization'
}

android {
Expand All @@ -12,8 +13,8 @@ android {
applicationId "com.smitpatel.enigmamachine"
minSdk 21
targetSdk 33
versionCode 10
versionName "2.0"
versionCode 12
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

Expand Down Expand Up @@ -43,6 +44,8 @@ dependencies {

implementation 'io.github.ShawnLin013:number-picker:2.4.13'

implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0"

// Datastore
implementation("androidx.datastore:datastore-preferences:1.0.0")

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,113 @@
package com.smitpatel.enigmamachine

import android.content.Context
import com.smitpatel.enigmamachine.models.Reflector
import com.smitpatel.enigmamachine.models.Rotor
import com.smitpatel.enigmamachine.ui.main.ClipboardCopyState
import org.json.JSONArray
import org.json.JSONObject

internal fun Char.letterToNumber() = this.code - 65

internal fun Int.numberToLetter() = Char(this + 65)

internal fun Rotor.RotorOption.getRotorLabelText(context: Context): String {
val rotorOptions = context.resources.getStringArray(R.array.rotor_options)
return when (this) {
Rotor.RotorOption.ROTOR_ONE -> rotorOptions[0]
Rotor.RotorOption.ROTOR_TWO -> rotorOptions[1]
Rotor.RotorOption.ROTOR_THREE -> rotorOptions[2]
Rotor.RotorOption.ROTOR_FOUR -> rotorOptions[3]
Rotor.RotorOption.ROTOR_FIVE -> rotorOptions[4]
}
}

internal fun String.toRotorOption(context: Context): Rotor.RotorOption {
val rotorOptions = context.resources.getStringArray(R.array.rotor_options)
return when (this.uppercase().trim()) {
rotorOptions[0] -> Rotor.RotorOption.ROTOR_ONE
rotorOptions[1] -> Rotor.RotorOption.ROTOR_TWO
rotorOptions[2] -> Rotor.RotorOption.ROTOR_THREE
rotorOptions[3] -> Rotor.RotorOption.ROTOR_FOUR
rotorOptions[4] -> Rotor.RotorOption.ROTOR_FIVE
else -> throw IllegalArgumentException("Invalid Roman numeral for RotorOption: $this")
}
}

internal fun String.toNumber(): Int {
val char = this.single().uppercaseChar()
if (!char.isLetter()) {
throw IllegalArgumentException("Input must be a letter: $this")
}
return char.letterToNumber()
}

internal fun Reflector.toStringRepresentation(context: Context) = when(this) {
Reflector.REFLECTOR_UKW_A -> context.getString(R.string.reflector_a)
Reflector.REFLECTOR_UKW_B -> context.getString(R.string.reflector_b)
Reflector.REFLECTOR_UKW_C -> context.getString(R.string.reflector_c)
}

internal fun String.toReflector(context: Context) = when (this.uppercase().trim()) {
context.getString(R.string.reflector_a) -> Reflector.REFLECTOR_UKW_A
context.getString(R.string.reflector_b) -> Reflector.REFLECTOR_UKW_B
context.getString(R.string.reflector_c) -> Reflector.REFLECTOR_UKW_C
else -> throw IllegalArgumentException("Invalid reflector string: $this")
}

internal fun ClipboardCopyState.SettingsCopyState.toSettingsJson(context: Context): String {
val json = JSONObject()

json.put("rotorOptions", JSONArray(arrayOf(
this.rotorOneLabel.getRotorLabelText(context),
this.rotorTwoLabel.getRotorLabelText(context),
this.rotorThreeLabel.getRotorLabelText(context),
)))

json.put("rotorPositions", JSONArray(arrayOf(
this.rotorOnePosition.numberToLetter(),
this.rotorTwoPosition.numberToLetter(),
this.rotorThreePosition.numberToLetter(),
)))

json.put("ringPositions", JSONArray(arrayOf(
this.rotorOnePosition.numberToLetter(),
this.rotorTwoPosition.numberToLetter(),
this.rotorThreePosition.numberToLetter(),
)))

json.put("reflector", this.reflector.toStringRepresentation(context))
json.put("plugboardPairs", JSONArray(this.plugboardPairs.map { JSONArray(arrayOf(it.first, it.second)) }))

return json.toString()
}

internal fun ClipboardCopyState.SettingsCopyState.toSettingsString(context: Context): String {

val rotorOptions = "${this.rotorOneLabel.getRotorLabelText(context)} " +
"${this.rotorTwoLabel.getRotorLabelText(context)} " +
this.rotorThreeLabel.getRotorLabelText(context)

val rotorPositions = "${this.rotorOnePosition.numberToLetter()} " +
"${this.rotorTwoPosition.numberToLetter()} " +
this.rotorThreePosition.numberToLetter()

val ringPositions = "${this.rotorOneRing.numberToLetter()} " +
"${this.rotorTwoRing.numberToLetter()} " +
this.rotorThreeRing.numberToLetter()

val plugboardPairs = this.plugboardPairs.map {
Pair(
first = it.first.numberToLetter(),
second = it.second.numberToLetter()
)
}

return context.getString(R.string.copy_settings_text,
rotorOptions,
rotorPositions,
ringPositions,
this.reflector.toStringRepresentation(context),
plugboardPairs,
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.smitpatel.enigmamachine.events

import com.smitpatel.enigmamachine.models.EnigmaHistoryItem
import com.smitpatel.enigmamachine.ui.RotorPosition

/**
Expand All @@ -11,13 +12,15 @@ sealed class EnigmaEvent {
data class RotorStartPositionChanged(val rotorPosition: RotorPosition, val start: Int): EnigmaEvent()
data class SettingMenuClosed(val didSettingsChanged : Boolean) : EnigmaEvent()
data class PasteRawText(val rawText: String) : EnigmaEvent()
data class PasteEnigmaSettings(val settings: EnigmaHistoryItem): EnigmaEvent()
object InputSpacePressed : EnigmaEvent()
object InputDeletePressed : EnigmaEvent()
object InputLongDeletePressed : EnigmaEvent()
object ToastMessageDisplayed : EnigmaEvent()
object CopyRawText : EnigmaEvent()
object CopyEncodedText : EnigmaEvent()
object CopySettings : EnigmaEvent()
object CopySettingsText : EnigmaEvent()
object CopySettingsJson : EnigmaEvent()
object ClosePasteError : EnigmaEvent()
object SaveState : EnigmaEvent()
object RestoreState : EnigmaEvent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,21 @@ import com.smitpatel.enigmamachine.ui.EnigmaSounds
import com.smitpatel.enigmamachine.ui.SoundEffects
import com.smitpatel.enigmamachine.ui.setting.SettingsFragment
import com.smitpatel.enigmamachine.events.EnigmaEvent
import com.smitpatel.enigmamachine.getRotorLabelText
import com.smitpatel.enigmamachine.letterToNumber
import com.smitpatel.enigmamachine.models.Reflector
import com.smitpatel.enigmamachine.models.EnigmaHistoryItem
import com.smitpatel.enigmamachine.models.Rotor
import com.smitpatel.enigmamachine.numberToLetter
import com.smitpatel.enigmamachine.toNumber
import com.smitpatel.enigmamachine.toReflector
import com.smitpatel.enigmamachine.toRotorOption
import com.smitpatel.enigmamachine.toSettingsJson
import com.smitpatel.enigmamachine.toSettingsString
import com.smitpatel.enigmamachine.ui.RotorPosition
import com.smitpatel.enigmamachine.ui.paste_error.PasteErrorFragment
import com.smitpatel.enigmamachine.viewmodels.EnigmaViewModel
import org.json.JSONObject
import java.lang.Exception
import java.util.Stack

class EnigmaMainActivity : AppCompatActivity() {

Expand Down Expand Up @@ -54,16 +62,6 @@ class EnigmaMainActivity : AppCompatActivity() {
}

private fun setupRenderer() {
fun getRotorLabelText(rotor: Rotor.RotorOption): String {
val rotorOptions = resources.getStringArray(R.array.rotor_options)
return when (rotor) {
Rotor.RotorOption.ROTOR_ONE -> rotorOptions[0]
Rotor.RotorOption.ROTOR_TWO -> rotorOptions[1]
Rotor.RotorOption.ROTOR_THREE -> rotorOptions[2]
Rotor.RotorOption.ROTOR_FOUR -> rotorOptions[3]
Rotor.RotorOption.ROTOR_FIVE -> rotorOptions[4]
}
}

fun showToast(text: String) {
Toast.makeText(applicationContext, text, Toast.LENGTH_SHORT).show()
Expand All @@ -75,9 +73,9 @@ class EnigmaMainActivity : AppCompatActivity() {
binding.rotors.rotor2.value = it.rotorTwoPosition + 1
binding.rotors.rotor3.value = it.rotorThreePosition + 1

binding.rotors.rotor1Label.text = getRotorLabelText(it.rotorOneLabel)
binding.rotors.rotor2Label.text = getRotorLabelText(it.rotorTwoLabel)
binding.rotors.rotor3Label.text = getRotorLabelText(it.rotorThreeLabel)
binding.rotors.rotor1Label.text = it.rotorOneLabel.getRotorLabelText(applicationContext)
binding.rotors.rotor2Label.text = it.rotorTwoLabel.getRotorLabelText(applicationContext)
binding.rotors.rotor3Label.text = it.rotorThreeLabel.getRotorLabelText(applicationContext)

binding.textboxes.textRaw.setText(it.rawMessage)
binding.textboxes.textCode.setText(it.encodedMessage)
Expand Down Expand Up @@ -113,53 +111,21 @@ class EnigmaMainActivity : AppCompatActivity() {
)
}

if (it.showSettingsErrorToast) {
showToast(text = resources.getString(R.string.settings_not_changed_toast_message))
viewModel.handleEvent(
event = EnigmaEvent.ToastMessageDisplayed
)
}

if (it.clipboardCopyState != null) {
val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
when (val settingsState = it.clipboardCopyState.settingsState) {
null -> {
clipboardManager.setPrimaryClip(ClipData.newPlainText(
"",
it.clipboardCopyState.text,
))
}
else -> {

fun getReflectorLabelText(reflector: Reflector) = when (reflector) {
Reflector.REFLECTOR_UKW_A -> getString(R.string.reflector_a)
Reflector.REFLECTOR_UKW_B -> getString(R.string.reflector_b)
Reflector.REFLECTOR_UKW_C -> getString(R.string.reflector_c)
}

val rotorOptions = "${getRotorLabelText(settingsState.rotorOneLabel)} " +
"${getRotorLabelText(settingsState.rotorTwoLabel)} " +
getRotorLabelText(settingsState.rotorThreeLabel)

val rotorPositions = "${settingsState.rotorOnePosition.numberToLetter()} " +
"${settingsState.rotorTwoPosition.numberToLetter()} " +
settingsState.rotorThreePosition.numberToLetter()

val ringPositions = "${settingsState.rotorOneRing.numberToLetter()} " +
"${settingsState.rotorTwoRing.numberToLetter()} " +
settingsState.rotorThreeRing.numberToLetter()

val plugboardPairs = settingsState.plugboardPairs.map { plugboardPair ->
Pair(
first = plugboardPair.first.numberToLetter(),
second = plugboardPair.second.numberToLetter()
)
}

clipboardManager.setPrimaryClip(ClipData.newPlainText(
"",
getString(R.string.copy_settings_text,
rotorOptions,
rotorPositions,
ringPositions,
getReflectorLabelText(settingsState.reflector),
plugboardPairs,
)
))
}
val settingsState = it.clipboardCopyState.settingsState
val json = it.clipboardCopyState.json
when {
settingsState == null -> clipboardManager.setPrimaryClip(ClipData.newPlainText("", it.clipboardCopyState.text))
json -> clipboardManager.setPrimaryClip(ClipData.newPlainText("", settingsState.toSettingsJson(applicationContext)))
else -> clipboardManager.setPrimaryClip(ClipData.newPlainText("", settingsState.toSettingsString(applicationContext)))
}

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
Expand Down Expand Up @@ -316,8 +282,12 @@ class EnigmaMainActivity : AppCompatActivity() {
viewModel.handleEvent(EnigmaEvent.CopyEncodedText)
true
}
R.id.copy_enigma_settings -> {
viewModel.handleEvent(EnigmaEvent.CopySettings)
R.id.copy_enigma_settings_text -> {
viewModel.handleEvent(EnigmaEvent.CopySettingsText)
true
}
R.id.copy_enigma_settings_json -> {
viewModel.handleEvent(EnigmaEvent.CopySettingsJson)
true
}
R.id.paste_raw_text -> {
Expand All @@ -328,7 +298,65 @@ class EnigmaMainActivity : AppCompatActivity() {
}
true
}
R.id.paste_enigma_settings -> {
val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
val clipboardText = clipboardManager.primaryClip?.getItemAt(0)?.text

if (!clipboardText.isNullOrEmpty()) {

try {
val json = JSONObject(clipboardText.toString())

val jsonRotorOptions = json.getJSONArray("rotorOptions")
val rotorOptions = (0 until jsonRotorOptions.length()).map {
jsonRotorOptions.getString(it).toRotorOption(applicationContext)
}

// Need to ensure these are within the
val jsonRotorPositions = json.getJSONArray("rotorPositions")
val rotorPositions = (0 until jsonRotorPositions.length()).map {
jsonRotorPositions.getString(it).toNumber()
}

val jsonRingPositions = json.getJSONArray("ringPositions")
val ringPositions = (0 until jsonRingPositions.length()).map {
jsonRingPositions.getString(it).toNumber()
}

val reflector = json.getString("reflector").toReflector(applicationContext)

val jsonPlugboardPairs = json.getJSONArray("plugboardPairs")
val plugboardPairs = mutableSetOf<Pair<Int, Int>>()
for (i in 0 until jsonPlugboardPairs.length()) {
val jsonPair = jsonPlugboardPairs.getJSONArray(i)
plugboardPairs.add(
Pair(
first = jsonPair.getInt(0),
second = jsonPair.getInt(1)
)
)
}

viewModel.handleEvent(EnigmaEvent.PasteEnigmaSettings(
settings = EnigmaHistoryItem(
rotorOneOption = rotorOptions[0],
rotorTwoOption = rotorOptions[1],
rotorThreeOption = rotorOptions[2],
rotorOnePosition = rotorPositions[0],
rotorTwoPosition = rotorPositions[1],
rotorThreePosition = rotorPositions[2],
ringOneOption = ringPositions[0],
ringTwoOption = ringPositions[1],
ringThreeOption = ringPositions[2],
reflectorOption = reflector,
plugboardPairs = plugboardPairs,
)
))
} catch (e : Exception) {
}
}
true
}
else -> super.onContextItemSelected(item)
}

}
Loading