diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..fb7f4a8
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..526b4c2
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..fa0d9d1
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 93d31ce..0eebe9d 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,11 +1,16 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
+ id 'androidx.navigation.safeargs.kotlin'
}
android {
compileSdk 31
+ viewBinding {
+ enabled = true
+ }
+
defaultConfig {
applicationId "com.github.krottv.tmstemp"
minSdk 24
@@ -32,6 +37,17 @@ android {
}
dependencies {
+ implementation "androidx.navigation:navigation-fragment-ktx:2.4.2"
+ implementation "androidx.navigation:navigation-ui-ktx:2.4.2"
+ implementation "androidx.fragment:fragment-ktx:1.4.1"
+ implementation "androidx.activity:activity-ktx:1.4.0"
+
+ implementation("io.coil-kt:coil:2.0.0-rc03")
+
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a551aff..e24bb3d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,8 @@
+
+
diff --git a/app/src/main/java/com/github/krottv/tmstemp/MainActivity.kt b/app/src/main/java/com/github/krottv/tmstemp/MainActivity.kt
deleted file mode 100644
index 8952f64..0000000
--- a/app/src/main/java/com/github/krottv/tmstemp/MainActivity.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.github.krottv.tmstemp
-
-import androidx.appcompat.app.AppCompatActivity
-import android.os.Bundle
-
-class MainActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/binder/MainActivityDataBinder.kt b/app/src/main/java/com/github/krottv/tmstemp/binder/MainActivityDataBinder.kt
new file mode 100644
index 0000000..8b81aeb
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/binder/MainActivityDataBinder.kt
@@ -0,0 +1,5 @@
+package com.github.krottv.tmstemp.binder
+
+interface MainActivityDataBinder {
+ fun bind()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/binder/MainActivityRecyclerScrollDataBinder.kt b/app/src/main/java/com/github/krottv/tmstemp/binder/MainActivityRecyclerScrollDataBinder.kt
new file mode 100644
index 0000000..8b9d9da
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/binder/MainActivityRecyclerScrollDataBinder.kt
@@ -0,0 +1,15 @@
+package com.github.krottv.tmstemp.binder
+
+import android.app.Activity
+import android.view.LayoutInflater
+import com.github.krottv.tmstemp.databinding.ActivityMainBinding
+
+
+class MainActivityRecyclerScrollDataBinder(private val activity: Activity): MainActivityDataBinder {
+
+ override fun bind() {
+ val container = ActivityMainBinding.inflate(LayoutInflater.from(activity))
+ activity.setContentView(container.root)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/binder/RecyclerFragmentBinder.kt b/app/src/main/java/com/github/krottv/tmstemp/binder/RecyclerFragmentBinder.kt
new file mode 100644
index 0000000..ecabf04
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/binder/RecyclerFragmentBinder.kt
@@ -0,0 +1,67 @@
+package com.github.krottv.tmstemp.binder
+
+import android.os.Bundle
+import android.transition.*
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.github.krottv.tmstemp.R
+import com.github.krottv.tmstemp.databinding.SceneContainerBinding
+import com.github.krottv.tmstemp.domain.MessageModel
+import com.github.krottv.tmstemp.view.MessageAdapter
+
+class RecyclerFragmentBinder(private val fragment: Fragment, private val onItemClick: (View, MessageModel) -> Unit) {
+
+ private lateinit var binding: SceneContainerBinding
+
+ fun bindView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = SceneContainerBinding.inflate(inflater, container, false)
+
+ return binding.root
+ }
+
+
+ private val customTransition = TransitionSet().apply {
+ addTransition(ChangeBounds())
+ addTransition(Fade(Fade.IN))
+ }
+
+ fun onDataLoaded(data: List) {
+
+ val scene = Scene.getSceneForLayout(binding.sceneRoot, R.layout.messages_fragment, fragment.requireContext())
+ TransitionManager.go(scene, customTransition)
+
+ val recyclerView = scene.sceneRoot.findViewById(R.id.container)
+ recyclerView.layoutManager = LinearLayoutManager(fragment.requireContext())
+
+ if (recyclerView.adapter == null) {
+ recyclerView.adapter = MessageAdapter(data, onItemClick)
+ } else {
+ (recyclerView.adapter as MessageAdapter).data = data
+ }
+ }
+
+ fun showError(exception: Throwable) {
+
+ val scene = Scene.getSceneForLayout(binding.sceneRoot, R.layout.show_error, fragment.requireContext())
+ TransitionManager.go(scene, customTransition)
+
+ scene.sceneRoot.findViewById(R.id.errorText).apply {
+ text = exception.message
+ }
+ }
+
+ fun showProgress() {
+
+ val scene = Scene.getSceneForLayout(binding.sceneRoot, R.layout.loading, fragment.requireContext())
+ TransitionManager.go(scene, customTransition)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/data/MessagesRemoteDataSource.kt b/app/src/main/java/com/github/krottv/tmstemp/data/MessagesRemoteDataSource.kt
new file mode 100644
index 0000000..5d674f6
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/data/MessagesRemoteDataSource.kt
@@ -0,0 +1,7 @@
+package com.github.krottv.tmstemp.data
+
+import com.github.krottv.tmstemp.domain.MessageModel
+
+interface MessagesRemoteDataSource {
+ suspend fun getMessages(): List
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/data/MessagesRemoteDataSourceError.kt b/app/src/main/java/com/github/krottv/tmstemp/data/MessagesRemoteDataSourceError.kt
new file mode 100644
index 0000000..206edf1
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/data/MessagesRemoteDataSourceError.kt
@@ -0,0 +1,12 @@
+package com.github.krottv.tmstemp.data
+
+import com.github.krottv.tmstemp.domain.MessageModel
+import kotlinx.coroutines.delay
+import java.lang.IllegalStateException
+
+class MessagesRemoteDataSourceError: MessagesRemoteDataSource {
+ override suspend fun getMessages(): List {
+ delay(2000)
+ throw IllegalStateException("IllegalStateException")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/data/MessagesRemoteDataSourceFake.kt b/app/src/main/java/com/github/krottv/tmstemp/data/MessagesRemoteDataSourceFake.kt
new file mode 100644
index 0000000..47966d7
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/data/MessagesRemoteDataSourceFake.kt
@@ -0,0 +1,20 @@
+package com.github.krottv.tmstemp.data
+
+import com.github.krottv.tmstemp.domain.MessageModel
+import kotlinx.coroutines.delay
+
+class MessagesRemoteDataSourceFake: MessagesRemoteDataSource {
+ override suspend fun getMessages(): List {
+ delay(2000)
+ val message = MessageModel(
+ "https://images.unsplash.com/photo-1505062351414-586330b076f2?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1080&q=80",
+ "Пункт такойто",
+ "Какой-то текст Какой-то текст Какой-то текст Какой-то текст"
+ )
+ val result = ArrayList(20)
+ for (i in 0..20) {
+ result.add(message.copy(mainText = "Пункт $i"))
+ }
+ return result
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/domain/MessageModel.kt b/app/src/main/java/com/github/krottv/tmstemp/domain/MessageModel.kt
new file mode 100644
index 0000000..5bd1276
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/domain/MessageModel.kt
@@ -0,0 +1,36 @@
+package com.github.krottv.tmstemp.domain
+
+import android.os.Parcel
+import android.os.Parcelable
+import androidx.annotation.Keep
+
+@Keep
+data class MessageModel(val mainImage: String, val mainText: String, val littleText: String): Parcelable {
+ constructor(parcel: Parcel) : this(
+ parcel.readString()!!,
+ parcel.readString()!!,
+ parcel.readString()!!
+ )
+
+ fun transitionId() = mainText + "_"
+
+ override fun writeToParcel(parcel: Parcel, flags: Int) {
+ parcel.writeString(mainImage)
+ parcel.writeString(mainText)
+ parcel.writeString(littleText)
+ }
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ companion object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): MessageModel {
+ return MessageModel(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/presentation/MessageViewModel.kt b/app/src/main/java/com/github/krottv/tmstemp/presentation/MessageViewModel.kt
new file mode 100644
index 0000000..2d18502
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/presentation/MessageViewModel.kt
@@ -0,0 +1,31 @@
+package com.github.krottv.tmstemp.presentation
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.github.krottv.tmstemp.data.MessagesRemoteDataSource
+import com.github.krottv.tmstemp.data.MessagesRemoteDataSourceError
+import com.github.krottv.tmstemp.data.MessagesRemoteDataSourceFake
+import com.github.krottv.tmstemp.domain.MessageModel
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
+
+class MessageViewModel: ViewModel() {
+ private val fakeMessages: MessagesRemoteDataSource = MessagesRemoteDataSourceFake()
+
+ private val _state = MutableStateFlow>?>(null)
+ val state: StateFlow>?> = _state
+
+ fun loadData() {
+ viewModelScope.launch(Dispatchers.IO) {
+ val result = try {
+ Result.success(fakeMessages.getMessages())
+ } catch (exception: Throwable) {
+ Result.failure(exception)
+ }
+
+ _state.emit(result)
+ }
+ }
+}
diff --git a/app/src/main/java/com/github/krottv/tmstemp/view/FullscreenFragment.kt b/app/src/main/java/com/github/krottv/tmstemp/view/FullscreenFragment.kt
new file mode 100644
index 0000000..4b99d96
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/view/FullscreenFragment.kt
@@ -0,0 +1,62 @@
+package com.github.krottv.tmstemp.view
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.doOnPreDraw
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.FragmentNavigatorExtras
+import androidx.navigation.fragment.findNavController
+import androidx.transition.AutoTransition
+import coil.load
+import com.github.krottv.tmstemp.databinding.FullscreenMessageBinding
+import com.github.krottv.tmstemp.domain.MessageModel
+import java.util.concurrent.TimeUnit
+
+class FullscreenFragment: Fragment() {
+
+ companion object {
+ const val TRANSITION_ID = "Fullscreen"
+ }
+
+ private lateinit var binding: FullscreenMessageBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ sharedElementEnterTransition = AutoTransition()
+ sharedElementReturnTransition = AutoTransition()
+
+ binding = FullscreenMessageBinding.inflate(inflater, container, false)
+
+ binding.root.transitionName = TRANSITION_ID
+
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ val item: MessageModel = requireArguments().getParcelable("currentMessage")!!
+
+ postponeEnterTransition(3000, TimeUnit.MILLISECONDS)
+
+ binding.anyText.text = item.littleText
+ binding.imageView.load(item.mainImage) {
+ listener { request, result ->
+ (view.parent as? View)?.doOnPreDraw {
+ startPostponedEnterTransition()
+ }
+ }
+ }
+ binding.mainText.apply {
+ text = item.mainText
+ setOnClickListener {
+ findNavController().navigateUp()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/view/MainActivity.kt b/app/src/main/java/com/github/krottv/tmstemp/view/MainActivity.kt
new file mode 100644
index 0000000..e528fe2
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/view/MainActivity.kt
@@ -0,0 +1,15 @@
+package com.github.krottv.tmstemp.view
+
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import com.github.krottv.tmstemp.binder.MainActivityDataBinder
+import com.github.krottv.tmstemp.binder.MainActivityRecyclerScrollDataBinder
+
+class MainActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val mainActivityDataBinder: MainActivityDataBinder = MainActivityRecyclerScrollDataBinder(this)
+ mainActivityDataBinder.bind()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/view/MessageAdapter.kt b/app/src/main/java/com/github/krottv/tmstemp/view/MessageAdapter.kt
new file mode 100644
index 0000000..656ea99
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/view/MessageAdapter.kt
@@ -0,0 +1,39 @@
+package com.github.krottv.tmstemp.view
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import androidx.recyclerview.widget.RecyclerView
+import coil.load
+import com.github.krottv.tmstemp.R
+import com.github.krottv.tmstemp.domain.MessageModel
+
+class MessageAdapter(var data: List, private val onItemClick: (View, MessageModel) -> Unit): RecyclerView.Adapter() {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
+ val view = LayoutInflater.from(parent.context).inflate(R.layout.recycler_cell, parent, false)
+ return MessageViewHolder(view)
+ }
+
+ override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
+ val cell = data[position]
+ holder.mainImage.apply {
+ load(cell.mainImage)
+ scaleType = ImageView.ScaleType.CENTER_CROP
+ }
+
+ holder.mainText.text = cell.mainText
+ holder.littleText.text = cell.littleText
+
+ holder.itemView.transitionName = cell.transitionId()
+
+ holder.itemView.setOnClickListener {
+ onItemClick(it, cell)
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return data.size
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/view/MessageViewHolder.kt b/app/src/main/java/com/github/krottv/tmstemp/view/MessageViewHolder.kt
new file mode 100644
index 0000000..158f20d
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/view/MessageViewHolder.kt
@@ -0,0 +1,13 @@
+package com.github.krottv.tmstemp.view
+
+import android.view.View
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.github.krottv.tmstemp.R
+
+class MessageViewHolder(view: View): RecyclerView.ViewHolder(view) {
+ val mainImage: ImageView = view.findViewById(R.id.mainImage)
+ val mainText: TextView = view.findViewById(R.id.mainText)
+ val littleText: TextView = view.findViewById(R.id.littleText)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/krottv/tmstemp/view/RecyclerFragment.kt b/app/src/main/java/com/github/krottv/tmstemp/view/RecyclerFragment.kt
new file mode 100644
index 0000000..7b6973f
--- /dev/null
+++ b/app/src/main/java/com/github/krottv/tmstemp/view/RecyclerFragment.kt
@@ -0,0 +1,72 @@
+package com.github.krottv.tmstemp.view
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.doOnPreDraw
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.*
+import androidx.navigation.fragment.FragmentNavigatorExtras
+import androidx.navigation.fragment.findNavController
+import androidx.transition.AutoTransition
+import com.github.krottv.tmstemp.binder.RecyclerFragmentBinder
+import com.github.krottv.tmstemp.presentation.MessageViewModel
+import kotlinx.coroutines.launch
+import java.util.concurrent.TimeUnit
+
+class RecyclerFragment: Fragment() {
+
+ private lateinit var fragment: RecyclerFragmentBinder
+ private lateinit var viewModel: MessageViewModel
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ viewModel = ViewModelProvider(this)[MessageViewModel::class.java]
+
+ sharedElementEnterTransition = AutoTransition()
+ sharedElementReturnTransition = AutoTransition()
+
+ fragment = RecyclerFragmentBinder(this) { view, item ->
+ val navController = findNavController()
+
+ val action = RecyclerFragmentDirections.actionRecyclerFragmentToFullscreenFragment(item)
+ val extras = FragmentNavigatorExtras(view to FullscreenFragment.TRANSITION_ID)
+
+ navController.navigate(action, extras)
+ }
+
+ return fragment.bindView(inflater, container, savedInstanceState)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ postponeEnterTransition(1000, TimeUnit.MILLISECONDS)
+
+ viewModel.loadData()
+
+ lifecycleScope.launch {
+ viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+ viewModel.state.collect {
+ if (it != null) {
+ if (it.isSuccess) {
+ fragment.onDataLoaded(it.getOrThrow())
+
+ (view.parent as? ViewGroup)?.doOnPreDraw {
+ startPostponedEnterTransition()
+ }
+ } else {
+ fragment.showError(it.exceptionOrNull() as Throwable)
+ }
+ } else {
+ fragment.showProgress()
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 4fc2444..bf18798 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,18 +1,13 @@
-
-
-
-
-
-
\ No newline at end of file
+ android:layout_height="match_parent">
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fullscreen_message.xml b/app/src/main/res/layout/fullscreen_message.xml
new file mode 100644
index 0000000..af2697c
--- /dev/null
+++ b/app/src/main/res/layout/fullscreen_message.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/loading.xml b/app/src/main/res/layout/loading.xml
new file mode 100644
index 0000000..3e7fa63
--- /dev/null
+++ b/app/src/main/res/layout/loading.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/messages_fragment.xml b/app/src/main/res/layout/messages_fragment.xml
new file mode 100644
index 0000000..167ad72
--- /dev/null
+++ b/app/src/main/res/layout/messages_fragment.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/recycler_cell.xml b/app/src/main/res/layout/recycler_cell.xml
new file mode 100644
index 0000000..6a08f67
--- /dev/null
+++ b/app/src/main/res/layout/recycler_cell.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/scene_container.xml b/app/src/main/res/layout/scene_container.xml
new file mode 100644
index 0000000..f540014
--- /dev/null
+++ b/app/src/main/res/layout/scene_container.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/show_error.xml b/app/src/main/res/layout/show_error.xml
new file mode 100644
index 0000000..f612ab7
--- /dev/null
+++ b/app/src/main/res/layout/show_error.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml
new file mode 100644
index 0000000..135a69d
--- /dev/null
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 0ccd671..277b80e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,4 +1,15 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ google()
+ }
+ dependencies {
+ def nav_version = "2.4.2"
+ classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
+ }
+}
+
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false