Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
36004a2ba4
82
.kotlin/errors/errors-1739973336195.log
Normal file
82
.kotlin/errors/errors-1739973336195.log
Normal file
@ -0,0 +1,82 @@
|
||||
kotlin version: 2.0.21
|
||||
error message: Daemon compilation failed: null
|
||||
java.lang.Exception
|
||||
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:69)
|
||||
at org.jetbrains.kotlin.daemon.common.CompileService$CallResult$Error.get(CompileService.kt:65)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:240)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
|
||||
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
|
||||
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
|
||||
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
|
||||
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:195)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:128)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:170)
|
||||
at org.gradle.internal.Factories$1.create(Factories.java:31)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:267)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:131)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:136)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:165)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:134)
|
||||
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
|
||||
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
|
||||
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
|
||||
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:48)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
|
||||
at java.base/java.lang.Thread.run(Unknown Source)
|
||||
Caused by: java.nio.file.DirectoryNotEmptyException: C:\Users\User\AppData\Local\Temp\kotlin-backups5267971900938964466
|
||||
at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(Unknown Source)
|
||||
at java.base/sun.nio.fs.AbstractFileSystemProvider.delete(Unknown Source)
|
||||
at java.base/java.nio.file.Files.delete(Unknown Source)
|
||||
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
|
||||
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction$cleanupStash$2$1$1.invoke(CompilationTransaction.kt:244)
|
||||
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash$lambda$11$lambda$10$lambda$9(CompilationTransaction.kt:244)
|
||||
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Unknown Source)
|
||||
at java.base/java.util.ArrayList.forEach(Unknown Source)
|
||||
at java.base/java.util.stream.SortedOps$RefSortingSink.end(Unknown Source)
|
||||
at java.base/java.util.stream.Sink$ChainedReference.end(Unknown Source)
|
||||
at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
|
||||
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
|
||||
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source)
|
||||
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source)
|
||||
at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
|
||||
at java.base/java.util.stream.ReferencePipeline.forEach(Unknown Source)
|
||||
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.cleanupStash(CompilationTransaction.kt:244)
|
||||
at org.jetbrains.kotlin.incremental.RecoverableCompilationTransaction.close(CompilationTransaction.kt:254)
|
||||
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally(IncrementalCompilerRunner.kt:747)
|
||||
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:120)
|
||||
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:675)
|
||||
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:92)
|
||||
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1660)
|
||||
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
|
||||
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
|
||||
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
|
||||
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
|
||||
at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source)
|
||||
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
|
||||
at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source)
|
||||
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
|
||||
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
|
||||
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source)
|
||||
at java.base/java.security.AccessController.doPrivileged(Unknown Source)
|
||||
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
|
||||
... 3 more
|
||||
|
||||
|
@ -46,6 +46,7 @@ dependencies {
|
||||
|
||||
implementation(Dependencies.Retrofit.library)
|
||||
implementation(Dependencies.Retrofit.gsonConverter)
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.10.0")
|
||||
|
||||
implementation("com.squareup.picasso:picasso:2.8")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1")
|
||||
|
@ -1,64 +0,0 @@
|
||||
package ru.myitschool.work;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
* Use the {@link administrator_screen#newInstance} factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
public class administrator_screen extends Fragment {
|
||||
|
||||
// TODO: Rename parameter arguments, choose names that match
|
||||
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
||||
private static final String ARG_PARAM1 = "param1";
|
||||
private static final String ARG_PARAM2 = "param2";
|
||||
|
||||
// TODO: Rename and change types of parameters
|
||||
private String mParam1;
|
||||
private String mParam2;
|
||||
|
||||
public administrator_screen() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
* this fragment using the provided parameters.
|
||||
*
|
||||
* @param param1 Parameter 1.
|
||||
* @param param2 Parameter 2.
|
||||
* @return A new instance of fragment administrator_screen.
|
||||
*/
|
||||
// TODO: Rename and change types and number of parameters
|
||||
public static administrator_screen newInstance(String param1, String param2) {
|
||||
administrator_screen fragment = new administrator_screen();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_PARAM1, param1);
|
||||
args.putString(ARG_PARAM2, param2);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
mParam1 = getArguments().getString(ARG_PARAM1);
|
||||
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_administrator_screen, container, false);
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import ru.myitschool.work.api.list.ApiServiceList
|
||||
import ru.myitschool.work.api.login.ApiServiceLogin
|
||||
import ru.myitschool.work.api.main.ApiServiceMain
|
||||
import ru.myitschool.work.api.scan.ApiServiceScan
|
||||
@ -38,4 +39,10 @@ object NetworkModule {
|
||||
fun provideApiServiceScan(retrofitClient: RetrofitClient): ApiServiceScan {
|
||||
return retrofitClient.getApiServiceScanAuth()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideListApiService(retrofitClient: RetrofitClient): ApiServiceList {
|
||||
return retrofitClient.getApiServiceList()
|
||||
}
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
package ru.myitschool.work.api
|
||||
|
||||
import android.content.Context
|
||||
import com.google.android.datatransport.BuildConfig
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import ru.myitschool.work.api.list.ApiServiceList
|
||||
import ru.myitschool.work.api.login.ApiServiceLogin
|
||||
import ru.myitschool.work.api.main.ApiServiceMain
|
||||
import ru.myitschool.work.api.scan.ApiServiceScan
|
||||
@ -16,12 +19,18 @@ class RetrofitClient(context: Context) {
|
||||
private val serverAddress = SERVER_ADDRESS
|
||||
private var authPreferences: AuthPreferences = AuthPreferences(context)
|
||||
|
||||
|
||||
private val loggingInterceptor = HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
}
|
||||
|
||||
private val httpClientWithAuth = OkHttpClient.Builder()
|
||||
.connectTimeout(5, TimeUnit.SECONDS)
|
||||
.addInterceptor(BasicAuthInterceptor(
|
||||
authPreferences.getLogin() ?: "",
|
||||
authPreferences.getPassword() ?: ""
|
||||
))
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.readTimeout(5, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
@ -44,4 +53,8 @@ class RetrofitClient(context: Context) {
|
||||
fun getApiServiceScanAuth(): ApiServiceScan {
|
||||
return retrofitWithAuth.create(ApiServiceScan::class.java)
|
||||
}
|
||||
|
||||
fun getApiServiceList(): ApiServiceList {
|
||||
return retrofitWithAuth.create(ApiServiceList::class.java)
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
package ru.myitschool.work.api.list
|
||||
|
||||
import retrofit2.Call
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Path
|
||||
|
||||
interface ApiServiceList {
|
||||
@GET("api/auth/{login}")
|
||||
fun authenticate(@Path("login") login: String): Call<Void>
|
||||
@GET("api/list/{login}")
|
||||
suspend fun getList(@Path("login") login: String): Response<List<ListInfo>>
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package ru.myitschool.work.api.list
|
||||
|
||||
data class ListInfo(
|
||||
val value: String,
|
||||
val type: String,
|
||||
val time: String
|
||||
)
|
@ -8,6 +8,6 @@ import retrofit2.http.Path
|
||||
import ru.myitschool.work.api.main.UserInfo
|
||||
|
||||
interface ApiServiceLogin {
|
||||
@GET("api/auth")
|
||||
@GET("api/login")
|
||||
fun authenticate(): Call<Void>
|
||||
}
|
@ -2,10 +2,10 @@ package ru.myitschool.work.api.scan
|
||||
|
||||
import retrofit2.Call
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.PATCH
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Path
|
||||
|
||||
interface ApiServiceScan {
|
||||
@PATCH("api/info/{login}")
|
||||
@POST("api/add/{login}")
|
||||
fun open(@Path("login") login: String, @Body data: CodeJson): Call<Void>
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
package ru.myitschool.work.api.scan
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
class CodeJson(
|
||||
private var value: String? = null,
|
||||
private var type: String? = null,
|
||||
private var time: String? = null
|
||||
@SerializedName("value") var value: String? = null,
|
||||
@SerializedName("type") var type: String? = null,
|
||||
@SerializedName("time") var time: String? = null
|
||||
)
|
||||
|
||||
object OpenType {
|
||||
|
@ -1,5 +1,5 @@
|
||||
package ru.myitschool.work.core
|
||||
|
||||
object Constants {
|
||||
const val SERVER_ADDRESS = "http://192.168.1.113:8080"
|
||||
const val SERVER_ADDRESS = "http://10.6.66.93:8080"
|
||||
}
|
@ -13,8 +13,8 @@ import ru.myitschool.work.ui.login.LoginDestination
|
||||
import ru.myitschool.work.ui.login.LoginFragment
|
||||
import ru.myitschool.work.ui.main.MainDestination
|
||||
import ru.myitschool.work.ui.main.MainFragment
|
||||
import ru.myitschool.work.ui.qr.scan.QrScanDestination
|
||||
import ru.myitschool.work.ui.qr.scan.QrScanFragment
|
||||
import ru.myitschool.work.ui.scan.qr.QrScanDestination
|
||||
import ru.myitschool.work.ui.scan.qr.QrScanFragment
|
||||
import ru.myitschool.work.ui.result.ResultDestination
|
||||
import ru.myitschool.work.ui.result.ResultFragment
|
||||
|
||||
|
35
app/src/main/java/ru/myitschool/work/ui/list/ListAdapter.kt
Normal file
35
app/src/main/java/ru/myitschool/work/ui/list/ListAdapter.kt
Normal file
@ -0,0 +1,35 @@
|
||||
package ru.myitschool.work.ui.list
|
||||
|
||||
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ru.myitschool.work.R
|
||||
import ru.myitschool.work.api.list.ListInfo
|
||||
|
||||
class ListAdapter : ListAdapter<ListInfo, ListViewHolder>(DiffCallback()) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.item_recycler_view_entrancedata, parent, false)
|
||||
return ListViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
|
||||
val item = getItem(position)
|
||||
holder.bind(item)
|
||||
}
|
||||
|
||||
class DiffCallback : DiffUtil.ItemCallback<ListInfo>() {
|
||||
override fun areItemsTheSame(oldItem: ListInfo, newItem: ListInfo): Boolean {
|
||||
return oldItem.time == newItem.time && oldItem.value == newItem.value
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: ListInfo, newItem: ListInfo): Boolean {
|
||||
return oldItem == newItem
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package ru.myitschool.work.ui.list
|
||||
|
||||
import ru.myitschool.work.api.list.ApiServiceList
|
||||
import ru.myitschool.work.api.list.ListInfo
|
||||
import javax.inject.Inject
|
||||
|
||||
class ListRepository @Inject constructor(
|
||||
private val apiService: ApiServiceList
|
||||
) {
|
||||
suspend fun getList(login: String): List<ListInfo> {
|
||||
return apiService.getList(login).body() ?: emptyList()
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package ru.myitschool.work.ui.list
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ru.myitschool.work.api.list.ListInfo
|
||||
import ru.myitschool.work.databinding.ItemRecyclerViewEntrancedataBinding
|
||||
|
||||
class ListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val binding = ItemRecyclerViewEntrancedataBinding.bind(itemView)
|
||||
|
||||
fun bind(item: ListInfo) {
|
||||
binding.text1.text = item.time
|
||||
binding.text2.text = item.value
|
||||
binding.text3.text = item.type
|
||||
}
|
||||
}
|
@ -1,24 +1,23 @@
|
||||
package ru.myitschool.work.ui.main
|
||||
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.squareup.picasso.Picasso
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import ru.myitschool.work.R
|
||||
import ru.myitschool.work.databinding.FragmentMainBinding
|
||||
import ru.myitschool.work.ui.list.ListAdapter
|
||||
import ru.myitschool.work.ui.login.LoginDestination
|
||||
import ru.myitschool.work.ui.qr.scan.QrScanDestination
|
||||
import ru.myitschool.work.ui.scan.qr.QrScanDestination
|
||||
import ru.myitschool.work.utils.AuthPreferences
|
||||
import ru.myitschool.work.utils.collectWhenStarted
|
||||
import java.net.URL
|
||||
import ru.myitschool.work.utils.visibleOrGone
|
||||
import java.util.Locale
|
||||
|
||||
@AndroidEntryPoint
|
||||
@ -27,6 +26,7 @@ class MainFragment : Fragment(R.layout.fragment_main) {
|
||||
private val binding: FragmentMainBinding get() = _binding!!
|
||||
private lateinit var authPreferences: AuthPreferences
|
||||
private val viewModel: MainViewModel by viewModels()
|
||||
private lateinit var listAdapter: ListAdapter
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -41,23 +41,41 @@ class MainFragment : Fragment(R.layout.fragment_main) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = FragmentMainBinding.bind(view)
|
||||
|
||||
setupRecyclerView()
|
||||
|
||||
|
||||
if (authPreferences.isLoggedIn()) {
|
||||
setupMainComponents()
|
||||
|
||||
observeUserState()
|
||||
observeListState()
|
||||
|
||||
viewModel.getUserData(authPreferences.getLogin() ?: "")
|
||||
|
||||
val login = authPreferences.getLogin().toString()
|
||||
viewModel.loadList(login)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideAll() {
|
||||
binding.apply {
|
||||
username.visibility = View.GONE
|
||||
position.visibility = View.GONE
|
||||
lastEntry.visibility = View.GONE
|
||||
scan.visibility = View.GONE
|
||||
logout.visibility = View.GONE
|
||||
username.visibleOrGone(false)
|
||||
position.visibleOrGone(false)
|
||||
lastEntry.visibleOrGone(false)
|
||||
scan.visibleOrGone(false)
|
||||
logout.visibleOrGone(false)
|
||||
|
||||
error.visibility = View.VISIBLE
|
||||
refresh.visibility = View.VISIBLE
|
||||
error.visibleOrGone(true)
|
||||
refresh.visibleOrGone(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
listAdapter = ListAdapter()
|
||||
binding.entranceData.apply {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
adapter = listAdapter
|
||||
addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,19 +83,19 @@ class MainFragment : Fragment(R.layout.fragment_main) {
|
||||
viewModel.state.collectWhenStarted(this) { state ->
|
||||
when (state) {
|
||||
is MainViewModel.MainState.Initial -> {
|
||||
binding.error.visibility = View.GONE
|
||||
binding.error.visibleOrGone(false)
|
||||
}
|
||||
is MainViewModel.MainState.Loading -> {
|
||||
binding.error.visibility = View.GONE
|
||||
binding.error.visibleOrGone(false)
|
||||
}
|
||||
is MainViewModel.MainState.Success -> {
|
||||
binding.apply {
|
||||
username.visibility = View.VISIBLE
|
||||
position.visibility = View.VISIBLE
|
||||
lastEntry.visibility = View.VISIBLE
|
||||
scan.visibility = View.VISIBLE
|
||||
logout.visibility = View.VISIBLE
|
||||
error.visibility = View.GONE
|
||||
username.visibleOrGone(true)
|
||||
position.visibleOrGone(true)
|
||||
lastEntry.visibleOrGone(true)
|
||||
scan.visibleOrGone(true)
|
||||
logout.visibleOrGone(true)
|
||||
error.visibleOrGone(false)
|
||||
|
||||
username.text = state.userInfo.name
|
||||
position.text = state.userInfo.position
|
||||
@ -103,26 +121,31 @@ class MainFragment : Fragment(R.layout.fragment_main) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadImageFromUrl(url: String) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val bitmap = try {
|
||||
val input = URL(url).openStream()
|
||||
BitmapFactory.decodeStream(input)
|
||||
} catch (e: Exception) {
|
||||
Log.e("MainFragment", "Error loading image", e)
|
||||
null
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
if (bitmap != null) {
|
||||
binding.photo.setImageBitmap(bitmap)
|
||||
} else {
|
||||
binding.photo.setImageResource(R.drawable.ic_no_img)
|
||||
private fun observeListState() {
|
||||
viewModel.listState.collectWhenStarted(this) { state ->
|
||||
when (state) {
|
||||
is MainViewModel.ListState.Loading -> {
|
||||
//TODO
|
||||
}
|
||||
is MainViewModel.ListState.Success -> {
|
||||
listAdapter.submitList(state.data)
|
||||
}
|
||||
is MainViewModel.ListState.Error -> {
|
||||
//TODO
|
||||
binding.error.text = state.message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadImageFromUrl(url: String) {
|
||||
Picasso
|
||||
.get()
|
||||
.load(url)
|
||||
.error(R.drawable.icon_profile)
|
||||
.into(binding.photo)
|
||||
}
|
||||
|
||||
private fun setupMainComponents() {
|
||||
binding.logout.setOnClickListener {
|
||||
authPreferences.clearLoginState()
|
||||
|
@ -5,18 +5,22 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import ru.myitschool.work.api.list.ListInfo
|
||||
import ru.myitschool.work.api.main.ApiServiceMain
|
||||
import ru.myitschool.work.api.main.UserInfo
|
||||
import ru.myitschool.work.ui.list.ListRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class MainViewModel @Inject constructor(
|
||||
private val apiService: ApiServiceMain
|
||||
private val apiService: ApiServiceMain,
|
||||
private val listRepository: ListRepository
|
||||
) : ViewModel() {
|
||||
|
||||
private val _state = MutableStateFlow<MainState>(MainState.Initial)
|
||||
@ -52,6 +56,27 @@ class MainViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val _listState = MutableStateFlow<ListState>(ListState.Loading)
|
||||
val listState: StateFlow<ListState> = _listState
|
||||
|
||||
sealed class ListState {
|
||||
data object Loading : ListState()
|
||||
data class Success(val data: List<ListInfo>) : ListState()
|
||||
data class Error(val message: String) : ListState()
|
||||
}
|
||||
|
||||
fun loadList(login: String) {
|
||||
viewModelScope.launch {
|
||||
_listState.value = ListState.Loading
|
||||
try {
|
||||
val list = listRepository.getList(login)
|
||||
_listState.value = ListState.Success(list)
|
||||
} catch (e: Exception) {
|
||||
_listState.value = ListState.Error(e.message ?: "Unknown error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class MainState {
|
||||
data object Initial : MainState()
|
||||
data object Loading : MainState()
|
||||
|
@ -13,8 +13,8 @@ import ru.myitschool.work.api.scan.CodeJson
|
||||
import ru.myitschool.work.api.scan.OpenType
|
||||
import ru.myitschool.work.databinding.FragmentScanResultBinding
|
||||
import ru.myitschool.work.ui.main.MainDestination
|
||||
import ru.myitschool.work.ui.qr.scan.QrScanDestination
|
||||
import ru.myitschool.work.utils.AuthPreferences
|
||||
import ru.myitschool.work.utils.QrPreferences
|
||||
import ru.myitschool.work.utils.collectWhenStarted
|
||||
import ru.myitschool.work.utils.getCurrentTime
|
||||
import ru.myitschool.work.utils.visibleOrGone
|
||||
@ -24,11 +24,16 @@ class ResultFragment : Fragment(R.layout.fragment_scan_result) {
|
||||
private var _binding: FragmentScanResultBinding? = null
|
||||
private val binding: FragmentScanResultBinding get() = _binding!!
|
||||
private val viewModel: ResultViewModel by viewModels()
|
||||
|
||||
private lateinit var authPreferences: AuthPreferences
|
||||
private lateinit var qrPreferences: QrPreferences
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
authPreferences = AuthPreferences(requireContext())
|
||||
qrPreferences = QrPreferences(requireContext())
|
||||
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@ -45,18 +50,24 @@ class ResultFragment : Fragment(R.layout.fragment_scan_result) {
|
||||
successIcon.visibleOrGone(false)
|
||||
|
||||
close.setOnClickListener {
|
||||
navigateToMainScreen()
|
||||
navigateToResultScreen()
|
||||
}
|
||||
}
|
||||
|
||||
val qrData = QrScanDestination.getDataIfExist(arguments ?: Bundle())
|
||||
authPreferences.getLogin()?.let { login ->
|
||||
val currentTime = getCurrentTime()
|
||||
viewModel.open(login, CodeJson(
|
||||
value = qrData,
|
||||
type = OpenType.QR_TYPE,
|
||||
time = currentTime
|
||||
))
|
||||
val qrData = qrPreferences.getQr()
|
||||
|
||||
if (qrData != null) {
|
||||
authPreferences.getLogin()?.let { login ->
|
||||
val currentTime = getCurrentTime()
|
||||
viewModel.open(login, CodeJson(
|
||||
value = qrData.toString(),
|
||||
type = OpenType.QR_TYPE,
|
||||
time = currentTime
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Log.e("ResultFragment", "QR data is null")
|
||||
Toast.makeText(context, getString(R.string.error), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,7 +105,7 @@ class ResultFragment : Fragment(R.layout.fragment_scan_result) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToMainScreen() {
|
||||
private fun navigateToResultScreen() {
|
||||
try {
|
||||
findNavController().apply {
|
||||
popBackStack(MainDestination, false)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package ru.myitschool.work.ui.qr.scan
|
||||
package ru.myitschool.work.ui.scan.qr
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.core.os.bundleOf
|
||||
import kotlinx.serialization.Serializable
|
||||
|
@ -1,7 +1,9 @@
|
||||
package ru.myitschool.work.ui.qr.scan
|
||||
package ru.myitschool.work.ui.scan.qr
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.camera.core.ImageAnalysis
|
||||
import androidx.camera.mlkit.vision.MlKitAnalyzer
|
||||
@ -20,6 +22,9 @@ import com.google.mlkit.vision.barcode.BarcodeScanning
|
||||
import com.google.mlkit.vision.barcode.common.Barcode
|
||||
import ru.myitschool.work.R
|
||||
import ru.myitschool.work.databinding.FragmentQrScanBinding
|
||||
import ru.myitschool.work.ui.main.MainDestination
|
||||
import ru.myitschool.work.ui.result.ResultDestination
|
||||
import ru.myitschool.work.utils.QrPreferences
|
||||
import ru.myitschool.work.utils.collectWhenStarted
|
||||
import ru.myitschool.work.utils.visibleOrGone
|
||||
|
||||
@ -34,6 +39,14 @@ class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
|
||||
) { isGranted -> viewModel.onPermissionResult(isGranted) }
|
||||
|
||||
private val viewModel: QrScanViewModel by viewModels()
|
||||
private lateinit var qrPreferences: QrPreferences
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
qrPreferences = QrPreferences(requireContext())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
@ -65,7 +78,7 @@ class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
|
||||
}
|
||||
is QrScanViewModel.Action.CloseWithResult -> {
|
||||
sendResult(QrScanDestination.packToBundle(action.result))
|
||||
goBack()
|
||||
goResult()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,10 +126,31 @@ class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
|
||||
}
|
||||
|
||||
private fun goBack() {
|
||||
val qrData = arguments?.let { QrScanDestination.getDataIfExist(it) }
|
||||
qrPreferences.saveQr(qrData.toString())
|
||||
|
||||
findNavControllerOrNull()?.popBackStack()
|
||||
?: requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
private fun goResult() {
|
||||
try {
|
||||
val qrData = arguments?.let { QrScanDestination.getDataIfExist(it) }
|
||||
qrPreferences.saveQr(qrData.toString())
|
||||
|
||||
Log.i("ResultFragment", qrData.toString())
|
||||
|
||||
findNavController().apply {
|
||||
popBackStack(ResultDestination, false)
|
||||
navigate(ResultDestination)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("ResultFragment", "Navigation error", e)
|
||||
Toast.makeText(context, getText(R.string.errorGoText).toString(), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun sendResult(bundle: Bundle) {
|
||||
setFragmentResult(
|
||||
QrScanDestination.REQUEST_KEY,
|
@ -1,4 +1,4 @@
|
||||
package ru.myitschool.work.ui.qr.scan
|
||||
package ru.myitschool.work.ui.scan.qr
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Application
|
27
app/src/main/java/ru/myitschool/work/utils/QrPreferences.kt
Normal file
27
app/src/main/java/ru/myitschool/work/utils/QrPreferences.kt
Normal file
@ -0,0 +1,27 @@
|
||||
package ru.myitschool.work.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
|
||||
class QrPreferences(context: Context) {
|
||||
private val sharedPreferences: SharedPreferences = context.getSharedPreferences(
|
||||
PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
|
||||
fun saveQr(login: String) {
|
||||
sharedPreferences.edit().apply {
|
||||
putString("qr", login)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
fun getQr(): String? {
|
||||
return sharedPreferences.getString("qr", null)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private const val PREFS_NAME = "ArPreferences"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user