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.kts b/app/build.gradle.kts index 6b831bb..805d141 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,7 +4,7 @@ plugins { android { namespace = "com.example.tasktracker" - compileSdk = 35 + compileSdk = 36 defaultConfig { applicationId = "com.example.tasktracker" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 819adcd..a15ba51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,7 +17,9 @@ android:theme="@style/Theme.TaskTracker" android:usesCleartextTraffic="true" tools:targetApi="31"> - + diff --git a/app/src/main/java/com/example/tasktracker/Activities/AddNewTask.java b/app/src/main/java/com/example/tasktracker/Activities/AddNewTask.java index ef52dbb..8fddcda 100644 --- a/app/src/main/java/com/example/tasktracker/Activities/AddNewTask.java +++ b/app/src/main/java/com/example/tasktracker/Activities/AddNewTask.java @@ -1,28 +1,32 @@ package com.example.tasktracker.Activities; +import android.app.DatePickerDialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; +import android.widget.DatePicker; import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; +import com.example.tasktracker.Activities.ViewModels.AddItemViewModel; import com.example.tasktracker.Answers.Task; +import com.example.tasktracker.PublicKeyNames; import com.example.tasktracker.R; import com.example.tasktracker.databinding.ActivityAddNewTaskBinding; import com.google.android.material.snackbar.Snackbar; import java.util.Random; -public class AddNewTask extends AppCompatActivity { +public class AddNewTask extends AppCompatActivity implements DatePickerDialog.OnDateSetListener { private static final String TAG = "ADD_NEW_TASK"; - private static final String TOKEN_KEY = "TOKEN"; private ActivityAddNewTaskBinding binding; private static String token; private AddItemViewModel viewModel; + private String stringDate = ""; @Override protected void onCreate(Bundle savedInstanceState) { @@ -30,13 +34,20 @@ public class AddNewTask extends AppCompatActivity { super.onCreate(savedInstanceState); setContentView(binding.getRoot()); - token = getIntent().getStringExtra(TOKEN_KEY); + token = getIntent().getStringExtra(PublicKeyNames.TOKEN_KEY); if(token == null) { Log.w(TAG, "Token is null"); return; } + + binding.btnDatePick.setOnClickListener(v->{ + DatePickerFragment fragment; + fragment = new DatePickerFragment(); + fragment.show(getSupportFragmentManager(), "DATE PICK"); + }); + viewModel = new ViewModelProvider(this).get(AddItemViewModel.class); viewModel.getClose().observe(this, new Observer() { @Override @@ -60,19 +71,18 @@ public class AddNewTask extends AppCompatActivity { binding.AddTask.setOnClickListener(v->{ String name = binding.TaskName.getText().toString(); String description = binding.TaskDescription.getText().toString(); - String date = getDate(); if(name.isEmpty()) { Snackbar.make(binding.getRoot(), R.string.snackbar_EnterName, Snackbar.LENGTH_SHORT).show(); return; } - if(date.isEmpty()) { + if(stringDate.isEmpty()) { Snackbar.make(binding.getRoot(), R.string.snackbar_EnterDate, Snackbar.LENGTH_SHORT).show(); return; } - long ID = generateID(name, description, date); - Task task = new Task(ID, name, description, date); + long ID = generateID(name, description, stringDate); + Task task = new Task(ID, name, description, stringDate); viewModel.OfflineSaveData(task); }); } @@ -88,7 +98,7 @@ public class AddNewTask extends AppCompatActivity { binding.AddTask.setOnClickListener(v->{ String name = binding.TaskName.getText().toString(); String description = binding.TaskDescription.getText().toString(); - String date = getDate(); + String date = binding.btnDatePick.getText().toString(); if(name.isEmpty()) { Snackbar.make(binding.getRoot(), R.string.snackbar_EnterName, Snackbar.LENGTH_SHORT).show(); @@ -105,16 +115,6 @@ public class AddNewTask extends AppCompatActivity { }); } - private String getDate() { - String day = binding.day.getText().toString(); - String month = binding.month.getText().toString(); - String year = binding.year.getText().toString(); - String minute = binding.minute.getText().toString(); - String hour = binding.hour.getText().toString(); - - return day + '.' + month + '.' + year + ' ' + minute + ':' + hour; - } - private long generateID(String name, String Description, String date) { Random rand = new Random(); @@ -129,7 +129,15 @@ public class AddNewTask extends AppCompatActivity { public static Intent getIntent(Context context, String token) { Intent intent = new Intent(context, AddNewTask.class); - intent.putExtra(TOKEN_KEY, token); + intent.putExtra(PublicKeyNames.TOKEN_KEY, token); return intent; } + + @Override + public void onDateSet(DatePicker datePicker, int year, int month, int day) { + stringDate = Integer.toString(day) + '.' + + Integer.toString(month) + '.' + + Integer.toString(year); + binding.btnDatePick.setText(stringDate); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/tasktracker/Activities/DatePickerFragment.java b/app/src/main/java/com/example/tasktracker/Activities/DatePickerFragment.java new file mode 100644 index 0000000..7ec6c0b --- /dev/null +++ b/app/src/main/java/com/example/tasktracker/Activities/DatePickerFragment.java @@ -0,0 +1,22 @@ +package com.example.tasktracker.Activities; + +import android.app.DatePickerDialog; +import android.app.Dialog; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import java.util.Calendar; + +public class DatePickerFragment extends DialogFragment { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + Calendar mCalendar = Calendar.getInstance(); + int year = mCalendar.get(Calendar.YEAR); + int month = mCalendar.get(Calendar.MONTH); + int dayOfMonth = mCalendar.get(Calendar.DAY_OF_MONTH); + return new DatePickerDialog(getActivity(), (DatePickerDialog.OnDateSetListener) + getActivity(), year, month, dayOfMonth); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/tasktracker/Activities/EditTask.java b/app/src/main/java/com/example/tasktracker/Activities/EditTask.java new file mode 100644 index 0000000..a25322b --- /dev/null +++ b/app/src/main/java/com/example/tasktracker/Activities/EditTask.java @@ -0,0 +1,128 @@ +package com.example.tasktracker.Activities; + +import android.app.DatePickerDialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.widget.DatePicker; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.lifecycle.Observer; + +import com.example.tasktracker.Activities.ViewModels.EditTaskViewModel; +import com.example.tasktracker.Answers.Task; +import com.example.tasktracker.PublicKeyNames; +import com.example.tasktracker.R; +import com.example.tasktracker.databinding.ActivityEditTaskBinding; +import com.google.android.material.snackbar.Snackbar; + +public class EditTask extends AppCompatActivity implements DatePickerDialog.OnDateSetListener { + private static final String TAG = "EDIT_TASK"; + private static final String TASK_ID_KEY = "TASK_ID"; + + private ActivityEditTaskBinding binding; + private EditTaskViewModel viewModel; + private String token; + private long taskID = -1; + private String taskDateString; + + @Override + protected void onCreate(Bundle savedInstanceState) { + viewModel = new EditTaskViewModel(getApplication()); + binding = ActivityEditTaskBinding.inflate(getLayoutInflater()); + super.onCreate(savedInstanceState); + setContentView(binding.getRoot()); + + Intent intent = getIntent(); + taskID = intent.getLongExtra(TASK_ID_KEY, -1); + if(taskID == -1) { + Log.w(TAG, "No task id"); + return; + } + + binding.btnDatePick.setOnClickListener(v->{ // <----- + DatePickerFragment fragment; + fragment = new DatePickerFragment(); + fragment.show(getSupportFragmentManager(), "DATE PICK"); + }); + + viewModel.isLoading().observe(this, new Observer() { + @Override + public void onChanged(Task task) { + binding.TaskName.setText(task.getTaskName()); + binding.TaskDescription.setText(task.getTaskDescription()); + taskDateString = task.getTaskDate(); + binding.btnDatePick.setText(taskDateString); + } + }); + viewModel.getClose().observe(this, new Observer() { + @Override + public void onChanged(Boolean aBoolean) { + if(aBoolean) + finish(); + } + }); + + token = intent.getStringExtra(PublicKeyNames.TOKEN_KEY); + if(token == null) + { + Log.w(TAG, "Token is null"); + return; + } + + // Offline + if(token.equals("null")) { + Offline(); + } + // Online + else { + Online(); + } + } + + private void Offline() { + viewModel.LoadTaskOffline(taskID, this); + binding.btnEditTask.setOnClickListener(v->{ + String name = binding.TaskName.getText().toString(); + String description = binding.TaskDescription.getText().toString(); + + Task task = new Task(taskID, name, description, taskDateString); + viewModel.OfflineSaveData(task); + }); + } + + private void Online() { + binding.btnEditTask.setOnClickListener(v->{ + String name = binding.TaskName.getText().toString(); + String description = binding.TaskDescription.getText().toString(); + + Task task = new Task(taskID, name, description, taskDateString); + viewModel.OnlineSaveData(task, token); + }); + viewModel.getLiveDataFail().observe(this, new Observer() { + @Override + public void onChanged(String s) { + Snackbar.make(binding.getRoot(), R.string.snackbar_InternetError, Snackbar.LENGTH_LONG).show(); + Log.w(TAG, s); + } + }); + + viewModel.LoadTaskOnline(token, taskID); + } + + public static Intent getIntent(Context context, String token, long taskID) { + Intent intent = new Intent(context, EditTask.class); + intent.putExtra(PublicKeyNames.TOKEN_KEY, token); + intent.putExtra(TASK_ID_KEY, taskID); + return intent; + } + + @Override + public void onDateSet(DatePicker datePicker, int year, int month, int day) { + taskDateString = Integer.toString(day) + '.' + + Integer.toString(month) + '.' + + Integer.toString(year); + binding.btnDatePick.setText(taskDateString); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/tasktracker/Activities/LoginActivity.java b/app/src/main/java/com/example/tasktracker/Activities/LoginActivity.java index 9f08c41..d17ed68 100644 --- a/app/src/main/java/com/example/tasktracker/Activities/LoginActivity.java +++ b/app/src/main/java/com/example/tasktracker/Activities/LoginActivity.java @@ -1,7 +1,9 @@ package com.example.tasktracker.Activities; import android.annotation.SuppressLint; +import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; @@ -10,10 +12,13 @@ import androidx.appcompat.app.AppCompatActivity; import com.example.tasktracker.Answers.LoginAnswer; import com.example.tasktracker.Api.ApiFactory; +import com.example.tasktracker.PublicKeyNames; import com.example.tasktracker.R; import com.example.tasktracker.databinding.ActivityLoginBinding; import com.google.android.material.snackbar.Snackbar; +import java.util.Objects; + import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Single; import io.reactivex.rxjava3.disposables.CompositeDisposable; @@ -24,7 +29,12 @@ import io.reactivex.rxjava3.schedulers.Schedulers; public class LoginActivity extends AppCompatActivity { private static final String TAG = "LOGIN_ACTIVITY"; private ActivityLoginBinding binding; - private CompositeDisposable compositeDisposable = new CompositeDisposable(); + private SharedPreferences sharedPreferences; + private final CompositeDisposable compositeDisposable = new CompositeDisposable(); + + public static Intent getIntent(Context context) { + return new Intent(context, LoginActivity.class); + } @SuppressLint("UnsafeIntentLaunch") @Override @@ -34,6 +44,33 @@ public class LoginActivity extends AppCompatActivity { EdgeToEdge.enable(this); setContentView(binding.getRoot()); + sharedPreferences = getSharedPreferences(PublicKeyNames.TOKEN_LIST, MODE_PRIVATE); + String token = sharedPreferences.getString(PublicKeyNames.TOKEN_KEY, ""); + if(!token.isEmpty()) + { + Disposable disposable = ApiFactory.getApiService() + .checkToken(token) + .observeOn(Schedulers.io()).subscribe(new Consumer() { + @Override + public void accept(LoginAnswer loginAnswer) throws Throwable { + if(loginAnswer.getStatus().equals("ok")) { + Intent intent = MainMenu.getIntent(LoginActivity.this, token); + startActivity(intent); + finish(); + } else { + sharedPreferences.edit().putString(PublicKeyNames.TOKEN_KEY, "").apply(); + } + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Throwable { + Snackbar.make(binding.getRoot(), R.string.snackbar_InternetError, Snackbar.LENGTH_LONG).show(); + Log.e(TAG, Objects.requireNonNull(throwable.getMessage())); + } + }); + compositeDisposable.add(disposable); + } + binding.buttonSingIn.setOnClickListener(v->{ SingIn(); }); binding.buttonSingUp.setOnClickListener(v->{ SingUp(); }); @@ -74,6 +111,7 @@ public class LoginActivity extends AppCompatActivity { } String token = loginAnswer.getToken(); + sharedPreferences.edit().putString(PublicKeyNames.TOKEN_KEY, token).apply(); OpenMainMenu(token); } }, new Consumer() { @@ -115,6 +153,7 @@ public class LoginActivity extends AppCompatActivity { } String token = loginAnswer.getToken(); + sharedPreferences.edit().putString(PublicKeyNames.TOKEN_KEY, token).apply(); OpenMainMenu(token); } }, new Consumer() { @@ -127,6 +166,12 @@ public class LoginActivity extends AppCompatActivity { compositeDisposable.add(disposable); } + @Override + protected void onDestroy() { + super.onDestroy(); + compositeDisposable.dispose(); + } + private void OpenMainMenu(String token) { @SuppressLint("UnsafeIntentLaunch") diff --git a/app/src/main/java/com/example/tasktracker/Activities/MainMenu.java b/app/src/main/java/com/example/tasktracker/Activities/MainMenu.java index 996cf39..f601f11 100644 --- a/app/src/main/java/com/example/tasktracker/Activities/MainMenu.java +++ b/app/src/main/java/com/example/tasktracker/Activities/MainMenu.java @@ -1,7 +1,9 @@ package com.example.tasktracker.Activities; +import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.text.Editable; @@ -15,15 +17,16 @@ import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; +import com.example.tasktracker.Activities.ViewModels.MainMenuViewModel; import com.example.tasktracker.Answers.Task; import com.example.tasktracker.Api.ApiFactory; import com.example.tasktracker.Api.TaskRepository; +import com.example.tasktracker.PublicKeyNames; import com.example.tasktracker.R; import com.example.tasktracker.databinding.ActivityMainMenuBinding; import com.google.android.material.snackbar.Snackbar; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; import java.util.Objects; @@ -33,14 +36,12 @@ import retrofit2.Response; public class MainMenu extends AppCompatActivity { private static final String TAG = "MainMenu"; - private static final String TOKEN_KEY = "TOKEN"; private ActivityMainMenuBinding binding; private String token; private TaskAdapter taskAdapter; private MainMenuViewModel viewModel; - - private List taskListCache; + private List taskListCache = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { @@ -48,19 +49,27 @@ public class MainMenu extends AppCompatActivity { binding = ActivityMainMenuBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); - token = getIntent().getStringExtra(TOKEN_KEY); - if(token == null) - { + token = getIntent().getStringExtra(PublicKeyNames.TOKEN_KEY); + if (token == null) { Log.e(TAG, "Token is empty"); return; } taskAdapter = new TaskAdapter(); binding.scrollTask.setAdapter(taskAdapter); - binding.buttonAddNewTask.setOnClickListener(v->{ + binding.buttonAddNewTask.setOnClickListener(v -> { Intent intent = AddNewTask.getIntent(this, token); startActivity(intent); }); + taskAdapter.setOnItemClick(new TaskAdapter.OnItemClick() { + @Override + public void Click(int position) { + Task task = taskAdapter.getTaskList().get(position); + @SuppressLint("UnsafeIntentLaunch") + Intent intent = EditTask.getIntent(MainMenu.this, token, task.getID()); + startActivity(intent); + } + }); viewModel = new ViewModelProvider(this).get(MainMenuViewModel.class); binding.findLine.addTextChangedListener(new TextWatcher() { @@ -72,8 +81,8 @@ public class MainMenu extends AppCompatActivity { @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { String find = binding.findLine.getText().toString(); - if(find.isEmpty()) { - if(token.equals("null")) { + if (find.isEmpty()) { + if (token.equals("null")) { TaskRepository.newInstance(getApplication()).taskDao().getTaskList().observe(MainMenu.this, new Observer>() { @Override public void onChanged(List tasks) { @@ -81,8 +90,7 @@ public class MainMenu extends AppCompatActivity { taskAdapter.setTaskList(tasks); } }); - } - else { + } else { viewModel.OnlineUpdateList(token); } } @@ -112,121 +120,138 @@ public class MainMenu extends AppCompatActivity { } }); - // offline - if(token.equals("null")) { - Offline(); + binding.buttonSingOut.setOnClickListener(v -> { + getSharedPreferences(PublicKeyNames.TOKEN_LIST, MODE_PRIVATE). + edit(). + remove(PublicKeyNames.TOKEN_KEY). + apply(); + + @SuppressLint("UnsafeIntentLaunch") + Intent intent = LoginActivity.getIntent(MainMenu.this); + startActivity(intent); + finish(); + }); + + // offline + if (token.equals("null")) { + Offline(); + } + //online + else { + Online(); + } } - //online - else { - Online(); - } - } - public void Offline() { - viewModel.getOnLoad().observe(this, new Observer>() { - @Override - public void onChanged(List tasks) { - taskListCache = tasks; - taskAdapter.setTaskList(tasks); - } - }); - - ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, - ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { - @Override - public boolean onMove(@NonNull RecyclerView recyclerView, - @NonNull RecyclerView.ViewHolder viewHolder, - @NonNull RecyclerView.ViewHolder target) { - return false; - } - - @Override - public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { - int position = viewHolder.getAdapterPosition(); - - Task task = taskAdapter.getItem(position); - new Thread(new Runnable() { - @Override - public void run() { - TaskRepository.newInstance(getApplication()).taskDao().delete(task); - } - }).start(); - taskAdapter.removeItemByPosition(position); - } - }); - helper.attachToRecyclerView(binding.scrollTask); - } - - private void Online() { - - viewModel.getOnLoad().observe(this, new Observer>() { - @Override - public void onChanged(List tasks) { - taskListCache = tasks; - taskAdapter.setTaskList(tasks); - } - }); - viewModel.onFail().observe(this, new Observer() { - @Override - public void onChanged(String s) { - Snackbar.make(binding.getRoot(), R.string.snackbar_InternetError, Snackbar.LENGTH_LONG).show(); - Log.w(TAG, s); - } - }); - - ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, - ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { - @Override - public boolean onMove(@NonNull RecyclerView recyclerView, - @NonNull RecyclerView.ViewHolder viewHolder, - @NonNull RecyclerView.ViewHolder target) { - return false; - } - - @Override - public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { - int position = viewHolder.getAdapterPosition(); - - Task task = taskAdapter.getItem(position); - ApiFactory.getApiService().removeTask(token, task.getID()).enqueue(new Callback() { - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) { - Task task = taskAdapter.getItem(position); - taskAdapter.removeItemByPosition(position); - } - - @Override - public void onFailure(@NonNull Call call, @NonNull Throwable throwable) { - Snackbar.make(binding.getRoot(), R.string.snackbar_InternetError, Snackbar.LENGTH_LONG).show(); - Log.w(TAG, Objects.requireNonNull(throwable.getMessage())); - } - }); - } - }); - helper.attachToRecyclerView(binding.scrollTask); - } - - @Override - protected void onResume() { - super.onResume(); - if(token.equals("null")) { - TaskRepository.newInstance(getApplication()).taskDao().getTaskList().observe(this, new Observer>() { + public void Offline () { + viewModel.getOnLoad().observe(this, new Observer>() { @Override public void onChanged(List tasks) { taskListCache = tasks; taskAdapter.setTaskList(tasks); } }); - } - else { - viewModel.OnlineUpdateList(token); - } - } - public static Intent getIntent(Context context, String token) { - Intent intent = new Intent(context, MainMenu.class); - intent.putExtra(TOKEN_KEY, token); - return intent; - } + ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, + ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder, + @NonNull RecyclerView.ViewHolder target) { + return false; + } -} \ No newline at end of file + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + int position = viewHolder.getAdapterPosition(); + + Task task = taskAdapter.getItem(position); + new Thread(new Runnable() { + @Override + public void run() { + TaskRepository.newInstance(getApplication()).taskDao().delete(task); + for (int i = 0; i < taskListCache.size(); ++i) { + if (taskListCache.get(i).getID() == task.getID()) { + taskListCache.remove(i); + break; + } + } + } + }).start(); + taskAdapter.removeItemByPosition(position); + } + }); + helper.attachToRecyclerView(binding.scrollTask); + } + + private void Online () { + + viewModel.getOnLoad().observe(this, new Observer>() { + @Override + public void onChanged(List tasks) { + taskListCache = tasks; + taskAdapter.setTaskList(tasks); + } + }); + viewModel.onFail().observe(this, new Observer() { + @Override + public void onChanged(String s) { + Snackbar.make(binding.getRoot(), R.string.snackbar_InternetError, Snackbar.LENGTH_LONG).show(); + Log.w(TAG, s); + } + }); + + ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, + ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder, + @NonNull RecyclerView.ViewHolder target) { + return false; + } + + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + int position = viewHolder.getAdapterPosition(); + + Task task = taskAdapter.getItem(position); + ApiFactory.getApiService().removeTask(token, task.getID()).enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + Task task = taskAdapter.getItem(position); + taskAdapter.removeItemByPosition(position); + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable throwable) { + Snackbar.make(binding.getRoot(), R.string.snackbar_InternetError, Snackbar.LENGTH_LONG).show(); + Log.w(TAG, Objects.requireNonNull(throwable.getMessage())); + } + }); + } + }); + helper.attachToRecyclerView(binding.scrollTask); + } + + @Override + protected void onResume () { + super.onResume(); + if (token.equals("null")) { + TaskRepository.newInstance(getApplication()).taskDao().getTaskList().observe(this, new Observer>() { + @Override + public void onChanged(List tasks) { + taskListCache = tasks; + taskAdapter.setTaskList(tasks); + } + }); + } else { + viewModel.OnlineUpdateList(token); + } + } + + public static Intent getIntent (Context context, String token){ + Intent intent = new Intent(context, MainMenu.class); + intent.putExtra(PublicKeyNames.TOKEN_KEY, token); + return intent; + } + + } \ No newline at end of file diff --git a/app/src/main/java/com/example/tasktracker/Activities/AddItemViewModel.java b/app/src/main/java/com/example/tasktracker/Activities/ViewModels/AddItemViewModel.java similarity index 92% rename from app/src/main/java/com/example/tasktracker/Activities/AddItemViewModel.java rename to app/src/main/java/com/example/tasktracker/Activities/ViewModels/AddItemViewModel.java index d48a1f3..e478f90 100644 --- a/app/src/main/java/com/example/tasktracker/Activities/AddItemViewModel.java +++ b/app/src/main/java/com/example/tasktracker/Activities/ViewModels/AddItemViewModel.java @@ -1,4 +1,4 @@ -package com.example.tasktracker.Activities; +package com.example.tasktracker.Activities.ViewModels; import android.app.Application; import android.util.Log; @@ -7,7 +7,6 @@ import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.Observer; import com.example.tasktracker.Answers.Task; import com.example.tasktracker.Api.ApiFactory; @@ -38,7 +37,7 @@ public class AddItemViewModel extends AndroidViewModel { public void OnlineSaveData(Task task, String token) { - Call send = ApiFactory.getApiService().addTask(token, task); + Call send = ApiFactory.getApiService().editTask(token, task); send.enqueue(new Callback() { @Override public void onResponse(@NonNull Call call, @NonNull Response response) { diff --git a/app/src/main/java/com/example/tasktracker/Activities/ViewModels/EditTaskViewModel.java b/app/src/main/java/com/example/tasktracker/Activities/ViewModels/EditTaskViewModel.java new file mode 100644 index 0000000..662f53c --- /dev/null +++ b/app/src/main/java/com/example/tasktracker/Activities/ViewModels/EditTaskViewModel.java @@ -0,0 +1,106 @@ +package com.example.tasktracker.Activities.ViewModels; + +import android.app.Application; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Observer; + +import com.example.tasktracker.Activities.EditTask; +import com.example.tasktracker.Answers.Task; +import com.example.tasktracker.Api.ApiFactory; +import com.example.tasktracker.Api.TaskDao; +import com.example.tasktracker.Api.TaskRepository; + +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.functions.Consumer; +import io.reactivex.rxjava3.schedulers.Schedulers; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public class EditTaskViewModel extends AndroidViewModel { + private static final String TAG = "EDIT_ITEM_VIEW_MODEL"; + + private final CompositeDisposable compositeDisposable = new CompositeDisposable(); + private final MutableLiveData liveDataSave = new MutableLiveData<>(); + private final MutableLiveData liveDataFail = new MutableLiveData<>(); + private final MutableLiveData liveDataLoad = new MutableLiveData<>(); + + public EditTaskViewModel(@NonNull Application application) { + super(application); + } + + public void OfflineSaveData(Task task) { + new Thread(new Runnable() { + @Override + public void run() { + TaskRepository.newInstance(getApplication()).taskDao().addTask(task); + liveDataSave.postValue(true); + } + }).start(); + } + + public void OnlineSaveData(Task task, String token) { + + Call send = ApiFactory.getApiService().editTask(token, task); + send.enqueue(new Callback() { + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + Log.d(TAG, "Task update successfully"); + liveDataSave.postValue(true); + } + + @Override + public void onFailure(@NonNull Call call, @NonNull Throwable throwable) { + Log.w(TAG, throwable.toString()); + liveDataFail.postValue(throwable.getMessage()); + } + }); + } + + public void LoadTaskOffline(long taskID, EditTask owner) { + TaskRepository.newInstance(getApplication()).taskDao().getTask(taskID).observe(owner, new Observer() { + @Override + public void onChanged(Task task) { + liveDataLoad.postValue(task); + } + }); + } + + public void LoadTaskOnline(String token, long taskID) { + Disposable disposable = ApiFactory.getApiService().getTask(token, taskID) + .subscribeOn(Schedulers.io()).subscribe(new Consumer() { + @Override + public void accept(Task task) throws Throwable { + liveDataLoad.postValue(task); + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Throwable { + liveDataFail.postValue(throwable.getMessage()); + } + }); + compositeDisposable.add(disposable); + } + + @Override + protected void onCleared() { + super.onCleared(); + compositeDisposable.dispose(); + } + + public LiveData isLoading() { + return liveDataLoad; + } + public LiveData getLiveDataFail() { + return liveDataFail; + } + public LiveData getClose() { + return liveDataSave; + } +} diff --git a/app/src/main/java/com/example/tasktracker/Activities/MainMenuViewModel.java b/app/src/main/java/com/example/tasktracker/Activities/ViewModels/MainMenuViewModel.java similarity index 93% rename from app/src/main/java/com/example/tasktracker/Activities/MainMenuViewModel.java rename to app/src/main/java/com/example/tasktracker/Activities/ViewModels/MainMenuViewModel.java index 0057f85..9a34039 100644 --- a/app/src/main/java/com/example/tasktracker/Activities/MainMenuViewModel.java +++ b/app/src/main/java/com/example/tasktracker/Activities/ViewModels/MainMenuViewModel.java @@ -1,4 +1,4 @@ -package com.example.tasktracker.Activities; +package com.example.tasktracker.Activities.ViewModels; import android.app.Application; @@ -6,11 +6,9 @@ import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.Observer; import com.example.tasktracker.Answers.Task; import com.example.tasktracker.Api.ApiFactory; -import com.example.tasktracker.Api.TaskRepository; import java.util.ArrayList; import java.util.List; diff --git a/app/src/main/java/com/example/tasktracker/Answers/Task.java b/app/src/main/java/com/example/tasktracker/Answers/Task.java index aad0b36..be003a9 100644 --- a/app/src/main/java/com/example/tasktracker/Answers/Task.java +++ b/app/src/main/java/com/example/tasktracker/Answers/Task.java @@ -30,10 +30,10 @@ public class Task implements Serializable { } @Ignore - public Task(long ID, String TaskName, String TaskDescription, String TaskData) { + public Task(long ID, String TaskName, String TaskDescription, String TaskDate) { this.TaskName = TaskName; this.TaskDescription = TaskDescription; - this.TaskDate = TaskData; + this.TaskDate = TaskDate; this.ID = ID; } diff --git a/app/src/main/java/com/example/tasktracker/Api/ApiService.java b/app/src/main/java/com/example/tasktracker/Api/ApiService.java index 21fcc55..f3cb0d4 100644 --- a/app/src/main/java/com/example/tasktracker/Api/ApiService.java +++ b/app/src/main/java/com/example/tasktracker/Api/ApiService.java @@ -13,6 +13,9 @@ import retrofit2.http.POST; import retrofit2.http.Query; public interface ApiService { + @GET("user") + Single checkToken(@Query("token") String token); + @GET("singin") Single singin(@Query("login") String login, @Query("password") String password); @@ -20,10 +23,13 @@ public interface ApiService { Single singup(@Query("login") String login, @Query("password") String password); @GET("user/task") + Single getTask(@Query("token") String token, @Query("id") long id); + + @GET("user/task/list") Single> getTaskList(@Query("token") String token); - @POST("user/task/add") - Call addTask(@Query("token") String token, @Body Task task); + @POST("user/task/edit") + Call editTask(@Query("token") String token, @Body Task task); @POST("user/task/remove") Call removeTask(@Query("token") String token, @Query("id") long ID); diff --git a/app/src/main/java/com/example/tasktracker/Api/TaskDao.java b/app/src/main/java/com/example/tasktracker/Api/TaskDao.java index 80401e4..df66dee 100644 --- a/app/src/main/java/com/example/tasktracker/Api/TaskDao.java +++ b/app/src/main/java/com/example/tasktracker/Api/TaskDao.java @@ -18,6 +18,9 @@ public interface TaskDao { @Query("SELECT * FROM task_room") LiveData> getTaskList(); + @Query("SELECT * FROM task_room ORDER BY (:id)") + LiveData getTask(long id); + @Query("DELETE FROM task_room") void DropTable(); diff --git a/app/src/main/java/com/example/tasktracker/PublicKeyNames.java b/app/src/main/java/com/example/tasktracker/PublicKeyNames.java new file mode 100644 index 0000000..b23e743 --- /dev/null +++ b/app/src/main/java/com/example/tasktracker/PublicKeyNames.java @@ -0,0 +1,6 @@ +package com.example.tasktracker; + +public abstract class PublicKeyNames { + public static final String TOKEN_LIST = "token_list"; + public static final String TOKEN_KEY = "TOKEN"; +} diff --git a/app/src/main/res/drawable/add.png b/app/src/main/res/drawable/add.png new file mode 100644 index 0000000..3d0b46f Binary files /dev/null and b/app/src/main/res/drawable/add.png differ diff --git a/app/src/main/res/drawable/exit.png b/app/src/main/res/drawable/exit.png new file mode 100644 index 0000000..a7cb39c Binary files /dev/null and b/app/src/main/res/drawable/exit.png differ diff --git a/app/src/main/res/layout/activity_add_new_task.xml b/app/src/main/res/layout/activity_add_new_task.xml index 24547b9..98ef167 100644 --- a/app/src/main/res/layout/activity_add_new_task.xml +++ b/app/src/main/res/layout/activity_add_new_task.xml @@ -21,56 +21,17 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textMultiLine"/> - - - - - - - + android:layout_margin="5sp"/>