Improve profile item

This commit is contained in:
世界
2024-01-14 16:13:52 +08:00
parent 923a3789d0
commit cac0714587
13 changed files with 199 additions and 86 deletions

View File

@@ -8,6 +8,7 @@ import android.view.ViewGroup
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
@@ -15,13 +16,14 @@ import androidx.recyclerview.widget.RecyclerView
import io.nekohasekai.sfa.R
import io.nekohasekai.sfa.database.Profile
import io.nekohasekai.sfa.database.ProfileManager
import io.nekohasekai.sfa.database.TypedProfile
import io.nekohasekai.sfa.databinding.FragmentConfigurationBinding
import io.nekohasekai.sfa.databinding.ViewConfigutationItemBinding
import io.nekohasekai.sfa.ktx.errorDialogBuilder
import io.nekohasekai.sfa.ktx.shareProfile
import io.nekohasekai.sfa.ktx.shareProfileURL
import io.nekohasekai.sfa.ui.profile.EditProfileActivity
import io.nekohasekai.sfa.ui.profile.NewProfileActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@@ -36,7 +38,7 @@ class ConfigurationFragment : Fragment() {
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
val binding = FragmentConfigurationBinding.inflate(inflater, container, false)
val adapter = Adapter(lifecycleScope, binding)
val adapter = Adapter(binding)
this.adapter = adapter
binding.profileList.also {
it.layoutManager = LinearLayoutManager(requireContext())
@@ -89,16 +91,17 @@ class ConfigurationFragment : Fragment() {
adapter?.reload()
}
class Adapter(
internal val scope: CoroutineScope,
internal val parent: FragmentConfigurationBinding
inner class Adapter(
private val parent: FragmentConfigurationBinding
) :
RecyclerView.Adapter<Holder>() {
internal var items: MutableList<Profile> = mutableListOf()
internal val scope = lifecycleScope
internal val fragmentActivity = requireActivity() as FragmentActivity
internal fun reload() {
scope.launch(Dispatchers.IO) {
lifecycleScope.launch(Dispatchers.IO) {
val newItems = ProfileManager.list().toMutableList()
withContext(Dispatchers.Main) {
items = newItems
@@ -163,6 +166,15 @@ class ConfigurationFragment : Fragment() {
internal fun bind(profile: Profile) {
binding.profileName.text = profile.name
if (profile.typed.type == TypedProfile.Type.Remote) {
binding.profileLastUpdated.isVisible = true
binding.profileLastUpdated.text = binding.root.context.getString(
R.string.profile_item_last_updated,
profile.typed.lastUpdated.toLocaleString()
)
} else {
binding.profileLastUpdated.isVisible = false
}
binding.root.setOnClickListener {
val intent = Intent(binding.root.context, EditProfileActivity::class.java)
intent.putExtra("profile_id", profile.id)
@@ -172,6 +184,9 @@ class ConfigurationFragment : Fragment() {
val popup = PopupMenu(button.context, button)
popup.setForceShowIcon(true)
popup.menuInflater.inflate(R.menu.profile_menu, popup.menu)
if (profile.typed.type != TypedProfile.Type.Remote) {
popup.menu.removeItem(R.id.action_share_url)
}
popup.setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_share -> {
@@ -187,6 +202,19 @@ class ConfigurationFragment : Fragment() {
true
}
R.id.action_share_url -> {
adapter.scope.launch(Dispatchers.IO) {
try {
adapter.fragmentActivity.shareProfileURL(profile)
} catch (e: Exception) {
withContext(Dispatchers.Main) {
button.context.errorDialogBuilder(e).show()
}
}
}
true
}
R.id.action_delete -> {
adapter.items.remove(profile)
adapter.notifyItemRemoved(adapterPosition)

View File

@@ -95,13 +95,11 @@ class EditProfileActivity : AbstractActivity() {
TypedProfile.Type.Local -> {
binding.editButton.isVisible = true
binding.remoteFields.isVisible = false
binding.shareURLButton.isVisible = false
}
TypedProfile.Type.Remote -> {
binding.editButton.isVisible = false
binding.remoteFields.isVisible = true
binding.shareURLButton.isVisible = true
binding.remoteURL.text = profile.typed.remoteURL
binding.lastUpdated.text =
DateFormat.getDateTimeInstance().format(profile.typed.lastUpdated)
@@ -115,9 +113,6 @@ class EditProfileActivity : AbstractActivity() {
binding.autoUpdate.addTextChangedListener(this@EditProfileActivity::updateAutoUpdate)
binding.autoUpdateInterval.addTextChangedListener(this@EditProfileActivity::updateAutoUpdateInterval)
binding.updateButton.setOnClickListener(this@EditProfileActivity::updateProfile)
binding.checkButton.setOnClickListener(this@EditProfileActivity::checkProfile)
binding.shareButton.setOnClickListener(this@EditProfileActivity::shareProfile)
binding.shareURLButton.setOnClickListener(this@EditProfileActivity::shareProfileURL)
binding.profileLayout.isVisible = true
binding.progressView.isVisible = false
}
@@ -208,24 +203,6 @@ class EditProfileActivity : AbstractActivity() {
}
}
private fun checkProfile(button: View) {
val binding = binding ?: return
binding.progressView.isVisible = true
lifecycleScope.launch(Dispatchers.IO) {
delay(200L)
try {
Libbox.checkConfig(File(profile.typed.path).readText())
} catch (e: Exception) {
withContext(Dispatchers.Main) {
errorDialogBuilder(e).show()
}
}
withContext(Dispatchers.Main) {
binding.progressView.isVisible = false
}
}
}
private fun shareProfile(button: View) {
lifecycleScope.launch(Dispatchers.IO) {
try {
@@ -238,25 +215,4 @@ class EditProfileActivity : AbstractActivity() {
}
}
private fun shareProfileURL(button: View) {
try {
startActivity(
Intent.createChooser(
Intent(Intent.ACTION_SEND).setType("application/octet-stream")
.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.putExtra(
Intent.EXTRA_STREAM,
Libbox.generateRemoteProfileImportLink(
profile.name,
profile.typed.remoteURL
)
),
getString(com.google.android.material.R.string.abc_shareactionprovider_share_with)
)
)
} catch (e: Exception) {
errorDialogBuilder(e).show()
}
}
}

View File

@@ -0,0 +1,26 @@
package io.nekohasekai.sfa.ui.shared
import android.graphics.Bitmap
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import io.nekohasekai.sfa.databinding.FragmentQrcodeDialogBinding
class QRCodeDialog(private val bitmap: Bitmap) :
BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding = FragmentQrcodeDialogBinding.inflate(inflater, container, false)
val behavior = BottomSheetBehavior.from(binding.qrcodeLayout)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
binding.qrCode.setImageBitmap(bitmap)
return binding.root
}
}