Skip to content
Merged
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
68 changes: 38 additions & 30 deletions app/src/main/res/layout/fragment_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,69 +11,77 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
android:padding="16dp">

<TextView
android:id="@+id/input_organisation_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="Organisation" />
android:layout_marginStart="4dp"
android:layout_marginBottom="4dp"
android:text="Organisation"
android:textStyle="bold" />

<EditText
android:id="@+id/input_organisation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_marginBottom="16dp"
android:hint="@string/enter_your_text_here"
android:text="indoorvivants"
android:inputType="text" />
android:inputType="text"
android:importantForAutofill="no" />

<TextView
android:id="@+id/input_repository_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="Repository" />
android:layout_marginStart="4dp"
android:layout_marginBottom="4dp"
android:text="Repository"
android:textStyle="bold" />

<EditText
android:id="@+id/input_repository"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_marginBottom="16dp"
android:hint="@string/enter_your_text_here"
android:text="sn-bindgen"
android:inputType="text" />
android:inputType="text"
android:importantForAutofill="no" />

<Button
android:id="@+id/submit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_marginBottom="16dp"
android:text="@string/lookup_on_scaladex" />

<!-- Styled TextView for Query Results -->
<TextView
android:id="@+id/query_result_text_view"
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F0F0F0"
android:padding="16dp"
android:text="Query Result Will Appear Here"
android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold" />
android:layout_height="wrap_content">

<ProgressBar
android:id="@+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />

<!-- <TextView-->
<!-- android:id="@+id/message_text_view"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:textSize="24sp"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintEnd_toEndOf="parent"-->
<!-- app:layout_constraintStart_toStartOf="parent"-->
<!-- app:layout_constraintTop_toTopOf="parent" />-->
<TextView
android:id="@+id/query_result_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F0F0F0"
android:padding="16dp"
android:text="Enter organization and repository to search"
android:textColor="@android:color/black"
android:textSize="16sp"
android:minHeight="150dp" />
</FrameLayout>

</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,27 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import com.example.core.Foo
import com.example.scala_3_android_java.R
import scala.util.{Left, Right}
import java.util.concurrent.Executors
import androidx.lifecycle.Observer
import scala.compiletime.uninitialized

object MainFragment:
def newInstance = MainFragment()

class MainFragment extends Fragment:
private var mViewModel: MainViewModel = _
// private var messageTextView: TextView = _
private var inputOrgText: EditText = _
private var inputRepoText: EditText = _
private var submitButton: Button = _
private var queryResultTextView: TextView = _
private val executor = Executors.newSingleThreadExecutor()
private var viewModel: MainViewModel = uninitialized
private var inputOrgText: EditText = uninitialized
private var inputRepoText: EditText = uninitialized
private var submitButton: Button = uninitialized
private var queryResultTextView: TextView = uninitialized
private var progressBar: ProgressBar = uninitialized

override def onCreate(savedInstanceState: Bundle): Unit =
super.onCreate(savedInstanceState)
mViewModel = ViewModelProvider(this).get(classOf[MainViewModel])
// TODO: Use the ViewModel
viewModel = ViewModelProvider(this).get(classOf[MainViewModel])

override def onCreateView(inflater: LayoutInflater,
container: ViewGroup,
Expand All @@ -39,41 +37,58 @@ class MainFragment extends Fragment:

override def onViewCreated(view: View, savedInstanceState: Bundle): Unit =
super.onViewCreated(view, savedInstanceState)

// Find view references
// messageTextView = view.findViewById(R.id.message_text_view)
inputOrgText = view.findViewById(R.id.input_organisation)
inputRepoText = view.findViewById(R.id.input_repository)
submitButton = view.findViewById(R.id.submit_button)
queryResultTextView = view.findViewById(R.id.query_result_text_view)
progressBar = view.findViewById(R.id.progress_bar)

// // Observe the LiveData from ViewModel
// mViewModel.getMessage.observe(getViewLifecycleOwner, (message: String) =>
// viewModel.getMessage.observe(getViewLifecycleOwner, (message: String) =>
// // Update the UI when data changes
// messageTextView.setText("\n" + message)
// )

// Observe the ProjectInfoState LiveData
viewModel.getProjectInfoState.observe(getViewLifecycleOwner, {
case Initial =>
progressBar.setVisibility(View.GONE)
queryResultTextView.setText("Enter organization and repository to search")

case Loading =>
progressBar.setVisibility(View.VISIBLE)
queryResultTextView.setText("Loading...")

case Error(message) =>
progressBar.setVisibility(View.GONE)
queryResultTextView.setText("")
Toast.makeText(getContext, s"An error occurred: $message", Toast.LENGTH_LONG).show()

case Success(projectInfo) =>
progressBar.setVisibility(View.GONE)
queryResultTextView.setText(
s"""
|Project: ${inputOrgText.getText}/${inputRepoText.getText}
|Description: ${projectInfo.description}
|Stars: ${projectInfo.stars}
|${if projectInfo.topic.isEmpty then "" else s"Topics: ${projectInfo.topic.mkString(", ")}"}
""".stripMargin)
})

// Set up the button click listener
submitButton.setOnClickListener(new View.OnClickListener() {
override def onClick(v: View): Unit =
// Get the input from the EditText
val org = inputOrgText.getText.toString
val repo = inputRepoText.getText.toString
// Execute side effect on a background thread
executor.execute(() =>
val result = Foo.getProjectInfo(org, repo)
// Update UI on the main thread
getActivity.runOnUiThread(() =>
result match
case Left(error) =>
queryResultTextView.setText("")
// Optionally, you can show a Toast with the error
Toast.makeText(getContext, s"An error occurred: $error", Toast.LENGTH_LONG).show()
case Right(projectInfo) =>
queryResultTextView.setText(s"${projectInfo.description}, stars: ${projectInfo.stars}")
)
)
// Here you can send your user input to the ViewModel to update the data
// mViewModel.processInput(userInput)
})
val org = inputOrgText.getText.toString.trim
val repo = inputRepoText.getText.toString.trim

override def onDestroyView(): Unit =
super.onDestroyView()
executor.shutdown()
// Validate input
if org.isEmpty || repo.isEmpty then
Toast.makeText(getContext, "Please enter both organization and repository", Toast.LENGTH_SHORT).show()
else
// Use the ViewModel to fetch project info
viewModel.fetchProjectInfo(org, repo)
})
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,44 @@ package com.example.scala_3_android_java.ui.main
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.core.{Description, Foo}
import java.util.concurrent.Executors

// Sealed trait for UI state
sealed trait ProjectInfoState
case object Loading extends ProjectInfoState
case class Error(message: String) extends ProjectInfoState
case class Success(projectInfo: Description) extends ProjectInfoState
case object Initial extends ProjectInfoState

class MainViewModel extends ViewModel:
private val message = new MutableLiveData[String]
// Initialize with Hello World message
private val projectInfoState = new MutableLiveData[ProjectInfoState]
private val executor = Executors.newSingleThreadExecutor()

// Initialize with Hello World message and Initial state
message.setValue("Hello, Scala 3 Android!")
projectInfoState.setValue(Initial)

// Getter for the LiveData
// Getters for the LiveData
def getMessage: LiveData[String] = message
def getProjectInfoState: LiveData[ProjectInfoState] = projectInfoState

// Method to update the message
def setMessage(newMessage: String): Unit =
message.setValue(newMessage)

// Method to fetch project information
def fetchProjectInfo(org: String, repo: String): Unit =
projectInfoState.setValue(Loading)
executor.execute(() =>
val state =
Foo.getProjectInfo(org, repo) match
case Left(error) => Error(error)
case Right(projectInfo) => Success(projectInfo)
projectInfoState.postValue(state)
)

override def onCleared(): Unit =
super.onCleared()
executor.shutdown()