forked from github/wulkanowy-mirror
Implementing Pull to Refresh (#28)
* Add swipe refresh layout * Remove indicator and change border position * Add snackbar for new grades and rename classes of synchronization * Add info of the number of grades * Add grades average average * Add alert of new grades * Fix crash while refreshing * Add disappearing alerts * Optimize res and fix crash * Update API to version 27
This commit is contained in:
parent
fe54fa71f3
commit
f6e29490c3
@ -4,13 +4,13 @@ apply plugin: "io.github.ddimtirov.codacy"
|
||||
apply plugin: 'org.greenrobot.greendao'
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion "26.0.1"
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.0"
|
||||
defaultConfig {
|
||||
applicationId "io.github.wulkanowy"
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 26
|
||||
targetSdkVersion 27
|
||||
versionCode 1
|
||||
versionName "0.1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
@ -39,21 +39,19 @@ android {
|
||||
}
|
||||
|
||||
greendao {
|
||||
schemaVersion 10
|
||||
schemaVersion 13
|
||||
generateTests = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
|
||||
compile 'com.android.support:appcompat-v7:26.0.1'
|
||||
compile 'com.android.support:appcompat-v7:27.0.0'
|
||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
compile 'com.android.support:design:26.0.1'
|
||||
compile 'com.android.support:support-vector-drawable:26.0.1'
|
||||
compile 'com.android.support:support-v4:26.0.1'
|
||||
compile 'com.android.support:recyclerview-v7:26.0.1'
|
||||
compile 'com.android.support:cardview-v7:26.0.1'
|
||||
compile 'com.firebase:firebase-jobdispatcher:0.8.1'
|
||||
compile 'com.android.support:design:27.0.0'
|
||||
compile 'com.android.support:support-vector-drawable:27.0.0'
|
||||
compile 'com.android.support:support-v4:27.0.0'
|
||||
compile 'com.android.support:recyclerview-v7:27.0.0'
|
||||
compile 'com.android.support:cardview-v7:27.0.0'
|
||||
compile 'com.firebase:firebase-jobdispatcher:0.8.4'
|
||||
compile 'com.thoughtbot:expandablerecyclerview:1.3'
|
||||
compile 'org.apache.commons:commons-lang3:3.6'
|
||||
compile 'org.apache.commons:commons-collections4:4.1'
|
||||
@ -71,7 +69,7 @@ dependencies {
|
||||
androidTestCompile('com.android.support.test.espresso:espresso-core:3.0.1', {
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
})
|
||||
androidTestCompile 'com.android.support:support-annotations:26.0.1'
|
||||
androidTestCompile 'com.android.support:support-annotations:27.0.0'
|
||||
androidTestCompile 'com.android.support.test:runner:1.0.1'
|
||||
androidTestCompile 'com.android.support.test:rules:1.0.1'
|
||||
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
|
||||
|
@ -0,0 +1,50 @@
|
||||
package io.github.wulkanowy.dao;
|
||||
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
|
||||
import org.greenrobot.greendao.database.Database;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import io.github.wulkanowy.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.dao.entities.Grade;
|
||||
|
||||
public class DatabaseAccessTest extends DatabaseAccess {
|
||||
|
||||
private static DaoSession daoSession;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(InstrumentationRegistry.getTargetContext()
|
||||
, "wulkanowyTest-database");
|
||||
Database database = devOpenHelper.getWritableDb();
|
||||
|
||||
daoSession = new DaoMaster(database).newSession();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
daoSession.getGradeDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNewGradesTest() {
|
||||
daoSession.getGradeDao().insert(new Grade()
|
||||
.setIsNew(true));
|
||||
|
||||
Assert.assertEquals(1, DatabaseAccess.getNewGrades(daoSession).size());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() {
|
||||
daoSession.getAccountDao().deleteAll();
|
||||
daoSession.getGradeDao().deleteAll();
|
||||
daoSession.getSubjectDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@
|
||||
android:label="@string/activity_dashboard_text" />
|
||||
|
||||
<service
|
||||
android:name=".services.jobs.GradesSync$GradeJob"
|
||||
android:name=".services.jobs.GradeJob$GradeService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
|
||||
|
@ -3,12 +3,9 @@ package io.github.wulkanowy.activity.dashboard.grades;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.RotateAnimation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -21,16 +18,17 @@ import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.dao.entities.Grade;
|
||||
|
||||
import static android.view.animation.Animation.RELATIVE_TO_SELF;
|
||||
import io.github.wulkanowy.utilities.AverageCalculator;
|
||||
|
||||
public class GradesAdapter extends ExpandableRecyclerViewAdapter<GradesAdapter.SubjectViewHolder, GradesAdapter.GradeViewHolder> {
|
||||
|
||||
private Activity activity;
|
||||
|
||||
public GradesAdapter(List<? extends ExpandableGroup> groups, Context context) {
|
||||
private int numberOfNotReadGrade;
|
||||
|
||||
public GradesAdapter(List<? extends ExpandableGroup> groups, Activity activity) {
|
||||
super(groups);
|
||||
activity = (Activity) context;
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -59,80 +57,42 @@ public class GradesAdapter extends ExpandableRecyclerViewAdapter<GradesAdapter.S
|
||||
|
||||
private TextView subjectName;
|
||||
|
||||
private ImageView indicatorDown;
|
||||
private TextView numberOfGrades;
|
||||
|
||||
private ImageView indicatorUp;
|
||||
private TextView averageGrades;
|
||||
|
||||
private ImageView subjectAlertNewGrades;
|
||||
|
||||
public SubjectViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
subjectName = itemView.findViewById(R.id.subject_text);
|
||||
indicatorDown = itemView.findViewById(R.id.group_indicator_down);
|
||||
indicatorUp = itemView.findViewById(R.id.group_indicator_up);
|
||||
numberOfGrades = itemView.findViewById(R.id.subject_number_of_grades);
|
||||
subjectAlertNewGrades = itemView.findViewById(R.id.subject_new_grades_alert);
|
||||
averageGrades = itemView.findViewById(R.id.subject_grades_average);
|
||||
|
||||
subjectAlertNewGrades.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
public void bind(ExpandableGroup group) {
|
||||
subjectName.setText(group.getTitle());
|
||||
int volumeGrades = group.getItemCount();
|
||||
List<Grade> gradeList = group.getItems();
|
||||
float average = AverageCalculator.calculate(gradeList);
|
||||
|
||||
if (isGroupExpanded(group)) {
|
||||
indicatorDown.setVisibility(View.INVISIBLE);
|
||||
indicatorUp.setVisibility(View.VISIBLE);
|
||||
itemView.setTag(group.getTitle());
|
||||
|
||||
if (average < 0) {
|
||||
averageGrades.setText(R.string.info_no_average);
|
||||
} else {
|
||||
indicatorDown.setVisibility(View.VISIBLE);
|
||||
indicatorUp.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
averageGrades.setText(activity.getResources().getString(R.string.info_average_grades, average));
|
||||
}
|
||||
subjectName.setText(group.getTitle());
|
||||
numberOfGrades.setText(activity.getResources().getQuantityString(R.plurals.numberOfGrades, volumeGrades, volumeGrades));
|
||||
|
||||
@Override
|
||||
public void expand() {
|
||||
RotateAnimation rotate =
|
||||
new RotateAnimation(-360, -180, RELATIVE_TO_SELF, 0.5f, RELATIVE_TO_SELF, 0.5f);
|
||||
rotate.setDuration(300);
|
||||
rotate.setFillAfter(false);
|
||||
rotate.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
//Empty method definition
|
||||
for (Grade grade : gradeList) {
|
||||
if (!grade.getRead()) {
|
||||
subjectAlertNewGrades.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
indicatorDown.setVisibility(View.INVISIBLE);
|
||||
indicatorUp.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
//Empty method definition
|
||||
}
|
||||
});
|
||||
indicatorDown.setAnimation(rotate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collapse() {
|
||||
RotateAnimation rotate =
|
||||
new RotateAnimation(360, 180, RELATIVE_TO_SELF, 0.5f, RELATIVE_TO_SELF, 0.5f);
|
||||
rotate.setDuration(300);
|
||||
rotate.setFillAfter(false);
|
||||
rotate.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
//Empty method definition
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
indicatorDown.setVisibility(View.VISIBLE);
|
||||
indicatorUp.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
//Empty method definition
|
||||
}
|
||||
});
|
||||
indicatorUp.setAnimation(rotate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,32 +104,29 @@ public class GradesAdapter extends ExpandableRecyclerViewAdapter<GradesAdapter.S
|
||||
|
||||
private TextView dateGrade;
|
||||
|
||||
private Grade grade;
|
||||
private ImageView alertNewGrade;
|
||||
|
||||
public GradeViewHolder(final View itemView) {
|
||||
private View itemView;
|
||||
|
||||
private Grade gradeItem;
|
||||
|
||||
public GradeViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
this.itemView = itemView;
|
||||
gradeValue = itemView.findViewById(R.id.grade_text);
|
||||
descriptionGrade = itemView.findViewById(R.id.description_grade_text);
|
||||
dateGrade = itemView.findViewById(R.id.grade_date_text);
|
||||
|
||||
itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
GradesDialogFragment gradesDialogFragment = GradesDialogFragment.newInstance(grade);
|
||||
gradesDialogFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0);
|
||||
gradesDialogFragment.show(activity.getFragmentManager(), grade.toString());
|
||||
}
|
||||
});
|
||||
alertNewGrade = itemView.findViewById(R.id.grade_new_grades_alert);
|
||||
}
|
||||
|
||||
public void bind(Grade grade) {
|
||||
this.grade = grade;
|
||||
gradeValue.setText(grade.getValue());
|
||||
gradeValue.setBackgroundResource(grade.getValueColor());
|
||||
dateGrade.setText(grade.getDate());
|
||||
gradeItem = grade;
|
||||
|
||||
if (grade.getDescription().equals("") || grade.getDescription() == null) {
|
||||
if (!grade.getSymbol().equals("")) {
|
||||
if (grade.getDescription() == null || "".equals(grade.getDescription())) {
|
||||
if (!"".equals(grade.getSymbol())) {
|
||||
descriptionGrade.setText(grade.getSymbol());
|
||||
} else {
|
||||
descriptionGrade.setText(R.string.noDescription_text);
|
||||
@ -178,6 +135,37 @@ public class GradesAdapter extends ExpandableRecyclerViewAdapter<GradesAdapter.S
|
||||
descriptionGrade.setText(grade.getDescription());
|
||||
}
|
||||
|
||||
if (gradeItem.getRead()) {
|
||||
alertNewGrade.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
alertNewGrade.setVisibility(View.VISIBLE);
|
||||
numberOfNotReadGrade++;
|
||||
}
|
||||
|
||||
itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
GradesDialogFragment gradesDialogFragment = GradesDialogFragment.newInstance(gradeItem);
|
||||
gradesDialogFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0);
|
||||
gradesDialogFragment.show(activity.getFragmentManager(), gradeItem.toString());
|
||||
|
||||
if (!gradeItem.getRead()) {
|
||||
numberOfNotReadGrade--;
|
||||
}
|
||||
|
||||
if (numberOfNotReadGrade == 0) {
|
||||
View subjectView = activity.findViewById(R.id.subject_grade_recycler).findViewWithTag(gradeItem.getSubject());
|
||||
View subjectAlertNewGrade = subjectView.findViewById(R.id.subject_new_grades_alert);
|
||||
subjectAlertNewGrade.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
gradeItem.setRead(true);
|
||||
gradeItem.setIsNew(false);
|
||||
gradeItem.update();
|
||||
alertNewGrade.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,70 +3,99 @@ package io.github.wulkanowy.activity.dashboard.grades;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.activity.WulkanowyApp;
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.dao.DatabaseAccess;
|
||||
import io.github.wulkanowy.dao.entities.Account;
|
||||
import io.github.wulkanowy.dao.entities.AccountDao;
|
||||
import io.github.wulkanowy.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.dao.entities.Grade;
|
||||
import io.github.wulkanowy.dao.entities.Subject;
|
||||
import io.github.wulkanowy.services.LoginSession;
|
||||
import io.github.wulkanowy.services.VulcanSynchronization;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.utilities.ConnectionUtilities;
|
||||
|
||||
public class GradesFragment extends Fragment {
|
||||
|
||||
private List<SubjectWithGrades> subjectWithGradesList = new ArrayList<>();
|
||||
|
||||
private SwipeRefreshLayout swipeRefreshLayout;
|
||||
|
||||
private View view;
|
||||
|
||||
private RefreshTask refreshTask;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
view = inflater.inflate(R.layout.fragment_grades, container, false);
|
||||
|
||||
DaoSession daoSession = ((WulkanowyApp) getActivity().getApplication()).getDaoSession();
|
||||
swipeRefreshLayout = view.findViewById(R.id.grade_swipe_refresh);
|
||||
swipeRefreshLayout.setColorSchemeResources(android.R.color.black,
|
||||
android.R.color.holo_blue_bright,
|
||||
android.R.color.holo_green_light,
|
||||
android.R.color.holo_orange_light,
|
||||
android.R.color.holo_red_light);
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
if (!ConnectionUtilities.isOnline(view.getContext())) {
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
Toast.makeText(view.getContext(), R.string.noInternet_text, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
refreshTask = new RefreshTask();
|
||||
refreshTask.execute(((WulkanowyApp) getActivity().getApplication()).getDaoSession());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (new ArrayList<>().equals(subjectWithGradesList)) {
|
||||
createExpListView();
|
||||
new GradesTask(daoSession).execute();
|
||||
new GradesTask().execute(((WulkanowyApp) getActivity().getApplication()).getDaoSession());
|
||||
} else if (subjectWithGradesList.size() > 0) {
|
||||
createExpListView();
|
||||
view.findViewById(R.id.loadingPanel).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (refreshTask != null && refreshTask.getStatus() == AsyncTask.Status.RUNNING) {
|
||||
refreshTask.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void createExpListView() {
|
||||
|
||||
RecyclerView recyclerView = view.findViewById(R.id.subject_grade_recycler);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
|
||||
GradesAdapter gradesAdapter = new GradesAdapter(subjectWithGradesList, view.getContext());
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
GradesAdapter gradesAdapter = new GradesAdapter(subjectWithGradesList, getActivity());
|
||||
recyclerView.setAdapter(gradesAdapter);
|
||||
|
||||
}
|
||||
|
||||
private class GradesTask extends AsyncTask<Void, Void, Void> {
|
||||
private void prepareSubjectsWithGradesList(DaoSession daoSession) {
|
||||
subjectWithGradesList = new ArrayList<>();
|
||||
|
||||
private DaoSession daoSession;
|
||||
|
||||
GradesTask(DaoSession daoSession) {
|
||||
this.daoSession = daoSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
|
||||
long userId = getActivity().getSharedPreferences("LoginData", Context.MODE_PRIVATE)
|
||||
long userId = getContext().getSharedPreferences("LoginData", Context.MODE_PRIVATE)
|
||||
.getLong("userId", 0);
|
||||
|
||||
AccountDao accountDao = daoSession.getAccountDao();
|
||||
@ -79,6 +108,13 @@ public class GradesFragment extends Fragment {
|
||||
subjectWithGradesList.add(subjectWithGrades);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class GradesTask extends AsyncTask<DaoSession, Void, Void> {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(DaoSession... params) {
|
||||
prepareSubjectsWithGradesList(params[0]);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -86,8 +122,51 @@ public class GradesFragment extends Fragment {
|
||||
super.onPostExecute(result);
|
||||
|
||||
createExpListView();
|
||||
|
||||
view.findViewById(R.id.loadingPanel).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private class RefreshTask extends AsyncTask<DaoSession, Void, Boolean> {
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(DaoSession... params) {
|
||||
VulcanSynchronization vulcanSynchronization = new VulcanSynchronization(new LoginSession());
|
||||
try {
|
||||
vulcanSynchronization.loginCurrentUser(getContext(), params[0], new Vulcan());
|
||||
vulcanSynchronization.syncGrades();
|
||||
prepareSubjectsWithGradesList(params[0]);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "There was a synchronization problem", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
super.onPostExecute(result);
|
||||
|
||||
if (result) {
|
||||
prepareSubjectsWithGradesList(((WulkanowyApp) getActivity().getApplication()).getDaoSession());
|
||||
createExpListView();
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
|
||||
|
||||
int volumeGrades = DatabaseAccess.getNewGrades(((WulkanowyApp) getActivity().getApplication()).getDaoSession()).size();
|
||||
|
||||
if (volumeGrades == 0) {
|
||||
Snackbar.make(getActivity().findViewById(R.id.fragment_container),
|
||||
R.string.snackbar_no_grades,
|
||||
Snackbar.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Snackbar.make(getActivity().findViewById(R.id.fragment_container),
|
||||
getString(R.string.snackbar_new_grade, volumeGrades),
|
||||
Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(getContext(), R.string.refresh_error_text, Toast.LENGTH_SHORT).show();
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import io.github.wulkanowy.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.security.CryptoException;
|
||||
import io.github.wulkanowy.services.LoginSession;
|
||||
import io.github.wulkanowy.services.VulcanSynchronization;
|
||||
import io.github.wulkanowy.services.jobs.GradesSync;
|
||||
import io.github.wulkanowy.services.jobs.GradeJob;
|
||||
import io.github.wulkanowy.utilities.ConnectionUtilities;
|
||||
|
||||
public class LoginTask extends AsyncTask<String, Integer, Integer> {
|
||||
@ -74,7 +74,7 @@ public class LoginTask extends AsyncTask<String, Integer, Integer> {
|
||||
protected void onPostExecute(Integer messageID) {
|
||||
super.onPostExecute(messageID);
|
||||
|
||||
GradesSync gradesSync = new GradesSync();
|
||||
GradeJob gradesSync = new GradeJob();
|
||||
gradesSync.scheduledJob(activity);
|
||||
|
||||
progress.dismiss();
|
||||
|
@ -8,7 +8,7 @@ import android.widget.Toast;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.activity.dashboard.DashboardActivity;
|
||||
import io.github.wulkanowy.activity.main.MainActivity;
|
||||
import io.github.wulkanowy.services.jobs.GradesSync;
|
||||
import io.github.wulkanowy.services.jobs.GradeJob;
|
||||
import io.github.wulkanowy.utilities.ConnectionUtilities;
|
||||
|
||||
public class LoadingTask extends AsyncTask<Void, Void, Boolean> {
|
||||
@ -42,7 +42,7 @@ public class LoadingTask extends AsyncTask<Void, Void, Boolean> {
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
GradesSync gradesSync = new GradesSync();
|
||||
GradeJob gradesSync = new GradeJob();
|
||||
gradesSync.scheduledJob(context);
|
||||
|
||||
Intent intent = new Intent(context, DashboardActivity.class);
|
||||
|
@ -0,0 +1,20 @@
|
||||
package io.github.wulkanowy.dao;
|
||||
|
||||
import org.greenrobot.greendao.query.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.dao.entities.Grade;
|
||||
import io.github.wulkanowy.dao.entities.GradeDao;
|
||||
|
||||
public abstract class DatabaseAccess {
|
||||
|
||||
public static List<Grade> getNewGrades(DaoSession daoSession) {
|
||||
Query<Grade> gradeQuery = daoSession.getGradeDao().queryBuilder()
|
||||
.where(GradeDao.Properties.IsNew.eq(1))
|
||||
.build();
|
||||
|
||||
return gradeQuery.list();
|
||||
}
|
||||
}
|
@ -15,12 +15,24 @@ public abstract class EntitiesCompare {
|
||||
.removeAll(newList, oldList));
|
||||
List<Grade> updatedList = new ArrayList<>(CollectionUtils
|
||||
.removeAll(newList, addedOrUpdatedGradeList));
|
||||
List<Grade> lastList = new ArrayList<>();
|
||||
|
||||
for (Grade grade : addedOrUpdatedGradeList) {
|
||||
grade.setIsNew(true);
|
||||
if (oldList.size() != 0) {
|
||||
grade.setRead(false);
|
||||
}
|
||||
updatedList.add(grade);
|
||||
}
|
||||
|
||||
return updatedList;
|
||||
for (Grade grade : updatedList) {
|
||||
for (Grade grade1 : oldList) {
|
||||
if (grade.equals(grade1)) {
|
||||
grade.setRead(grade1.getRead());
|
||||
}
|
||||
}
|
||||
lastList.add(grade);
|
||||
}
|
||||
return lastList;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.os.Parcelable;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.greenrobot.greendao.DaoException;
|
||||
import org.greenrobot.greendao.annotation.Entity;
|
||||
import org.greenrobot.greendao.annotation.Generated;
|
||||
import org.greenrobot.greendao.annotation.Id;
|
||||
@ -12,7 +13,10 @@ import org.greenrobot.greendao.annotation.Property;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
|
||||
@Entity(nameInDb = "Grades")
|
||||
@Entity(
|
||||
nameInDb = "Grades",
|
||||
active = true
|
||||
)
|
||||
public class Grade implements Parcelable {
|
||||
|
||||
@Id(autoincrement = true)
|
||||
@ -54,14 +58,18 @@ public class Grade implements Parcelable {
|
||||
@Property(nameInDb = "IS_NEW")
|
||||
private boolean isNew = false;
|
||||
|
||||
@Property(nameInDb = "READ")
|
||||
private boolean read = true;
|
||||
|
||||
protected Grade(Parcel source) {
|
||||
value = source.readString();
|
||||
}
|
||||
|
||||
@Generated(hash = 1154096520)
|
||||
@Generated(hash = 568899968)
|
||||
public Grade(Long id, Long subjectId, Long userId, String subject, String value,
|
||||
String color, String symbol, String description, String weight,
|
||||
String date, String teacher, String semester, boolean isNew) {
|
||||
String date, String teacher, String semester, boolean isNew,
|
||||
boolean read) {
|
||||
this.id = id;
|
||||
this.subjectId = subjectId;
|
||||
this.userId = userId;
|
||||
@ -75,6 +83,7 @@ public class Grade implements Parcelable {
|
||||
this.teacher = teacher;
|
||||
this.semester = semester;
|
||||
this.isNew = isNew;
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
@Generated(hash = 2042976393)
|
||||
@ -95,8 +104,8 @@ public class Grade implements Parcelable {
|
||||
parcel.writeString(description);
|
||||
parcel.writeString(weight);
|
||||
parcel.writeString(date);
|
||||
parcel.writeString(value);
|
||||
parcel.writeString(value);
|
||||
parcel.writeString(teacher);
|
||||
parcel.writeString(semester);
|
||||
}
|
||||
|
||||
public static final Creator<Grade> CREATOR = new Creator<Grade>() {
|
||||
@ -111,6 +120,18 @@ public class Grade implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to resolve relations
|
||||
*/
|
||||
@Generated(hash = 2040040024)
|
||||
private transient DaoSession daoSession;
|
||||
|
||||
/**
|
||||
* Used for active entity operations.
|
||||
*/
|
||||
@Generated(hash = 681281562)
|
||||
private transient GradeDao myDao;
|
||||
|
||||
public int getValueColor() {
|
||||
|
||||
String replacedString = value.replaceAll("[^0-9]", "");
|
||||
@ -284,7 +305,62 @@ public class Grade implements Parcelable {
|
||||
return this.isNew;
|
||||
}
|
||||
|
||||
public void setIsNew(boolean isNew) {
|
||||
public Grade setIsNew(boolean isNew) {
|
||||
this.isNew = isNew;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getRead() {
|
||||
return this.read;
|
||||
}
|
||||
|
||||
public Grade setRead(boolean read) {
|
||||
this.read = read;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
|
||||
* Entity must attached to an entity context.
|
||||
*/
|
||||
@Generated(hash = 128553479)
|
||||
public void delete() {
|
||||
if (myDao == null) {
|
||||
throw new DaoException("Entity is detached from DAO context");
|
||||
}
|
||||
myDao.delete(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
|
||||
* Entity must attached to an entity context.
|
||||
*/
|
||||
@Generated(hash = 1942392019)
|
||||
public void refresh() {
|
||||
if (myDao == null) {
|
||||
throw new DaoException("Entity is detached from DAO context");
|
||||
}
|
||||
myDao.refresh(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
|
||||
* Entity must attached to an entity context.
|
||||
*/
|
||||
@Generated(hash = 713229351)
|
||||
public void update() {
|
||||
if (myDao == null) {
|
||||
throw new DaoException("Entity is detached from DAO context");
|
||||
}
|
||||
myDao.update(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* called by internal mechanisms, do not call yourself.
|
||||
*/
|
||||
@Generated(hash = 1187286414)
|
||||
public void __setDaoSession(DaoSession daoSession) {
|
||||
this.daoSession = daoSession;
|
||||
myDao = daoSession != null ? daoSession.getGradeDao() : null;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package io.github.wulkanowy.services;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.dao.entities.DaoSession;
|
||||
|
||||
@ -38,4 +41,28 @@ public class LoginSession {
|
||||
this.daoSession = daoSession;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
LoginSession that = (LoginSession) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(userId, that.userId)
|
||||
.append(vulcan, that.vulcan)
|
||||
.append(daoSession, that.daoSession)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(userId)
|
||||
.append(vulcan)
|
||||
.append(daoSession)
|
||||
.toHashCode();
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import io.github.wulkanowy.api.login.LoginErrorException;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.security.CryptoException;
|
||||
import io.github.wulkanowy.services.jobs.VulcanSync;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.services.synchronisation.AccountSynchronisation;
|
||||
import io.github.wulkanowy.services.synchronisation.GradesSynchronisation;
|
||||
import io.github.wulkanowy.services.synchronisation.SubjectsSynchronisation;
|
||||
@ -47,7 +47,7 @@ public class VulcanSynchronization {
|
||||
gradesSynchronisation.sync(loginSession);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(VulcanSync.DEBUG_TAG, "Synchronisation of grades failed", e);
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Synchronisation of grades failed", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -60,7 +60,7 @@ public class VulcanSynchronization {
|
||||
syncGrades();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(VulcanSync.DEBUG_TAG, "Synchronisation of subjects failed", e);
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Synchronisation of subjects failed", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import io.github.wulkanowy.security.CryptoException;
|
||||
import io.github.wulkanowy.services.LoginSession;
|
||||
import io.github.wulkanowy.services.VulcanSynchronization;
|
||||
|
||||
public class GradesSync extends VulcanSync {
|
||||
public class GradeJob extends VulcanJobHelper {
|
||||
|
||||
public static final String UNIQUE_TAG = "GradesSync34512";
|
||||
|
||||
@ -31,7 +31,7 @@ public class GradesSync extends VulcanSync {
|
||||
protected Job createJob(FirebaseJobDispatcher dispatcher) {
|
||||
return dispatcher.newJobBuilder()
|
||||
.setLifetime(Lifetime.FOREVER)
|
||||
.setService(GradeJob.class)
|
||||
.setService(GradeService.class)
|
||||
.setTag(UNIQUE_TAG)
|
||||
.setRecurring(true)
|
||||
.setTrigger(Trigger.executionWindow(DEFAULT_INTERVAL_START, DEFAULT_INTERVAL_END))
|
||||
@ -41,7 +41,7 @@ public class GradesSync extends VulcanSync {
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class GradeJob extends VulcanJob {
|
||||
public static class GradeService extends VulcanService {
|
||||
|
||||
@Override
|
||||
public void workToBePerformed() throws CryptoException, BadCredentialsException,
|
@ -19,7 +19,7 @@ import io.github.wulkanowy.security.CryptoException;
|
||||
import io.github.wulkanowy.services.LoginSession;
|
||||
import io.github.wulkanowy.services.VulcanSynchronization;
|
||||
|
||||
public class SubjectsSync extends VulcanSync {
|
||||
public class SubjectJob extends VulcanJobHelper {
|
||||
|
||||
public static final String UNIQUE_TAG = "SubjectsSync34512";
|
||||
|
||||
@ -31,7 +31,7 @@ public class SubjectsSync extends VulcanSync {
|
||||
protected Job createJob(FirebaseJobDispatcher dispatcher) {
|
||||
return dispatcher.newJobBuilder()
|
||||
.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
|
||||
.setService(SubjectJob.class)
|
||||
.setService(SubjectService.class)
|
||||
.setTag(UNIQUE_TAG)
|
||||
.setRecurring(false)
|
||||
.setTrigger(Trigger.executionWindow(DEFAULT_INTERVAL_START, DEFAULT_INTERVAL_END))
|
||||
@ -41,7 +41,7 @@ public class SubjectsSync extends VulcanSync {
|
||||
.build();
|
||||
}
|
||||
|
||||
private class SubjectJob extends VulcanJob {
|
||||
private class SubjectService extends VulcanService {
|
||||
|
||||
@Override
|
||||
public void workToBePerformed() throws CryptoException, BadCredentialsException,
|
@ -7,7 +7,7 @@ import com.firebase.jobdispatcher.FirebaseJobDispatcher;
|
||||
import com.firebase.jobdispatcher.GooglePlayDriver;
|
||||
import com.firebase.jobdispatcher.Job;
|
||||
|
||||
public abstract class VulcanSync {
|
||||
public abstract class VulcanJobHelper {
|
||||
|
||||
public static final String DEBUG_TAG = "SynchronizationService";
|
||||
|
@ -13,20 +13,20 @@ import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.security.CryptoException;
|
||||
|
||||
public abstract class VulcanJob extends JobService {
|
||||
public abstract class VulcanService extends JobService {
|
||||
|
||||
private SyncTask syncTask = new SyncTask();
|
||||
|
||||
@Override
|
||||
public boolean onStartJob(JobParameters params) {
|
||||
Log.d(VulcanSync.DEBUG_TAG, "Wulkanowy services start");
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Wulkanowy services start");
|
||||
syncTask.execute(params);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters params) {
|
||||
Log.e(VulcanSync.DEBUG_TAG, "Wulkanowy serives stop");
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Wulkanowy serives stop");
|
||||
syncTask.cancel(true);
|
||||
return true;
|
||||
}
|
||||
@ -41,7 +41,7 @@ public abstract class VulcanJob extends JobService {
|
||||
try {
|
||||
workToBePerformed();
|
||||
} catch (Exception e) {
|
||||
Log.e(VulcanSync.DEBUG_TAG, "User logging in the background failed", e);
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "User logging in the background failed", e);
|
||||
} finally {
|
||||
jobFinished(params[0], false);
|
||||
}
|
@ -18,7 +18,7 @@ import io.github.wulkanowy.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.security.CryptoException;
|
||||
import io.github.wulkanowy.security.Safety;
|
||||
import io.github.wulkanowy.services.LoginSession;
|
||||
import io.github.wulkanowy.services.jobs.VulcanSync;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
|
||||
public class AccountSynchronisation {
|
||||
|
||||
@ -31,7 +31,7 @@ public class AccountSynchronisation {
|
||||
|
||||
if (userId != 0) {
|
||||
|
||||
Log.d(VulcanSync.DEBUG_TAG, "Login current user id=" + String.valueOf(userId));
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Login current user id=" + String.valueOf(userId));
|
||||
|
||||
Safety safety = new Safety();
|
||||
Account account = accountDao.load(userId);
|
||||
@ -46,7 +46,7 @@ public class AccountSynchronisation {
|
||||
.setUserId(userId)
|
||||
.setVulcan(vulcan);
|
||||
} else {
|
||||
Log.wtf(VulcanSync.DEBUG_TAG, "loginCurrentUser - USERID IS EMPTY");
|
||||
Log.wtf(VulcanJobHelper.DEBUG_TAG, "loginCurrentUser - USERID IS EMPTY");
|
||||
throw new IOException("Can't find user with index 0");
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,7 @@ public class AccountSynchronisation {
|
||||
|
||||
userId = accountDao.insert(account);
|
||||
|
||||
Log.d(VulcanSync.DEBUG_TAG, "Login and save new user id=" + String.valueOf(userId));
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Login and save new user id=" + String.valueOf(userId));
|
||||
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences("LoginData", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
|
@ -19,7 +19,7 @@ import io.github.wulkanowy.dao.entities.GradeDao;
|
||||
import io.github.wulkanowy.dao.entities.Subject;
|
||||
import io.github.wulkanowy.dao.entities.SubjectDao;
|
||||
import io.github.wulkanowy.services.LoginSession;
|
||||
import io.github.wulkanowy.services.jobs.VulcanSync;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.utilities.ConversionVulcanObject;
|
||||
|
||||
public class GradesSynchronisation {
|
||||
@ -57,6 +57,6 @@ public class GradesSynchronisation {
|
||||
|
||||
gradeDao.insertInTx(lastList);
|
||||
|
||||
Log.d(VulcanSync.DEBUG_TAG, "Synchronization grades (amount = " + String.valueOf(lastList.size() + ")"));
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Synchronization grades (amount = " + String.valueOf(lastList.size() + ")"));
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.dao.entities.Subject;
|
||||
import io.github.wulkanowy.dao.entities.SubjectDao;
|
||||
import io.github.wulkanowy.services.LoginSession;
|
||||
import io.github.wulkanowy.services.jobs.VulcanSync;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.utilities.ConversionVulcanObject;
|
||||
|
||||
public class SubjectsSynchronisation {
|
||||
@ -36,6 +36,6 @@ public class SubjectsSynchronisation {
|
||||
subjectDao.insertInTx(preparedList);
|
||||
|
||||
|
||||
Log.d(VulcanSync.DEBUG_TAG, "Synchronization subjects (amount = " + String.valueOf(subjectEntitiesList.size() + ")"));
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Synchronization subjects (amount = " + String.valueOf(subjectEntitiesList.size() + ")"));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
package io.github.wulkanowy.utilities;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.dao.entities.Grade;
|
||||
|
||||
public abstract class AverageCalculator {
|
||||
|
||||
public static float calculate(List<Grade> gradeList) {
|
||||
|
||||
float counter = 0f;
|
||||
float denominator = 0f;
|
||||
|
||||
for (Grade grade : gradeList) {
|
||||
int integerWeight = getIntegerForWeightOfGrade(grade.getWeight());
|
||||
float floatValue = getMathematicalValueOfGrade(grade.getValue());
|
||||
|
||||
if (floatValue != -1f) {
|
||||
counter += floatValue * integerWeight;
|
||||
denominator += integerWeight;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter == 0f) {
|
||||
return -1f;
|
||||
} else {
|
||||
return counter / denominator;
|
||||
}
|
||||
}
|
||||
|
||||
private static float getMathematicalValueOfGrade(String valueOfGrade) {
|
||||
if (valueOfGrade.matches("[-|+|=]{0,2}[0-6]") || valueOfGrade.matches("[0-6][-|+|=]{0,2}")) {
|
||||
if (valueOfGrade.matches("[-][0-6]") || valueOfGrade.matches("[0-6][-]")) {
|
||||
String replacedValue = valueOfGrade.replaceAll("[-]", "");
|
||||
return Float.valueOf(replacedValue) - 0.25f;
|
||||
} else if (valueOfGrade.matches("[+][0-6]") || valueOfGrade.matches("[0-6][+]")) {
|
||||
String replacedValue = valueOfGrade.replaceAll("[+]", "");
|
||||
return Float.valueOf((replacedValue)) + 0.25f;
|
||||
} else if (valueOfGrade.matches("[-|=]{1,2}[0-6]") || valueOfGrade.matches("[0-6][-|=]{1,2}")) {
|
||||
String replacedValue = valueOfGrade.replaceAll("[-|=]{1,2}", "");
|
||||
return Float.valueOf((replacedValue)) - 0.5f;
|
||||
} else {
|
||||
return Float.valueOf(valueOfGrade);
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getIntegerForWeightOfGrade(String weightOfGrade) {
|
||||
return Integer.valueOf(weightOfGrade.substring(0, weightOfGrade.length() - 3));
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="35dp"
|
||||
android:height="35dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
|
||||
<path android:pathData="M0-.75h24v24H0z" />
|
||||
</vector>
|
@ -4,5 +4,12 @@
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#ffffff" android:pathData="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M19.4,13c0-0.3,0.1-0.7,0.1-1s0-0.7-0.1-1l2.1-1.5c0.2-0.1,0.3-0.4,0.1-0.7l-2-3.5C19.5,5,19.2,4.9,19,5l-2.4,1.1
|
||||
c-0.5-0.4-1.2-0.8-1.8-1l-0.3-2.6C14.5,2.2,14.3,2,14,2H10C9.7,2,9.5,2.2,9.5,2.5L9.2,5c-0.7,0.3-1.3,0.6-1.8,1L5,5
|
||||
C4.8,4.9,4.5,5,4.4,5.2l-2,3.5C2.2,9,2.2,9.3,2.5,9.4L4.6,11c0,0.3-0.1,0.7-0.1,1s0,0.7,0.1,1l-2.1,1.5c-0.2,0.1-0.3,0.4-0.1,0.7
|
||||
l2,3.5C4.5,19,4.8,19.1,5,19l2.4-1.1c0.5,0.4,1.2,0.8,1.8,1l0.3,2.6c0,0.3,0.2,0.5,0.5,0.5H14c0.3,0,0.5-0.2,0.5-0.5l0.3-2.6
|
||||
c0.7-0.3,1.3-0.6,1.8-1L19,19c0.2,0.1,0.5,0,0.6-0.2l2-3.5c0.1-0.2,0.1-0.5-0.1-0.7L19.4,13z M12,16c-2.2,0-4-1.8-4-4
|
||||
c0-2.2,1.8-4,4-4s4,1.8,4,4C16,14.2,14.2,16,12,16z" />
|
||||
</vector>
|
9
app/src/main/res/drawable/subject_alert_circle.xml
Normal file
9
app/src/main/res/drawable/subject_alert_circle.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@color/colorPrimary"
|
||||
android:pathData="M13,13H11V7H13M13,17H11V15H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
|
||||
</vector>
|
@ -2,7 +2,7 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:angle="270"
|
||||
android:centerColor="@android:color/transparent"
|
||||
android:centerX="0.01"
|
||||
android:startColor="#60606060" />
|
@ -9,12 +9,11 @@
|
||||
android:weightSum="1"
|
||||
tools:context="io.github.wulkanowy.activity.dashboard.DashboardActivity">
|
||||
|
||||
<FrameLayout
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:fitsSystemWindows="true"
|
||||
app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior" />
|
||||
|
||||
|
||||
|
@ -1,13 +1,19 @@
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/coordinator_grade"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="io.github.wulkanowy.activity.dashboard.grades.GradesFragment">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/grade_swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/subject_grade_recycler" />
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/subject_grade_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/loadingPanel"
|
||||
@ -21,4 +27,6 @@
|
||||
android:indeterminate="true" />
|
||||
</RelativeLayout>
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
@ -1,4 +1,5 @@
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/grade_cardview"
|
||||
android:layout_width="match_parent"
|
||||
@ -23,27 +24,28 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grade_text"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="center"
|
||||
android:textSize="19sp" />
|
||||
android:maxLength="5"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description_grade_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginEnd="40dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginRight="40dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_toEndOf="@+id/grade_text"
|
||||
android:layout_toRightOf="@+id/grade_text"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="19sp" />
|
||||
android:textSize="15sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/grade_date_text"
|
||||
@ -53,7 +55,16 @@
|
||||
android:layout_alignLeft="@+id/description_grade_text"
|
||||
android:layout_alignStart="@+id/description_grade_text"
|
||||
android:text="@string/grades_text"
|
||||
android:textSize="13sp" />
|
||||
android:textSize="12sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/grade_new_grades_alert"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginTop="10dp"
|
||||
app:srcCompat="@drawable/subject_alert_circle" />
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.v7.widget.CardView>
|
@ -179,6 +179,7 @@
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:text="@string/ok_text"
|
||||
android:textSize="16sp" />
|
||||
|
@ -2,36 +2,51 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/border"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless">
|
||||
android:background="@drawable/subject_border_1px"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="15dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subject_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="15dp"
|
||||
android:layout_marginRight="50dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:layout_marginEnd="35dp"
|
||||
android:layout_marginRight="35dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="19sp" />
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subject_grades_average"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/subject_text"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="#4C4C4C"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subject_number_of_grades"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/subject_text"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_toEndOf="@+id/subject_grades_average"
|
||||
android:layout_toRightOf="@+id/subject_grades_average"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="#4C4C4C"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/group_indicator_down"
|
||||
android:id="@+id/subject_new_grades_alert"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
app:srcCompat="@drawable/ic_arrow_down" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/group_indicator_up"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:rotation="180"
|
||||
app:srcCompat="@drawable/ic_arrow_down" />
|
||||
|
||||
android:layout_marginTop="10dp"
|
||||
app:srcCompat="@drawable/subject_alert_circle" />
|
||||
</RelativeLayout>
|
@ -20,11 +20,8 @@
|
||||
<string name="lessonplan_text">Plan lekcji</string>
|
||||
<string name="settings_text">Ustawienia</string>
|
||||
<string name="noInternet_text">Brak połączenia z internetem</string>
|
||||
<string name="login_cookies_save_failed_text">Nie udało się zapisać sesji</string>
|
||||
<string name="SQLite_ioError_text">W bazie danych wystąpił błąd. Zrestartuj aplikacje a także sprawdź iość wolnego miejsca w pamięci wewnętrznej</string>
|
||||
<string name="root_failed_text">To urządzenie posiada posiada podwyższone uprawnienia (root). Automatyczne logowanie zosatło wyłączone.</string>
|
||||
<string name="encrypt_failed_text">Szyfrowanie nie powiodło się. Automatyczne logowanie zostało wyłączone</string>
|
||||
<string name="decrypt_failed_text">Deszyfrowanie nie powiodło się. Automatyczne logowanie zostało wyłączone</string>
|
||||
<string name="version_text">Wersja\u0020</string>
|
||||
<string name="dialog_description_text">Opis</string>
|
||||
<string name="dialog_weight_text">Waga</string>
|
||||
@ -38,5 +35,16 @@
|
||||
<string name="color_green_text">Zielony</string>
|
||||
<string name="noColor_text">Brak koloru</string>
|
||||
<string name="ok_text">OK</string>
|
||||
<string name="dialog_subject_text">Przedmiot</string>
|
||||
<string name="refresh_error_text">"Podczas odświeżania zawartości wystąpił błąd. "</string>
|
||||
<string name="snackbar_no_grades">Brak nowych ocen</string>
|
||||
<string name="snackbar_new_grade">Ilość nowych ocen: %1$d</string>
|
||||
|
||||
<plurals name="numberOfGrades">
|
||||
<item quantity="one">%d ocena</item>
|
||||
<item quantity="few">%d oceny</item>
|
||||
<item quantity="many">%d ocen</item>
|
||||
<item quantity="other">%d ocen</item>
|
||||
</plurals>
|
||||
<string name="info_average_grades">Średnia: %1$.2f</string>
|
||||
<string name="info_no_average">Brak średniej</string>
|
||||
</resources>
|
||||
|
@ -20,11 +20,8 @@
|
||||
<string name="lessonplan_text">Lesson Plan</string>
|
||||
<string name="settings_text">Settings</string>
|
||||
<string name="noInternet_text">No internet connection</string>
|
||||
<string name="login_cookies_save_failed_text">Failed to save session</string>
|
||||
<string name="SQLite_ioError_text">An error occurred in the database. Restart the applications and check the free space in the internal memory</string>
|
||||
<string name="root_failed_text">This device is rooted. Automatic login has been disabled</string>
|
||||
<string name="encrypt_failed_text">Encryption failed. Automatic login has been disabled</string>
|
||||
<string name="decrypt_failed_text">Decrypt is failed. Automatic login has been disable</string>
|
||||
<string name="version_text">Version\u0020</string>
|
||||
<string name="dialog_description_text">Description</string>
|
||||
<string name="dialog_weight_text">Weight</string>
|
||||
@ -38,5 +35,14 @@
|
||||
<string name="color_green_text">Green</string>
|
||||
<string name="noColor_text">No color</string>
|
||||
<string name="ok_text">OK</string>
|
||||
<string name="dialog_subject_text">Subject</string>
|
||||
<string name="refresh_error_text">An error occurred while refreshing the content.</string>
|
||||
<string name="snackbar_no_grades">No new grades</string>
|
||||
<string name="snackbar_new_grade">Number of new grades: %1$d</string>
|
||||
|
||||
<plurals name="numberOfGrades">
|
||||
<item quantity="one">%d grade</item>
|
||||
<item quantity="other">%d grades</item>
|
||||
</plurals>
|
||||
<string name="info_average_grades">Average: %1$.2f</string>
|
||||
<string name="info_no_average">No average</string>
|
||||
</resources>
|
||||
|
@ -0,0 +1,42 @@
|
||||
package io.github.wulkanowy.utilities;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.dao.entities.Grade;
|
||||
|
||||
public class AverageCalculatorTest extends AverageCalculator {
|
||||
|
||||
@Test
|
||||
public void averageTest() {
|
||||
List<Grade> gradeList = new ArrayList<>();
|
||||
gradeList.add(new Grade().setValue("np.").setWeight("1,00"));
|
||||
gradeList.add(new Grade().setValue("-5").setWeight("10,00"));
|
||||
gradeList.add(new Grade().setValue("--5").setWeight("10,00"));
|
||||
gradeList.add(new Grade().setValue("=5").setWeight("10,00"));
|
||||
gradeList.add(new Grade().setValue("+5").setWeight("10,00"));
|
||||
gradeList.add(new Grade().setValue("5").setWeight("10,00"));
|
||||
|
||||
List<Grade> gradeList1 = new ArrayList<>();
|
||||
gradeList1.add(new Grade().setValue("np.").setWeight("1,00"));
|
||||
gradeList1.add(new Grade().setValue("5-").setWeight("10,00"));
|
||||
gradeList1.add(new Grade().setValue("5--").setWeight("10,00"));
|
||||
gradeList1.add(new Grade().setValue("5=").setWeight("10,00"));
|
||||
gradeList1.add(new Grade().setValue("5+").setWeight("10,00"));
|
||||
gradeList1.add(new Grade().setValue("5").setWeight("10,00"));
|
||||
|
||||
Assert.assertEquals(4.8f, AverageCalculator.calculate(gradeList), 0.0f);
|
||||
Assert.assertEquals(4.8f, AverageCalculator.calculate(gradeList1), 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorAverageTest() {
|
||||
List<Grade> gradeList = new ArrayList<>();
|
||||
gradeList.add(new Grade().setValue("np.").setWeight("1,00"));
|
||||
|
||||
Assert.assertEquals(-1f, AverageCalculator.calculate(gradeList), 0.0f);
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ buildscript {
|
||||
maven { url 'https://maven.google.com' }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
||||
classpath 'com.android.tools.build:gradle:3.0.0'
|
||||
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Wed Mar 08 19:17:31 CET 2017
|
||||
#Thu Oct 26 14:47:13 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
|
||||
|
Loading…
x
Reference in New Issue
Block a user