feat: Sync and fix problems with navigation

This commit is contained in:
SunZar 2025-02-19 16:36:03 +03:00 committed by SunZar
parent a29cdbb5d5
commit 290de5f6cd
28 changed files with 645 additions and 222 deletions

View File

@ -0,0 +1,4 @@
kotlin version: 2.0.21
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
1. Kotlin compile daemon is ready

View File

@ -47,6 +47,7 @@ dependencies {
implementation(Dependencies.Retrofit.library)
implementation(Dependencies.Retrofit.gsonConverter)
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("com.squareup.picasso:picasso:2.8")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1")
implementation("androidx.datastore:datastore-preferences:1.1.1")

View File

@ -17,10 +17,12 @@
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.Default"
tools:targetApi="31">
<activity
android:name=".ui.RootActivity"
android:windowSoftInputMode="adjustPan"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -12,6 +12,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentResultListener;
import androidx.navigation.Navigation;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.squareup.picasso.Picasso;
@ -44,16 +46,16 @@ public class InformationFragment extends Fragment {
getInformation();
binding.refresh.setOnClickListener(view1 -> {
onClickRefresh();
});
binding.scan.setOnClickListener(view1 -> {
onClickScan();
onClickScan(view);
});
binding.logout.setOnClickListener(view2 -> {
onClickLogout();
onClickLogout(view);
});
binding.refreshLayout.setOnRefreshListener(() -> {
onClickRefresh();
});
//getParentFragmentManager()
@ -66,8 +68,9 @@ public class InformationFragment extends Fragment {
ResultFragment resFragment = ResultFragment.newInstance(res);
getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, resFragment).commit();
//ResultFragment resFragment = ResultFragment.newInstance(res);
Navigation.findNavController(view).navigate(R.id.action_informationFragment_to_resultFragment);
//getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, resFragment).commit();
});
}
@ -75,13 +78,15 @@ public class InformationFragment extends Fragment {
getInformation();
}
private void onClickScan() {
getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new QrScanFragment()).commit();
private void onClickScan(View view) {
Navigation.findNavController(view).navigate(R.id.action_informationFragment_to_qrScanFragment);
//getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new QrScanFragment()).commit();
}
private void onClickLogout() {
private void onClickLogout(View view) {
sharedPreferences.edit().clear().apply();
getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new LoginFragment()).commit();
Navigation.findNavController(view).navigate(R.id.action_informationFragment_to_loginFragment);
//getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new LoginFragment()).commit();
}
private void getInformation() {
@ -105,6 +110,7 @@ public class InformationFragment extends Fragment {
binding.position.setText(user.getPosition());
binding.lastEntry.setText(user.getLastVisit().substring(0, 10) + " " + user.getLastVisit().substring(11, 16));
Picasso.get().load(user.getPhoto()).into(binding.photo);
binding.refreshLayout.setRefreshing(false);
} else {
takeError();
}
@ -133,5 +139,6 @@ public class InformationFragment extends Fragment {
binding.scan.setVisibility(View.GONE);
binding.error.setVisibility(View.VISIBLE);
binding.refreshLayout.setRefreshing(false);
}
}

View File

@ -0,0 +1,35 @@
package ru.myitschool.work.ui;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import ru.myitschool.work.R;
import ru.myitschool.work.databinding.FragmentProfileBinding;
import ru.myitschool.work.databinding.FragmentResultBinding;
public class ProfileFragment extends Fragment {
FragmentProfileBinding binding;
SharedPreferences sharedPreferences;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentProfileBinding.inflate(inflater, container, false);
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
sharedPreferences = getContext().getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE);
}
}

View File

@ -10,6 +10,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import java.util.Objects;
@ -58,12 +59,13 @@ public class ResultFragment extends Fragment {
}
binding.close.setOnClickListener(view1 -> {
onClickClose();
onClickClose(view);
});
}
private void onClickClose() {
getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new InformationFragment()).commit();
private void onClickClose(View view) {
Navigation.findNavController(view).navigate(R.id.action_resultFragment_to_informationFragment);
//getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new InformationFragment()).commit();
}
private void patchDoor() {

View File

@ -0,0 +1,74 @@
package ru.myitschool.work.ui;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import ru.myitschool.work.R;
import ru.myitschool.work.databinding.ActivityRootBinding;
public class RootActivity extends AppCompatActivity {
private ActivityRootBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityRootBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.navView.setOnItemSelectedListener(item -> {
switch (item.getItemId()) {
case R.id.history:
onClickNavHistory();
break;
case R.id.profile:
onClickNavProfile();
break;
}
return true;
});
}
private void onClickNavHistory() {
NavHostFragment navHostFragment =
(NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.root_fragment);
NavController navController = navHostFragment.getNavController();
//navHostFragment.getChildFragmentManager().getFragments().get(0);
switch (navController.getCurrentDestination().getId()) {
// case R.id.historyFragment:
// navController.navigate(R.id.action_listFragment_to_mapFragment);
// break;
case R.id.profileFragment:
navController.navigate(R.id.action_informationFragment_to_profileFragment);
break;
}
Log.d("tagigi", navController.getCurrentDestination().getId() + "");
//Log.d("tagigi", R.id.listFragment + "");
//.navigate(R.id.action_listFragment_to_mapFragment);
}
private void onClickNavProfile() {
NavHostFragment navHostFragment =
(NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.root_fragment);
NavController navController = navHostFragment.getNavController();
//navController.navigate(R.id.action_listFragment_to_profileFragment);
switch (navController.getCurrentDestination().getId()) {
case R.id.informationFragment:
navController.navigate(R.id.action_profileFragment_to_informationFragment);
break;
// case R.id.profileFragment:
// navController.navigate(R.id.action_mapFragment_to_profileFragment);
// break;
}
}
/*
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp();
}*/
}

View File

@ -1,83 +0,0 @@
package ru.myitschool.work.ui
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.createGraph
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.fragment
import dagger.hilt.android.AndroidEntryPoint
import ru.myitschool.work.R
import ru.myitschool.work.ui.login.LoginDestination
import ru.myitschool.work.ui.login.LoginFragment
import ru.myitschool.work.ui.qr.scan.QrScanDestination
import ru.myitschool.work.ui.qr.scan.QrScanFragment
// НЕ ИЗМЕНЯЙТЕ НАЗВАНИЕ КЛАССА!
@AndroidEntryPoint
class RootActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_root)
val navHostFragment = supportFragmentManager
.findFragmentById(R.id.nav_host_fragment) as NavHostFragment?
if (navHostFragment != null) {
val navController = navHostFragment.navController
navController.graph = navController.createGraph(
startDestination = LoginDestination
) {
fragment<LoginFragment, LoginDestination>()
fragment<QrScanFragment, QrScanDestination>()
fragment<ru.myitschool.work.ui.LoginFragment, LoginDestination>()
fragment<ResultFragment, LoginDestination>()
}
}
val sharedPreferences = getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE)
val login = sharedPreferences.getString(Constants.KEY_LOGIN, "")
//Toast.makeText(baseContext, login, Toast.LENGTH_LONG).show()
if (login != "") {
val fragment = ru.myitschool.work.ui.InformationFragment() // Create an instance of your fragment
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.nav_host_fragment, fragment) // Add the fragment to the container
transaction.commit()
} else {
val fragment = ru.myitschool.work.ui.LoginFragment() // Create an instance of your fragment
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.nav_host_fragment, fragment) // Add the fragment to the container
transaction.commit()
}
/*if (supportFragmentManager.findFragmentById(R.id.nav_host_fragment) == null) {
Toast.makeText(baseContext, "hhgjgg", Toast.LENGTH_LONG).show()
val fragment = ru.myitschool.work.ui.LoginFragment() // Create an instance of your fragment
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.nav_host_fragment, fragment) // Add the fragment to the container
transaction.commit()
}*/
/*onBackPressedDispatcher.addCallback(
this,
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
onSupportNavigateUp()
}
}
)*/
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
val popBackResult = if (navController.previousBackStackEntry != null) {
navController.popBackStack()
} else {
false
}
return popBackResult || super.onSupportNavigateUp()
}
}

View File

@ -1,6 +0,0 @@
package ru.myitschool.work.ui.login
import kotlinx.serialization.Serializable
@Serializable
data object LoginDestination

View File

@ -1,18 +1,20 @@
package ru.myitschool.work.ui;
package ru.myitschool.work.ui.login;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import retrofit2.Call;
import retrofit2.Callback;
@ -22,11 +24,15 @@ import retrofit2.converter.gson.GsonConverterFactory;
import ru.myitschool.work.R;
import ru.myitschool.work.core.Constants;
import ru.myitschool.work.databinding.FragmentLoginBinding;
import ru.myitschool.work.ui.StoreAPI;
import ru.myitschool.work.utils.OnChangeText;
import ru.myitschool.work.utils.PreferenceManager;
public class LoginFragment extends Fragment {
FragmentLoginBinding binding;
SharedPreferences sharedPreferences;
private FragmentLoginBinding binding;
private PreferenceManager preferenceManager;
private LoginViewModel viewModel;
@Nullable
@Override
@ -40,9 +46,34 @@ public class LoginFragment extends Fragment {
super.onViewCreated(view, savedInstanceState);
//binding.log.setText("created");
sharedPreferences = getContext().getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE);
preferenceManager = new PreferenceManager(this.getContext());
viewModel = new ViewModelProvider(this).get(LoginViewModel.class);
//sharedPreferences.edit().putString(ru.myitschool.work.ui.Constants.KEY_LOGIN, "5user").apply();
binding.login.setEnabled(false);
binding.username.addTextChangedListener(new OnChangeText() {
@Override
public void afterTextChanged(Editable s) {
super.afterTextChanged(s);
viewModel.changeUsername(s.toString());
if (binding.username.getText().length() >= 3 && binding.username.getText().toString().matches("[0-9a-zA-Z]+") && (binding.username.getText().toString().charAt(0) + "").matches("[0-9]+")) {
binding.login.setEnabled(true);
} else {
binding.login.setEnabled(false);
}
if (binding.error.getVisibility() == View.VISIBLE) {
binding.error.setVisibility(View.GONE);
}
}
});
binding.password.addTextChangedListener(new OnChangeText() {
@Override
public void afterTextChanged(Editable s) {
super.afterTextChanged(s);
viewModel.changePassword(s.toString());
}
});
binding.username.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
@ -71,18 +102,21 @@ public class LoginFragment extends Fragment {
});
binding.login.setOnClickListener(view1 -> {
if (binding.login.isEnabled()) {
viewModel.confirm();
/*if (binding.login.isEnabled()) {
if (binding.error.getVisibility() == View.VISIBLE) {
binding.error.setVisibility(View.GONE);
//binding.log.setText("click enabled");
}
//binding.log.setText("click");
onClickLogin();
}
onClickLogin(view);
}*/
});
subscribe(viewModel);
}
private void onClickLogin() {
private void onClickLogin(View view) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.SERVER_ADDRESS)
.addConverterFactory(GsonConverterFactory.create())
@ -98,8 +132,9 @@ public class LoginFragment extends Fragment {
public void onResponse(Call<Boolean> call, Response<Boolean> response) {
if (response.isSuccessful()) {
if (response.body() != null && response.body()) {
sharedPreferences.edit().putString(ru.myitschool.work.ui.Constants.KEY_LOGIN, binding.username.getText().toString()).apply();
getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new InformationFragment()).commit();
preferenceManager.putString(ru.myitschool.work.ui.Constants.KEY_LOGIN, binding.username.getText().toString());
Navigation.findNavController(view).navigate(R.id.action_loginFragment_to_informationFragment);
//getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new InformationFragment()).commit();
} else {
binding.error.setVisibility(View.VISIBLE);
}
@ -118,4 +153,28 @@ public class LoginFragment extends Fragment {
}
});
}
private void subscribe(LoginViewModel viewModel) {
viewModel.errorLiveData.observe(getViewLifecycleOwner(), error -> {
Toast.makeText(getContext(), error, Toast.LENGTH_SHORT).show();
});
/*viewModel.stateLiveData.observe(getViewLifecycleOwner(), state -> {
binding.confirm.setText(state.getButton());
binding.title.setText(state.getTitle());
binding.password.setVisibility(Utils.visibleOrGone(state.isPasswordEnabled()));
});*/
viewModel.openListLiveData.observe(getViewLifecycleOwner(), username -> {
final View view = getView();
if (view == null) return;
preferenceManager.putString(ru.myitschool.work.utils.Constants.KEY_USER_USERNAME, username);
view.getRootView().findViewById(R.id.nav_view).setVisibility(View.VISIBLE);
Navigation.findNavController(view).navigate(R.id.action_loginFragment_to_informationFragment);
});
}
@Override
public void onDestroyView() {
binding = null;
super.onDestroyView();
}
}

View File

@ -1,38 +0,0 @@
package ru.myitschool.work.ui.login
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint
import ru.myitschool.work.R
import ru.myitschool.work.databinding.FragmentLoginBinding
import ru.myitschool.work.utils.collectWhenStarted
import ru.myitschool.work.utils.visibleOrGone
@AndroidEntryPoint
class LoginFragment : Fragment(R.layout.fragment_login) {
private var _binding: FragmentLoginBinding? = null
private val binding: FragmentLoginBinding get() = _binding!!
private val viewModel: LoginViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_binding = FragmentLoginBinding.bind(view)
subscribe()
}
private fun subscribe() {
viewModel.state.collectWhenStarted(this) { state ->
binding.loading.visibleOrGone(state)
}
}
override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
}

View File

@ -0,0 +1,168 @@
package ru.myitschool.work.ui.login;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import ru.myitschool.work.R;
import ru.myitschool.work.data.UserRepositoryImpl;
import ru.myitschool.work.domain.sign.CreateUserUseCase;
import ru.myitschool.work.domain.sign.IsUserExistUseCase;
import ru.myitschool.work.domain.sign.LoginUserUseCase;
public class LoginViewModel extends ViewModel {
private final State INIT_STATE = new State(R.string.title_init, R.string.button_init, false);
private final MutableLiveData<State> mutableStateLiveData = new MutableLiveData<>(
INIT_STATE
);
public final LiveData<State> stateLiveData = mutableStateLiveData;
private final MutableLiveData<String> mutableErrorLiveData = new MutableLiveData<>();
public final LiveData<String> errorLiveData = mutableErrorLiveData;
private final MutableLiveData<String> mutableOpenListLiveData = new MutableLiveData<>();
public final LiveData<String> openListLiveData = mutableOpenListLiveData;
/* UseCases */
private final IsUserExistUseCase isUserExistUseCase = new IsUserExistUseCase(
UserRepositoryImpl.getInstance()
);
private final LoginUserUseCase loginUserUseCase = new LoginUserUseCase(
UserRepositoryImpl.getInstance()
);
/* UseCases */
@Nullable
private String username = null;
@Nullable
private String password = null;
private boolean userCheckCompleted = false;
private boolean isAccountExist = false;
public void changeUsername(@NonNull String username) {
this.username = username;
if (userCheckCompleted) {
userCheckCompleted = false;
mutableStateLiveData.postValue(INIT_STATE);
}
}
public void changePassword(@NonNull String password) {
this.password = password;
}
public void confirm() {
if (userCheckCompleted) {
checkAuth();
} else {
checkUserExist();
}
}
private void checkAuth() {
final String currentUsername = username;
final String currentPassword = password;
if (currentPassword == null || currentPassword.isEmpty()) {
mutableErrorLiveData.postValue("Password cannot be null");
return;
}
if (currentUsername == null || currentUsername.isEmpty()) {
mutableErrorLiveData.postValue("Login cannot be null");
return;
}
if (!isAccountExist) {
mutableErrorLiveData.postValue("This user not exist");
return;
/*createUserUseCase.execute(currentUsername, currentPassword, status -> {
if (status.getStatusCode() == 201 && status.getErrors() == null) {
loginUser(currentUsername, currentPassword);
} else {
mutableErrorLiveData.postValue("Something wrong");
}
});*/
} else {
Log.d("tagg", currentUsername + " " + currentPassword);
loginUser(currentUsername, currentPassword);
}
}
private void loginUser(@NonNull final String currentUsername, @NonNull final String currentPassword) {
loginUserUseCase.execute(currentUsername, currentPassword, status -> {
Log.d("tagg", status.getStatusCode() + " " + status.getErrors());
if (status.getStatusCode() == 200 && status.getErrors() == null) {
mutableOpenListLiveData.postValue(currentUsername);
} else {
mutableErrorLiveData.postValue("Something wrong");
}
});
}
private void checkUserExist() {
final String currentUsername = username;
if (currentUsername == null || currentUsername.isEmpty()) {
mutableErrorLiveData.postValue("Login cannot be null");
return;
}
isUserExistUseCase.execute(currentUsername, status -> {
if (status.getErrors() != null) {
//Log.d("tagg", status.getErrors().toString());
mutableErrorLiveData.postValue("Something wrong. Try later =(" + status.getErrors());
return;
}
userCheckCompleted = true;
Log.d("tagigiii", status.getStatusCode() + "");
if (status.getStatusCode() == 200) {
isAccountExist = true;
} else {
isAccountExist = false;
}
//isNewAccount = !status.getValue();
checkAuth();
/*if(isNewAccount) {
mutableStateLiveData.postValue(
new State(R.string.title_user_new, R.string.button_user_new, true)
);
} else {
mutableStateLiveData.postValue(
new State(R.string.title_user_exist, R.string.button_user_exist, true)
);
}*/
});
}
public class State {
@StringRes
private final int title;
@StringRes
private final int button;
private final boolean isPasswordEnabled;
public State(int title, int button, boolean isPasswordEnabled) {
this.title = title;
this.button = button;
this.isPasswordEnabled = isPasswordEnabled;
}
public int getTitle() {
return title;
}
public int getButton() {
return button;
}
public boolean isPasswordEnabled() {
return isPasswordEnabled;
}
}
}

View File

@ -1,17 +0,0 @@
package ru.myitschool.work.ui.login
import android.content.Context
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import javax.inject.Inject
@HiltViewModel
class LoginViewModel @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
private val _state = MutableStateFlow(true)
val state = _state.asStateFlow()
}

View File

@ -0,0 +1,6 @@
package ru.myitschool.work.utils;
public class Constants {
public static final String KEY_PREFERENCE_NAME = "App";
public static final String KEY_USER_USERNAME = "userUsername";
}

View File

@ -0,0 +1,22 @@
package ru.myitschool.work.utils;
import android.text.Editable;
import android.text.TextWatcher;
public class OnChangeText implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
}

View File

@ -0,0 +1,38 @@
package ru.myitschool.work.utils;
import android.content.Context;
import android.content.SharedPreferences;
public class PreferenceManager {
private final SharedPreferences sharedPreferences;
public PreferenceManager(Context context) {
sharedPreferences = context.getSharedPreferences(Constants.KEY_PREFERENCE_NAME, Context.MODE_PRIVATE);
}
public void putBoolean(String key, Boolean value) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean(key, value);
editor.apply();
}
public Boolean getBoolean(String key) {
return sharedPreferences.getBoolean(key, false);
}
public void putString(String key, String value) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(key, value);
editor.apply();
}
public String getString(String key) {
return sharedPreferences.getString(key, null);
}
public void clear() {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.clear();
editor.apply();
}
}

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,6c1.93,0 3.5,1.57 3.5,3.5S13.93,13 12,13s-3.5,-1.57 -3.5,-3.5S10.07,6 12,6zM12,20c-2.03,0 -4.43,-0.82 -6.14,-2.88C7.55,15.8 9.68,15 12,15s4.45,0.8 6.14,2.12C16.43,19.18 14.03,20 12,20z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
</vector>

View File

@ -1,13 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
<fragment
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/nav_view"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/root_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true" />
</FrameLayout>
android:layout_height="0dp"
app:navGraph="@navigation/nav_graph"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
tools:context=".MainActivity"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,52 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<TextView
android:id="@+id/fullname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/lastEntry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/logout"
android:text="@string/logout"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
android:layout_height="match_parent">
<Button
android:id="@+id/refresh"
android:text="@string/refresh"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/fullname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<Button
android:id="@+id/scan"
android:text="@string/scan"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/fullname"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/error"
android:visibility="gone"
android:text="@string/error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/photo"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</LinearLayout>
<TextView
android:id="@+id/lastEntry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/position"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/logout"
android:text="@string/logout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/lastEntry"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/refresh"
android:text="@string/refresh"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/logout"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/scan"
android:text="@string/scan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/refresh"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/error"
android:visibility="gone"
android:text="@string/error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/scan"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@ -11,7 +11,13 @@
android:layout_height="wrap_content"
android:hint="@string/username"/>
<Button
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/password"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/login"
android:text="@string/login"
android:layout_width="match_parent"

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/history"
android:title="История"
android:icon="@drawable/baseline_history_24"/>
<item
android:id="@+id/profile"
android:title="Профиль"
android:icon="@drawable/baseline_account_circle_24"/>
</menu>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/loginFragment">
<fragment
android:id="@+id/informationFragment"
android:name="ru.myitschool.work.ui.InformationFragment"
android:label="HistoryList"
tools:layout="@layout/fragment_information">
<action
android:id="@+id/action_informationFragment_to_qrScanFragment"
app:destination="@id/qrScanFragment" />
<action
android:id="@+id/action_informationFragment_to_resultFragment"
app:destination="@id/resultFragment" />
<action
android:id="@+id/action_informationFragment_to_loginFragment"
app:destination="@id/loginFragment" />
<action
android:id="@+id/action_informationFragment_to_profileFragment"
app:destination="@id/profileFragment" />
</fragment>
<fragment
android:id="@+id/profileFragment"
android:name="ru.myitschool.work.ui.ProfileFragment"
android:label="ProfileFragment"
tools:layout="@layout/fragment_profile">
<action
android:id="@+id/action_profileFragment_to_informationFragment"
app:destination="@id/informationFragment" />
</fragment>
<fragment
android:id="@+id/loginFragment"
android:name="ru.myitschool.work.ui.login.LoginFragment"
android:label="LoginFragment"
tools:layout="@layout/fragment_login" >
<action
android:id="@+id/action_loginFragment_to_informationFragment"
app:destination="@id/informationFragment" />
<!-- <action-->
<!-- android:id="@+id/action_signInFragment_to_signUpFragment" -->
<!-- app:destination="@id/signUpFragment" />-->
<!-- TODO: ADMINISTRATOR-->
</fragment>
<fragment
android:id="@+id/qrScanFragment"
android:name="ru.myitschool.work.ui.qr.scan.QrScanFragment"
android:label="QrScanFragment"
tools:layout="@layout/fragment_qr_scan" >
<action
android:id="@+id/action_qrScanFragment_to_informationFragment"
app:destination="@id/informationFragment" />
</fragment>
<fragment
android:id="@+id/resultFragment"
android:name="ru.myitschool.work.ui.ResultFragment"
android:label="ResultFragment"
tools:layout="@layout/fragment_qr_scan" >
<action
android:id="@+id/action_resultFragment_to_informationFragment"
app:destination="@id/informationFragment" />
</fragment>
</navigation>

View File

@ -3,6 +3,7 @@
<string name="username">Login</string>
<string name="close">Close</string>
<string name="login">Login</string>
<string name="password">Password</string>
<string name="logout">Logout</string>
<string name="refresh">Refresh</string>
<string name="scan">Scan</string>

View File

@ -3,6 +3,7 @@
<string name="username">Логин</string>
<string name="close">Закрыть</string>
<string name="login">Войти</string>
<string name="password">Пароль</string>
<string name="logout">Выйти</string>
<string name="refresh">Обновить</string>
<string name="scan">Отсканировать</string>

View File

@ -3,6 +3,7 @@
<string name="username">Логин</string>
<string name="close">Закрыть</string>
<string name="login">Войти</string>
<string name="password">Пароль</string>
<string name="logout">Выйти</string>
<string name="refresh">Обновить</string>
<string name="scan">Отсканировать</string>

View File

@ -18,4 +18,5 @@ android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.nonTransitiveRClass=true
android.nonFinalResIds=false