Skip to content

Commit

Permalink
Add QR code scanner to UnifiedPush settings
Browse files Browse the repository at this point in the history
And remove options to manually edit MollySocket setup
  • Loading branch information
p1gp1g authored and valldrac committed Nov 21, 2024
1 parent e06507c commit a5f5b44
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
package im.molly.unifiedpush.components.settings.app.notifications

import android.content.DialogInterface
import android.content.res.Resources
import android.text.InputType
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.launch
import androidx.annotation.StringRes
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.molly.unifiedpush.model.RegistrationStatus
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
Expand All @@ -28,6 +24,14 @@ class UnifiedPushSettingsFragment : DSLSettingsFragment(R.string.NotificationDel

private lateinit var viewModel: UnifiedPushSettingsViewModel

private val qrScanLauncher: ActivityResultLauncher<Unit> =
registerForActivityResult(MollySocketQrScannerActivity.Contract()) { mollySocket ->
if (mollySocket != null) {
viewModel.initializeMollySocket(mollySocket)
viewModel.refresh()
}
}

override fun bindAdapter(adapter: MappingAdapter) {
val factory = UnifiedPushSettingsViewModel.Factory(requireActivity().application)

Expand All @@ -54,6 +58,19 @@ class UnifiedPushSettingsFragment : DSLSettingsFragment(R.string.NotificationDel
summary = DSLSettingsText.from(getStatusSummary(state)),
)

textPref(
title = DSLSettingsText.from(R.string.UnifiedPushSettingsFragment__mollysocket_server_title),
summary = DSLSettingsText.from(
if (state.airGapped) {
getString(R.string.UnifiedPushSettingsFragment__mollysocket_server_sumarry_air_gapped)
} else {
state.mollySocketUrl ?: "Error"
}
)
)

dividerPref()

if (state.distributors.isEmpty()) {
textPref(
title = DSLSettingsText.from(R.string.UnifiedPushSettingsFragment__distributor_app),
Expand All @@ -70,17 +87,6 @@ class UnifiedPushSettingsFragment : DSLSettingsFragment(R.string.NotificationDel
)
}

dividerPref()

switchPref(
title = DSLSettingsText.from(getString(R.string.UnifiedPushSettingsFragment__air_gapped)),
summary = DSLSettingsText.from(getString(R.string.UnifiedPushSettingsFragment__air_gapped_summary)),
isChecked = state.airGapped,
onClick = {
viewModel.setUnifiedPushAirGapped(!state.airGapped)
}
)

if (state.airGapped) {
val parameters = getServerParameters(state) ?: ""

Expand All @@ -105,13 +111,6 @@ class UnifiedPushSettingsFragment : DSLSettingsFragment(R.string.NotificationDel
},
)

clickPref(
title = DSLSettingsText.from(getString(R.string.UnifiedPushSettingsFragment__server_url)),
summary = DSLSettingsText.from(state.mollySocketUrl ?: getString(R.string.UnifiedPushSettingsFragment__no_server_url_summary)),
iconEnd = getMollySocketUrlIcon(state),
onClick = { urlDialog(state) },
)

clickPref(
title = DSLSettingsText.from(getString(R.string.UnifiedPushSettingsFragment__test_configuration)),
summary = DSLSettingsText.from(getString(R.string.UnifiedPushSettingsFragment__tap_to_request_a_test_notification_from_mollysocket)),
Expand All @@ -121,6 +120,13 @@ class UnifiedPushSettingsFragment : DSLSettingsFragment(R.string.NotificationDel
},
)
}
clickPref(
title = DSLSettingsText.from(getString(R.string.UnifiedPushSettingsFragment__change_mollysocket_configuration_title)),
summary = DSLSettingsText.from(getString(R.string.UnifiedPushSettingsFragment__change_mollysocket_configuration_summary)),
onClick = {
qrScanLauncher.launch()
},
)
}
}

Expand All @@ -131,49 +137,6 @@ class UnifiedPushSettingsFragment : DSLSettingsFragment(R.string.NotificationDel
return "connection add $aci ${device.deviceId} ${device.password} $endpoint"
}

private fun urlDialog(state: UnifiedPushSettingsState) {
val alertDialog = MaterialAlertDialogBuilder(requireContext())
val input = EditText(requireContext()).apply {
inputType = InputType.TYPE_TEXT_VARIATION_URI
setText(state.mollySocketUrl)
}
alertDialog.setEditText(
input
)
alertDialog.setPositiveButton(getString(android.R.string.ok)) { _: DialogInterface, _: Int ->
val isValid = viewModel.setMollySocketUrl(input.text.toString())
if (!isValid && input.text.isNotEmpty()) {
Toast.makeText(requireContext(), R.string.UnifiedPushSettingsFragment__invalid_server_url, Toast.LENGTH_LONG).show()
}
}
alertDialog.show()
}

private val Float.toPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()

private fun MaterialAlertDialogBuilder.setEditText(editText: EditText): MaterialAlertDialogBuilder {
val container = FrameLayout(context)
container.addView(editText)
val containerParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT
)
val marginHorizontal = 48F
val marginTop = 16F
containerParams.topMargin = (marginTop / 2).toPx
containerParams.leftMargin = marginHorizontal.toInt()
containerParams.rightMargin = marginHorizontal.toInt()
container.layoutParams = containerParams

val superContainer = FrameLayout(context)
superContainer.addView(container)

setView(superContainer)

return this
}

@StringRes
private fun getStatusSummary(state: UnifiedPushSettingsState): Int {
return when {
Expand Down Expand Up @@ -208,12 +171,4 @@ class UnifiedPushSettingsFragment : DSLSettingsFragment(R.string.NotificationDel
}
}
}

private fun getMollySocketUrlIcon(state: UnifiedPushSettingsState): DSLSettingsIcon? {
return when (state.serverUnreachable) {
true -> DSLSettingsIcon.from(R.drawable.ic_alert)
false -> DSLSettingsIcon.from(R.drawable.ic_check_20)
else -> null
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import im.molly.unifiedpush.MollySocketRepository
import im.molly.unifiedpush.model.MollySocket
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import org.signal.core.util.ThreadUtil
Expand All @@ -33,6 +34,14 @@ class UnifiedPushSettingsViewModel(private val application: Application) : ViewM
store.update { getState() }
}

fun initializeMollySocket(mollySocket: MollySocket) {
SignalStore.unifiedpush.apply {
airGapped = mollySocket is MollySocket.AirGapped
mollySocketUrl = (mollySocket as? MollySocket.WebServer)?.url
mollySocketVapid = mollySocket.vapid
}
}

private fun refreshAndUpdateRegistration(pingOnRegister: Boolean = false) {
refresh()
AppDependencies.jobManager.add(UnifiedPushRefreshJob(pingOnRegister))
Expand Down
9 changes: 4 additions & 5 deletions app/src/main/res/values/strings2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,11 @@
<string name="UnifiedPushSettingsFragment__distributor_app">Distributor app</string>
<string name="UnifiedPushSettingsFragment__status">Status</string>
<string name="UnifiedPushSettingsFragment__tap_to_copy_to_clipboard">Tap to copy to clipboard</string>
<string name="UnifiedPushSettingsFragment__air_gapped">Air gapped</string>
<string name="UnifiedPushSettingsFragment__server_parameters">Server parameters</string>
<string name="UnifiedPushSettingsFragment__account_id">Account ID</string>
<string name="UnifiedPushSettingsFragment__server_url">Server URL</string>
<string name="UnifiedPushSettingsFragment__no_server_url_summary">Please provide the MollySocket server URL</string>
<string name="UnifiedPushSettingsFragment__test_configuration">Test configuration</string>
<string name="UnifiedPushSettingsFragment__tap_to_request_a_test_notification_from_mollysocket">Tap to request a test notification from MollySocket</string>
<string name="UnifiedPushSettingsFragment__a_test_notification_should_appear_in_a_few_moments">A test notification should appear in a few moments…</string>
<string name="UnifiedPushSettingsFragment__invalid_server_url">Invalid server URL</string>
<string name="UnifiedPushSettingsFragment__status_summary_mollysocket_url_missing">Missing MollySocket URL</string>
<string name="UnifiedPushSettingsFragment__status_summary_pending">Pending</string>
<string name="UnifiedPushSettingsFragment__status_summary_air_gapped_pending">Waiting for confirmation from the MollySocket server</string>
Expand All @@ -158,7 +154,6 @@
<string name="UnifiedPushSettingsFragment__status_summary_forbidden_endpoint">The endpoint is forbidden by the server</string>
<string name="UnifiedPushSettingsFragment__status_summary_no_distributor">No UnifiedPush distributor installed</string>
<string name="UnifiedPushSettingsFragment__status_summary_distributor_not_selected">No distributor app selected</string>
<string name="UnifiedPushSettingsFragment__air_gapped_summary">Enable if your MollySocket server can\'t be reached from the internet. You\'ll need to manually add your account to the server.</string>
<string name="UnifiedPushSettingsViewModel__mollysocket_server_not_found">"MollySocket server not found. Please check the URL and try again."</string>
<string name="UnifiedPushNotificationBuilder__mollysocket_device_limit_hit">You\'ve reached the limit of %d linked devices. To link your MollySocket server, please remove a device first.</string>
<string name="UnifiedPushNotificationBuilder__endpoint_changed_air_gapped">Your UnifiedPush endpoint has changed. You must update your connection on MollySocket.</string>
Expand All @@ -175,4 +170,8 @@
<string name="MollySocketLink_the_qr_code_was_invalid">The QR code was invalid</string>
<string name="MollySocketLink_mollysocket_server_not_found_at_s">MollySocket server not found at \'%s\'</string>
<string name="MollySocketLink_experienced_a_network_error_please_try_again">Experienced a network error. Please try again.</string>
<string name="UnifiedPushSettingsFragment__change_mollysocket_configuration_title">Scan MollySocket QR Code</string>
<string name="UnifiedPushSettingsFragment__change_mollysocket_configuration_summary">Tap to scan and select a new MollySocket server</string>
<string name="UnifiedPushSettingsFragment__mollysocket_server_title">MollySocket server</string>
<string name="UnifiedPushSettingsFragment__mollysocket_server_sumarry_air_gapped">Air gapped</string>
</resources>

0 comments on commit a5f5b44

Please sign in to comment.