mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
chore(ui): move disable resource into resources details (#6463)
To homogenize the UI in mobile and non-mobile, we re-enable the sub-menu for the internet resource, where it shows all resource ## New UI for android   ## New UI for apple  
This commit is contained in:
@@ -23,10 +23,9 @@ import com.google.android.material.button.MaterialButton
|
||||
import dev.firezone.android.R
|
||||
import dev.firezone.android.tunnel.model.StatusEnum
|
||||
|
||||
class ResourceDetailsBottomSheet(private val resource: ViewResource) : BottomSheetDialogFragment() {
|
||||
class ResourceDetailsBottomSheet(private val resource: ViewResource, private val activity: SessionActivity) : BottomSheetDialogFragment() {
|
||||
private lateinit var view: View
|
||||
private val viewModel: SessionViewModel by activityViewModels()
|
||||
private var isFavorite: Boolean = false
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
@@ -43,11 +42,6 @@ class ResourceDetailsBottomSheet(private val resource: ViewResource) : BottomShe
|
||||
this.view = view
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val addToFavoritesBtn: MaterialButton = view.findViewById(R.id.addToFavoritesBtn)
|
||||
val removeFromFavoritesBtn: MaterialButton = view.findViewById(R.id.removeFromFavoritesBtn)
|
||||
val resourceNameTextView: TextView = view.findViewById(R.id.tvResourceName)
|
||||
val resourceAddressTextView: TextView = view.findViewById(R.id.tvResourceAddress)
|
||||
val resourceAddressDescriptionTextView: TextView = view.findViewById(R.id.tvResourceAddressDescription)
|
||||
val siteNameTextView: TextView = view.findViewById(R.id.tvSiteName)
|
||||
val siteStatusTextView: TextView = view.findViewById(R.id.tvSiteStatus)
|
||||
val statusIndicatorDot: ImageView = view.findViewById(R.id.statusIndicatorDot)
|
||||
@@ -55,43 +49,9 @@ class ResourceDetailsBottomSheet(private val resource: ViewResource) : BottomShe
|
||||
val siteNameLayout: LinearLayout = view.findViewById(R.id.siteNameLayout)
|
||||
val siteStatusLayout: LinearLayout = view.findViewById(R.id.siteStatusLayout)
|
||||
|
||||
addToFavoritesBtn.setOnClickListener {
|
||||
viewModel.addFavoriteResource(resource.id)
|
||||
refreshButtons()
|
||||
}
|
||||
removeFromFavoritesBtn.setOnClickListener {
|
||||
viewModel.removeFavoriteResource(resource.id)
|
||||
refreshButtons()
|
||||
}
|
||||
refreshButtons()
|
||||
resourceHeader()
|
||||
|
||||
resourceNameTextView.text = resource.name
|
||||
val displayAddress = resource.addressDescription ?: resource.address
|
||||
resourceAddressTextView.text = displayAddress
|
||||
|
||||
if (!resource.addressDescription.isNullOrEmpty()) {
|
||||
resourceAddressDescriptionTextView.text = resource.addressDescription
|
||||
resourceAddressDescriptionTextView.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
val addressUri = resource.addressDescription?.let { Uri.parse(it) }
|
||||
if (addressUri != null && addressUri.scheme != null) {
|
||||
resourceAddressTextView.setTextColor(Color.BLUE)
|
||||
resourceAddressTextView.setTypeface(null, Typeface.ITALIC)
|
||||
resourceAddressTextView.setOnClickListener {
|
||||
openUrl(resource.addressDescription!!)
|
||||
}
|
||||
} else {
|
||||
resourceAddressTextView.setOnClickListener {
|
||||
copyToClipboard(displayAddress!!)
|
||||
Toast.makeText(requireContext(), "Address copied to clipboard", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
resourceNameTextView.setOnClickListener {
|
||||
copyToClipboard(resource.name)
|
||||
Toast.makeText(requireContext(), "Name copied to clipboard", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
refreshDisableToggleButton()
|
||||
|
||||
if (!resource.sites.isNullOrEmpty()) {
|
||||
val site = resource.sites.first()
|
||||
@@ -129,6 +89,81 @@ class ResourceDetailsBottomSheet(private val resource: ViewResource) : BottomShe
|
||||
}
|
||||
}
|
||||
|
||||
private fun resourceToggleText(): String {
|
||||
if (resource.enabled) {
|
||||
return "Disable this resource"
|
||||
} else {
|
||||
return "Enable this resource"
|
||||
}
|
||||
}
|
||||
|
||||
private fun resourceHeader() {
|
||||
if (resource.isInternetResource()) {
|
||||
internetResourceHeader()
|
||||
} else {
|
||||
nonInternetResourceHeader()
|
||||
}
|
||||
}
|
||||
|
||||
private fun internetResourceHeader() {
|
||||
val addToFavoritesBtn: MaterialButton = view.findViewById(R.id.addToFavoritesBtn)
|
||||
val removeFromFavoritesBtn: MaterialButton = view.findViewById(R.id.removeFromFavoritesBtn)
|
||||
val resourceNameTextView: TextView = view.findViewById(R.id.tvResourceName)
|
||||
val resourceAddress: LinearLayout = view.findViewById(R.id.addressSection)
|
||||
val resourceAddressDescriptionTextView: TextView = view.findViewById(R.id.tvResourceAddressDescription)
|
||||
val resourceDescriptionLayout: LinearLayout = view.findViewById(R.id.resourceDescriptionLayout)
|
||||
|
||||
addToFavoritesBtn.visibility = View.GONE
|
||||
removeFromFavoritesBtn.visibility = View.GONE
|
||||
|
||||
resourceNameTextView.text = resource.name
|
||||
|
||||
resourceAddress.visibility = View.GONE
|
||||
|
||||
resourceDescriptionLayout.visibility = View.VISIBLE
|
||||
resourceAddressDescriptionTextView.text = "All network traffic"
|
||||
}
|
||||
|
||||
private fun nonInternetResourceHeader() {
|
||||
val addToFavoritesBtn: MaterialButton = view.findViewById(R.id.addToFavoritesBtn)
|
||||
val removeFromFavoritesBtn: MaterialButton = view.findViewById(R.id.removeFromFavoritesBtn)
|
||||
val resourceNameTextView: TextView = view.findViewById(R.id.tvResourceName)
|
||||
val resourceAddressTextView: TextView = view.findViewById(R.id.tvResourceAddress)
|
||||
|
||||
addToFavoritesBtn.setOnClickListener {
|
||||
viewModel.addFavoriteResource(resource.id)
|
||||
refreshButtons()
|
||||
}
|
||||
removeFromFavoritesBtn.setOnClickListener {
|
||||
viewModel.removeFavoriteResource(resource.id)
|
||||
refreshButtons()
|
||||
}
|
||||
refreshButtons()
|
||||
|
||||
resourceNameTextView.text = resource.name
|
||||
val displayAddress = resource.addressDescription ?: resource.address
|
||||
resourceAddressTextView.text = displayAddress
|
||||
|
||||
val addressUri = resource.addressDescription?.let { Uri.parse(it) }
|
||||
if (addressUri != null && addressUri.scheme != null) {
|
||||
resourceAddressTextView.setTextColor(Color.BLUE)
|
||||
resourceAddressTextView.setTypeface(null, Typeface.ITALIC)
|
||||
resourceAddressTextView.setOnClickListener {
|
||||
openUrl(resource.addressDescription!!)
|
||||
}
|
||||
} else {
|
||||
resourceAddressTextView.setOnClickListener {
|
||||
copyToClipboard(displayAddress!!)
|
||||
Toast.makeText(requireContext(), "Address copied to clipboard", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
resourceNameTextView.setOnClickListener {
|
||||
copyToClipboard(resource.name)
|
||||
Toast.makeText(requireContext(), "Name copied to clipboard", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshButtons() {
|
||||
val addToFavoritesBtn: MaterialButton = view.findViewById(R.id.addToFavoritesBtn)
|
||||
val removeFromFavoritesBtn: MaterialButton = view.findViewById(R.id.removeFromFavoritesBtn)
|
||||
@@ -137,6 +172,21 @@ class ResourceDetailsBottomSheet(private val resource: ViewResource) : BottomShe
|
||||
removeFromFavoritesBtn.visibility = if (isFavorite) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun refreshDisableToggleButton() {
|
||||
if (resource.canBeDisabled) {
|
||||
val toggleResourceEnabled: MaterialButton = view.findViewById(R.id.toggleResourceEnabled)
|
||||
toggleResourceEnabled.visibility = View.VISIBLE
|
||||
toggleResourceEnabled.text = resourceToggleText()
|
||||
toggleResourceEnabled.setOnClickListener {
|
||||
resource.enabled = !resource.enabled
|
||||
|
||||
activity.onViewResourceToggled(resource)
|
||||
|
||||
refreshDisableToggleButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyToClipboard(text: String) {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("Copied Text", text)
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -14,8 +13,6 @@ import dev.firezone.android.databinding.ListItemResourceBinding
|
||||
internal class ResourcesAdapter(private val activity: SessionActivity) : ListAdapter<ViewResource, ResourcesAdapter.ViewHolder>(
|
||||
ResourceDiffCallback(),
|
||||
) {
|
||||
private var favoriteResources: HashSet<String> = HashSet()
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int,
|
||||
@@ -29,45 +26,24 @@ internal class ResourcesAdapter(private val activity: SessionActivity) : ListAda
|
||||
position: Int,
|
||||
) {
|
||||
val resource = getItem(position)
|
||||
holder.bind(resource) { newResource -> onSwitchToggled(newResource) }
|
||||
if (!resource.isInternetResource()) {
|
||||
holder.itemView.setOnClickListener {
|
||||
// Show bottom sheet
|
||||
val isFavorite = favoriteResources.contains(resource.id)
|
||||
val fragmentManager =
|
||||
(holder.itemView.context as AppCompatActivity).supportFragmentManager
|
||||
val bottomSheet = ResourceDetailsBottomSheet(resource)
|
||||
bottomSheet.show(fragmentManager, "ResourceDetailsBottomSheet")
|
||||
}
|
||||
holder.bind(resource)
|
||||
holder.itemView.setOnClickListener {
|
||||
// Show bottom sheet
|
||||
val fragmentManager =
|
||||
(holder.itemView.context as AppCompatActivity).supportFragmentManager
|
||||
val bottomSheet = ResourceDetailsBottomSheet(resource, activity)
|
||||
bottomSheet.show(fragmentManager, "ResourceDetailsBottomSheet")
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSwitchToggled(resource: ViewResource) {
|
||||
activity.onViewResourceToggled(resource)
|
||||
}
|
||||
|
||||
class ViewHolder(private val binding: ListItemResourceBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(
|
||||
resource: ViewResource,
|
||||
onSwitchToggled: (ViewResource) -> Unit,
|
||||
) {
|
||||
fun bind(resource: ViewResource) {
|
||||
binding.resourceNameText.text = resource.name
|
||||
if (resource.isInternetResource()) {
|
||||
binding.addressText.visibility = View.GONE
|
||||
} else {
|
||||
binding.addressText.text = resource.address
|
||||
}
|
||||
// Without this the item gets reset when out of view, isn't android wonderful?
|
||||
binding.enableSwitch.setOnCheckedChangeListener(null)
|
||||
binding.enableSwitch.isChecked = resource.enabled
|
||||
binding.enableSwitch.isVisible = resource.canBeDisabled
|
||||
|
||||
binding.enableSwitch.setOnCheckedChangeListener {
|
||||
_, isChecked ->
|
||||
resource.enabled = isChecked
|
||||
|
||||
onSwitchToggled(resource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import dev.firezone.android.features.settings.ui.SettingsActivity
|
||||
import dev.firezone.android.tunnel.TunnelService
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class SessionActivity : AppCompatActivity() {
|
||||
class SessionActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivitySessionBinding
|
||||
private var tunnelService: TunnelService? = null
|
||||
private var serviceBound = false
|
||||
|
||||
@@ -14,7 +14,7 @@ data class ViewResource(
|
||||
val sites: List<Site>?,
|
||||
val name: String,
|
||||
val status: StatusEnum,
|
||||
var enabled: Boolean = true,
|
||||
var enabled: Boolean,
|
||||
var canBeDisabled: Boolean = true,
|
||||
)
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ data class Resource(
|
||||
val sites: List<Site>?,
|
||||
val name: String,
|
||||
val status: StatusEnum,
|
||||
var enabled: Boolean = true,
|
||||
@Json(name = "can_be_disabled") val canBeDisabled: Boolean,
|
||||
) : Parcelable
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/addressSection"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
@@ -68,6 +69,13 @@
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/toggleResourceEnabled"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/addToFavoritesBtn"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
|
||||
@@ -28,14 +28,4 @@
|
||||
app:layout_constraintTop_toBottomOf="@id/resourceNameText"
|
||||
tools:text="Resource Address" />
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/enable_switch"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:checked="true"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/resourceNameText"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -91,7 +91,8 @@ pub struct ResourceDescriptionInternet {
|
||||
#[serde(rename = "gateway_groups")]
|
||||
pub sites: Vec<Site>,
|
||||
/// Whether or not resource can be disabled from UI
|
||||
pub can_be_disabled: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub can_be_disabled: bool,
|
||||
}
|
||||
|
||||
impl ResourceDescriptionInternet {
|
||||
@@ -100,7 +101,7 @@ impl ResourceDescriptionInternet {
|
||||
name: self.name,
|
||||
id: self.id,
|
||||
sites: self.sites,
|
||||
can_be_disabled: self.can_be_disabled.unwrap_or_default(),
|
||||
can_be_disabled: self.can_be_disabled,
|
||||
status,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ pub fn internet_resource(
|
||||
name: "Internet Resource".to_string(),
|
||||
id,
|
||||
sites,
|
||||
can_be_disabled: Some(can_be_disabled),
|
||||
can_be_disabled,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
import SwiftUI
|
||||
|
||||
#if os(iOS)
|
||||
private func copyToClipboard(_ value: String) {
|
||||
let pasteboard = UIPasteboard.general
|
||||
pasteboard.string = value
|
||||
}
|
||||
|
||||
struct ResourceView: View {
|
||||
@ObservedObject var model: SessionViewModel
|
||||
var resource: Resource
|
||||
@@ -15,82 +20,10 @@ struct ResourceView: View {
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section(header: Text("Resource")) {
|
||||
HStack {
|
||||
Text("NAME")
|
||||
.bold()
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.secondary)
|
||||
.frame(width: 80, alignment: .leading)
|
||||
Text(resource.name)
|
||||
}
|
||||
.contextMenu {
|
||||
Button(action: {
|
||||
copyToClipboard(resource.name)
|
||||
}) {
|
||||
Text("Copy name")
|
||||
Image(systemName: "doc.on.doc")
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("ADDRESS")
|
||||
.bold()
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.secondary)
|
||||
.frame(width: 80, alignment: .leading)
|
||||
if let url = URL(string: resource.addressDescription ?? resource.address!),
|
||||
let _ = url.host {
|
||||
Button(action: {
|
||||
openURL(url)
|
||||
}) {
|
||||
Text(resource.addressDescription ?? resource.address!)
|
||||
.foregroundColor(.blue)
|
||||
.underline()
|
||||
.font(.system(size: 16))
|
||||
.contextMenu {
|
||||
Button(action: {
|
||||
copyToClipboard(resource.addressDescription ?? resource.address!)
|
||||
}) {
|
||||
Text("Copy address")
|
||||
Image(systemName: "doc.on.doc")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text(resource.addressDescription ?? resource.address!)
|
||||
.contextMenu {
|
||||
Button(action: {
|
||||
copyToClipboard(resource.addressDescription ?? resource.address!)
|
||||
}) {
|
||||
Text("Copy address")
|
||||
Image(systemName: "doc.on.doc")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(model.favorites.ids.contains(resource.id)) {
|
||||
Button(action: {
|
||||
model.favorites.remove(resource.id)
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "star")
|
||||
Text("Remove from favorites")
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Button(action: {
|
||||
model.favorites.add(resource.id)
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "star.fill")
|
||||
Text("Add to favorites")
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
if resource.isInternetResource() {
|
||||
InternetResourceHeader(model: model, resource: resource)
|
||||
} else {
|
||||
NonInternetResourceHeader(model: model, resource: resource)
|
||||
}
|
||||
|
||||
if let site = resource.sites.first {
|
||||
@@ -156,10 +89,150 @@ struct ResourceView: View {
|
||||
return .gray
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func copyToClipboard(_ value: String) {
|
||||
let pasteboard = UIPasteboard.general
|
||||
pasteboard.string = value
|
||||
struct NonInternetResourceHeader: View {
|
||||
@ObservedObject var model: SessionViewModel
|
||||
var resource: Resource
|
||||
@Environment(\.openURL) var openURL
|
||||
|
||||
var body: some View {
|
||||
Section(header: Text("Resource")) {
|
||||
HStack {
|
||||
Text("NAME")
|
||||
.bold()
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.secondary)
|
||||
.frame(width: 80, alignment: .leading)
|
||||
Text(resource.name)
|
||||
}
|
||||
.contextMenu {
|
||||
Button(action: {
|
||||
copyToClipboard(resource.name)
|
||||
}) {
|
||||
Text("Copy name")
|
||||
Image(systemName: "doc.on.doc")
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("ADDRESS")
|
||||
.bold()
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.secondary)
|
||||
.frame(width: 80, alignment: .leading)
|
||||
if let url = URL(string: resource.addressDescription ?? resource.address!),
|
||||
let _ = url.host {
|
||||
Button(action: {
|
||||
openURL(url)
|
||||
}) {
|
||||
Text(resource.addressDescription ?? resource.address!)
|
||||
.foregroundColor(.blue)
|
||||
.underline()
|
||||
.font(.system(size: 16))
|
||||
.contextMenu {
|
||||
Button(action: {
|
||||
copyToClipboard(resource.addressDescription ?? resource.address!)
|
||||
}) {
|
||||
Text("Copy address")
|
||||
Image(systemName: "doc.on.doc")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text(resource.addressDescription ?? resource.address!)
|
||||
.contextMenu {
|
||||
Button(action: {
|
||||
copyToClipboard(resource.addressDescription ?? resource.address!)
|
||||
}) {
|
||||
Text("Copy address")
|
||||
Image(systemName: "doc.on.doc")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(model.favorites.ids.contains(resource.id)) {
|
||||
Button(action: {
|
||||
model.favorites.remove(resource.id)
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "star")
|
||||
Text("Remove from favorites")
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Button(action: {
|
||||
model.favorites.add(resource.id)
|
||||
}) {
|
||||
HStack {
|
||||
Image(systemName: "star.fill")
|
||||
Text("Add to favorites")
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ToggleResourceEnabledButton(resource: resource, model: model)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct InternetResourceHeader: View {
|
||||
@ObservedObject var model: SessionViewModel
|
||||
var resource: Resource
|
||||
|
||||
var body: some View {
|
||||
Section(header: Text("Resource")) {
|
||||
HStack {
|
||||
Text("NAME")
|
||||
.bold()
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.secondary)
|
||||
.frame(width: 80, alignment: .leading)
|
||||
Text(resource.name)
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("DESCRIPTION")
|
||||
.bold()
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.secondary)
|
||||
.frame(alignment: .leading)
|
||||
|
||||
Text("All network traffic")
|
||||
}
|
||||
ToggleResourceEnabledButton(resource: resource, model: model)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ToggleResourceEnabledButton: View {
|
||||
var resource: Resource
|
||||
@ObservedObject var model: SessionViewModel
|
||||
|
||||
private func toggleResourceEnabledText() -> String {
|
||||
if model.isResourceEnabled(resource.id) {
|
||||
"Disable this resource"
|
||||
} else {
|
||||
"Enable this resource"
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if resource.canBeDisabled {
|
||||
Button(action: {
|
||||
model.store.toggleResourceDisabled(resource: resource.id, enabled: !model.isResourceEnabled(resource.id))
|
||||
}) {
|
||||
HStack {
|
||||
Text(toggleResourceEnabledText())
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -130,37 +130,13 @@ struct ResourceSection: View {
|
||||
var body: some View {
|
||||
ForEach(resources) { resource in
|
||||
HStack {
|
||||
if !resource.isInternetResource() {
|
||||
NavigationLink { ResourceView(model: model, resource: resource) }
|
||||
NavigationLink { ResourceView(model: model, resource: resource) }
|
||||
label: {
|
||||
ResourceLabel(resource: resource, model: model )
|
||||
Text(resource.name)
|
||||
}
|
||||
} else {
|
||||
ResourceLabel(resource: resource, model: model)
|
||||
}
|
||||
}
|
||||
.navigationTitle("All Resources")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ResourceLabel: View {
|
||||
let resource: Resource
|
||||
@ObservedObject var model: SessionViewModel
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Text(resource.name)
|
||||
if resource.canBeDisabled {
|
||||
Spacer()
|
||||
Toggle("Enabled", isOn: Binding<Bool>(
|
||||
get: { model.isResourceEnabled(resource.id) },
|
||||
set: { newValue in
|
||||
model.store.toggleResourceDisabled(resource: resource.id, enabled: newValue)
|
||||
}
|
||||
)).labelsHidden()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user