Skip to content

Commit

Permalink
Fix json decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
massivemadness committed Feb 4, 2025
1 parent 2c012ec commit a8fdc28
Show file tree
Hide file tree
Showing 20 changed files with 173 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@

package com.blacksquircle.ui.core.extensions

import android.net.Uri
import com.google.gson.Gson
import java.net.URLDecoder
import java.net.URLEncoder

fun String.encodeUrl(encoding: String = "UTF-8"): String = URLEncoder.encode(this, encoding)
fun String.decodeUrl(encoding: String = "UTF-8"): String = URLDecoder.decode(this, encoding)
fun String.encodeUri(): String = Uri.encode(this)
fun String.decodeUri(): String = Uri.decode(this)

fun Gson.toJsonEncoded(any: Any): String = toJson(any).encodeUrl()
fun Any.toJsonEncoded(): String {
return Gson().toJson(this).encodeUri()
}
inline fun <reified T> String.fromJsonEncoded(): T {
return Gson().fromJson(this.decodeUri(), T::class.java)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.navArgs
import com.blacksquircle.ui.core.extensions.decodeUri
import com.blacksquircle.ui.feature.editor.R
import com.blacksquircle.ui.feature.editor.ui.mvi.EditorIntent
import com.blacksquircle.ui.feature.editor.ui.viewmodel.EditorViewModel
Expand All @@ -35,7 +36,7 @@ class CloseModifiedDialog : DialogFragment() {

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return AlertDialog.Builder(requireContext())
.setTitle(navArgs.fileName)
.setTitle(navArgs.fileName.decodeUri())
.setMessage(R.string.dialog_message_close_tab)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.action_close) { _, _ ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.navArgs
import com.blacksquircle.ui.core.extensions.decodeUri
import com.blacksquircle.ui.core.extensions.showToast
import com.blacksquircle.ui.feature.editor.R
import com.blacksquircle.ui.feature.editor.ui.mvi.EditorIntent
Expand All @@ -39,7 +40,10 @@ class ForceSyntaxDialog : DialogFragment() {
val langEntries = resources.getStringArray(R.array.language_name)
return AlertDialog.Builder(requireContext())
.setTitle(R.string.dialog_title_force_syntax)
.setSingleChoiceItems(langNames, langEntries.indexOf(navArgs.languageName)) { _, which ->
.setSingleChoiceItems(
langNames,
langEntries.indexOf(navArgs.languageName.decodeUri())
) { _, which ->
val intent = EditorIntent.ForceSyntaxHighlighting(langEntries[which])
viewModel.obtainEvent(intent)
requireContext().showToast(text = langNames[which])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@

package com.blacksquircle.ui.feature.editor.ui.navigation

import com.blacksquircle.ui.core.extensions.encodeUrl
import com.blacksquircle.ui.core.extensions.encodeUri
import com.blacksquircle.ui.core.navigation.Screen

sealed class EditorScreen(route: String) : Screen<String>(route) {

class ForceSyntaxDialog(languageName: String) : EditorScreen(
route = "blacksquircle://editor/syntax?languageName=${languageName.encodeUrl()}",
route = "blacksquircle://editor/syntax?languageName=${languageName.encodeUri()}",
)
class CloseModifiedDialog(position: Int, fileName: String) : EditorScreen(
route = "blacksquircle://editor/close?position=$position&fileName=${fileName.encodeUrl()}",
route = "blacksquircle://editor/close?position=$position&fileName=${fileName.encodeUri()}",
)

data object GotoLine : EditorScreen("blacksquircle://editor/goto")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.blacksquircle.ui.core.extensions.decodeUri
import com.blacksquircle.ui.feature.explorer.R
import com.blacksquircle.ui.feature.explorer.ui.mvi.ExplorerIntent
import com.blacksquircle.ui.feature.explorer.ui.viewmodel.ExplorerViewModel
Expand All @@ -42,7 +43,7 @@ class DeleteDialog : DialogFragment() {
val dialogTitle = if (isMultiDelete) {
getString(R.string.dialog_title_multi_delete)
} else {
navArgs.fileName
navArgs.fileName.decodeUri()
}

val dialogMessage = if (isMultiDelete) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import androidx.navigation.fragment.navArgs
import com.blacksquircle.ui.core.extensions.fromJsonEncoded
import com.blacksquircle.ui.feature.explorer.R
import com.blacksquircle.ui.feature.explorer.data.utils.toReadableDate
import com.blacksquircle.ui.feature.explorer.data.utils.toReadableSize
Expand All @@ -37,8 +38,7 @@ class PropertiesDialog : DialogFragment() {
private val navArgs by navArgs<PropertiesDialogArgs>()

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val fileModel = Gson().fromJson(navArgs.data, FileModel::class.java) // FIXME

val fileModel = navArgs.data.fromJsonEncoded<FileModel>()
val readableSize = fileModel.size.toReadableSize()
val readableDate = fileModel.lastModified
.toReadableDate(getString(R.string.properties_date_format))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.blacksquircle.ui.core.extensions.decodeUri
import com.blacksquircle.ui.feature.explorer.R
import com.blacksquircle.ui.feature.explorer.databinding.DialogRenameBinding
import com.blacksquircle.ui.feature.explorer.ui.mvi.ExplorerIntent
Expand All @@ -39,7 +40,7 @@ class RenameDialog : DialogFragment() {

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val binding = DialogRenameBinding.inflate(layoutInflater)
binding.input.setText(navArgs.fileName)
binding.input.setText(navArgs.fileName.decodeUri())

return AlertDialog.Builder(requireContext())
.setTitle(R.string.dialog_title_rename)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package com.blacksquircle.ui.feature.explorer.ui.navigation

import com.blacksquircle.ui.core.extensions.encodeUrl
import com.blacksquircle.ui.core.extensions.encodeUri
import com.blacksquircle.ui.core.extensions.toJsonEncoded
import com.blacksquircle.ui.core.navigation.Screen
import com.blacksquircle.ui.feature.explorer.data.utils.Operation
Expand All @@ -27,16 +27,16 @@ import com.google.gson.Gson
sealed class ExplorerScreen(route: String) : Screen<String>(route) {

class DeleteDialog(fileName: String, fileCount: Int) : ExplorerScreen(
route = "blacksquircle://explorer/delete?fileName=${fileName.encodeUrl()}&fileCount=$fileCount",
route = "blacksquircle://explorer/delete?fileName=${fileName.encodeUri()}&fileCount=$fileCount",
)
class RenameDialog(fileName: String) : ExplorerScreen(
route = "blacksquircle://explorer/rename?fileName=${fileName.encodeUrl()}",
route = "blacksquircle://explorer/rename?fileName=${fileName.encodeUri()}",
)
class ProgressDialog(totalCount: Int, operation: Operation) : ExplorerScreen(
route = "blacksquircle://explorer/progress?totalCount=$totalCount&operation=${operation.value}",
)
class PropertiesDialog(fileModel: FileModel) : ExplorerScreen(
route = "blacksquircle://explorer/properties?data=${Gson().toJsonEncoded(fileModel)}",
route = "blacksquircle://explorer/properties?data=${fileModel.toJsonEncoded()}",
)
class AuthDialog(authMethod: AuthMethod) : ExplorerScreen(
route = "blacksquircle://explorer/authenticate?authMethod=${authMethod.value}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ internal class ServerDialog : DialogFragment() {
when (result) {
is ContractResult.Success -> {
val filePath = context?.extractFilePath(result.uri)
viewModel.onKeyFileChosen(filePath.orEmpty())
viewModel.onKeyFileSelected(filePath.orEmpty())
}
is ContractResult.Canceled -> Unit
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ import com.google.gson.Gson
internal sealed class ServersScreen(route: String) : Screen<String>(route) {

class EditServer(serverConfig: ServerConfig) : ServersScreen(
route = "blacksquircle://settings/cloud/edit?data=${Gson().toJsonEncoded(serverConfig)}",
route = "blacksquircle://settings/cloud/edit?data=${serverConfig.toJsonEncoded()}",
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.blacksquircle.ui.feature.servers.ui.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.blacksquircle.ui.core.extensions.fromJsonEncoded
import com.blacksquircle.ui.core.mvi.ViewEvent
import com.blacksquircle.ui.feature.servers.ui.dialog.ServerViewState
import com.blacksquircle.ui.feature.servers.ui.dialog.internal.PassphraseAction
Expand Down Expand Up @@ -111,7 +112,7 @@ internal class ServerViewModel @AssistedInject constructor(
}
}

fun onKeyFileChosen(filePath: String) {
fun onKeyFileSelected(filePath: String) {
_viewState.update {
it.copy(privateKey = filePath)
}
Expand Down Expand Up @@ -179,7 +180,7 @@ internal class ServerViewModel @AssistedInject constructor(

private fun initialViewState(): ServerViewState {
return if (isEditMode) {
val serverConfig = Gson().fromJson(serverData, ServerConfig::class.java)
val serverConfig = serverData!!.fromJsonEncoded<ServerConfig>()
ServerViewState(
isEditMode = true,
uuid = serverConfig.uuid,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,10 @@ private fun ShortcutsScreen(
onClick = { onKeyClicked(keybinding) },
)
}
item {
HorizontalDivider()
if (keyGroup != KeyGroup.TOOLS) {
item {
HorizontalDivider()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

@AndroidEntryPoint
internal class NewThemeFragment : Fragment() {
internal class EditThemeFragment : Fragment() {

private val viewModel by hiltNavGraphViewModels<ThemesViewModel>(R.id.themes_graph)

// private val binding by viewBinding(FragmentNewThemeBinding::bind)
// private val binding by viewBinding(FragmentEditThemeBinding::bind)
private val navController by lazy { findNavController() }
private val navArgs by navArgs<NewThemeFragmentArgs>()
private val navArgs by navArgs<EditThemeFragmentArgs>()
private val openFileContract = OpenFileContract(this) { result ->
/*when (result) {
is ContractResult.Success -> viewModel.obtainEvent(ThemeIntent.ImportTheme(result.uri))
Expand All @@ -65,7 +65,7 @@ internal class NewThemeFragment : Fragment() {
viewModel.newThemeState.flowWithLifecycle(viewLifecycleOwner.lifecycle)
.onEach { state ->
when (state) {
is NewThemeViewState.MetaData -> {
is EditThemeViewState.MetaData -> {
/*val name = binding.textInputThemeName.text.toString()
val author = binding.textInputThemeAuthor.text.toString()
val description = binding.textInputThemeDescription.text.toString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import com.blacksquircle.ui.core.mvi.ViewState
import com.blacksquircle.ui.feature.themes.domain.model.Meta
import com.blacksquircle.ui.feature.themes.domain.model.PropertyItem

sealed class NewThemeViewState : ViewState() {
sealed class EditThemeViewState : ViewState() {

data class MetaData(
val meta: Meta,
val properties: List<PropertyItem>,
) : NewThemeViewState()
) : EditThemeViewState()
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.blacksquircle.ui.core.extensions.navigateTo
import com.blacksquircle.ui.core.extensions.showToast
import com.blacksquircle.ui.core.mvi.ViewEvent
import com.blacksquircle.ui.ds.SquircleTheme
import com.blacksquircle.ui.feature.themes.ui.navigation.ThemesViewEvent
import com.blacksquircle.ui.feature.themes.ui.viewmodel.ThemesViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
Expand All @@ -45,10 +46,7 @@ internal class ThemesFragment : Fragment() {
private val navController by lazy { findNavController() }
private val exportThemeContract = CreateFileContract(this) { result ->
when (result) {
is ContractResult.Success -> {
// viewModel.obtainEvent(ThemeIntent.ExportTheme(themeModel, result.uri))
}

is ContractResult.Success -> viewModel.onExportFileSelected(result.uri)
is ContractResult.Canceled -> Unit
}
}
Expand Down Expand Up @@ -80,6 +78,12 @@ internal class ThemesFragment : Fragment() {
is ViewEvent.Toast -> context?.showToast(text = event.message)
is ViewEvent.Navigation -> navController.navigateTo(event.screen)
is ViewEvent.PopBackStack -> navController.popBackStack()
is ThemesViewEvent.ChooseExportFile -> {
exportThemeContract.launch(
event.themeName,
CreateFileContract.JSON
)
}
}
}
.launchIn(viewLifecycleOwner.lifecycleScope)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ internal fun ThemesScreen(viewModel: ThemesViewModel) {
onCodePreviewChanged = viewModel::onCodePreviewChanged,
onQueryChanged = viewModel::onQueryChanged,
onClearQueryClicked = viewModel::onClearQueryClicked,
onCreateClicked = {},
onSelectClicked = {},
onRemoveClicked = {},
onCreateClicked = viewModel::onCreateClicked,
onSelectClicked = viewModel::onSelectClicked,
onExportClicked = viewModel::onExportClicked,
onEditClicked = viewModel::onEditClicked,
onRemoveClicked = viewModel::onRemoveClicked,
)
}

Expand All @@ -96,6 +98,8 @@ private fun ThemesScreen(
onClearQueryClicked: () -> Unit,
onCreateClicked: () -> Unit,
onSelectClicked: (ThemeModel) -> Unit,
onExportClicked: (ThemeModel) -> Unit,
onEditClicked: (ThemeModel) -> Unit,
onRemoveClicked: (ThemeModel) -> Unit,
) {
val scrollState = rememberLazyGridState()
Expand Down Expand Up @@ -209,8 +213,8 @@ private fun ThemesScreen(
fontPath = viewState.fontPath,
codeSample = viewState.preview.codeSample,
onSelectClicked = { onSelectClicked(theme) },
onExportClicked = {},
onEditClicked = {},
onExportClicked = { onExportClicked(theme) },
onEditClicked = { onEditClicked(theme) },
onRemoveClicked = { onRemoveClicked(theme) },
modifier = Modifier.animateItem(),
)
Expand Down Expand Up @@ -244,6 +248,8 @@ private fun ThemesScreenPreview() {
onClearQueryClicked = {},
onCreateClicked = {},
onSelectClicked = {},
onExportClicked = {},
onEditClicked = {},
onRemoveClicked = {},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package com.blacksquircle.ui.feature.themes.ui.navigation

import com.blacksquircle.ui.core.extensions.encodeUrl
import com.blacksquircle.ui.core.extensions.encodeUri
import com.blacksquircle.ui.core.navigation.Screen

internal sealed class ThemesScreen(route: String) : Screen<String>(route) {
Expand All @@ -26,6 +26,6 @@ internal sealed class ThemesScreen(route: String) : Screen<String>(route) {
class Update(uuid: String?) : ThemesScreen("blacksquircle://themes/update?uuid=$uuid")

class ChooseColor(key: String, value: String) : ThemesScreen(
route = "blacksquircle://themes/choosecolor?key=$key&value=${value.encodeUrl()}"
route = "blacksquircle://themes/choosecolor?key=$key&value=${value.encodeUri()}"
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2023 Squircle CE contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.blacksquircle.ui.feature.themes.ui.navigation

import com.blacksquircle.ui.core.mvi.ViewEvent

internal sealed class ThemesViewEvent : ViewEvent() {
data class ChooseExportFile(val themeName: String) : ThemesViewEvent()
}
Loading

0 comments on commit a8fdc28

Please sign in to comment.