forked from github/wulkanowy-mirror
MVP (#46)
This commit is contained in:
parent
a1a3427142
commit
79bdbbbb16
@ -1,5 +1,5 @@
|
||||
exclude:
|
||||
- /app/src/main/java/io/github/wulkanowy/db/dao/entities/.*
|
||||
- /app/src/main/java/io/github/wulkanowy/data/db/dao/entities/.*
|
||||
component_depth: 1
|
||||
languages:
|
||||
- java
|
||||
|
@ -48,7 +48,7 @@ public class Vulcan {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
public String login(String email, String password, String symbol)
|
||||
public void login(String email, String password, String symbol)
|
||||
throws BadCredentialsException, AccountPermissionException,
|
||||
LoginErrorException, IOException, VulcanOfflineException {
|
||||
|
||||
@ -56,8 +56,6 @@ public class Vulcan {
|
||||
login = getLogin();
|
||||
|
||||
this.symbol = login.login(this.email, password, symbol);
|
||||
|
||||
return this.symbol;
|
||||
}
|
||||
|
||||
public Vulcan login(String email, String password, String symbol, String id)
|
||||
@ -82,6 +80,10 @@ public class Vulcan {
|
||||
return email;
|
||||
}
|
||||
|
||||
public String getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
private void setFullEndpointInfo(String email) {
|
||||
String[] creds = email.split("\\\\");
|
||||
|
||||
|
@ -27,14 +27,6 @@ public class Login {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
private String getLoginPageUrl() {
|
||||
return LOGIN_PAGE_URL;
|
||||
}
|
||||
|
||||
private String getLoginEndpointPageUrl() {
|
||||
return LOGIN_ENDPOINT_PAGE_URL;
|
||||
}
|
||||
|
||||
public String login(String email, String password, String symbol)
|
||||
throws BadCredentialsException, LoginErrorException,
|
||||
AccountPermissionException, IOException, VulcanOfflineException {
|
||||
@ -47,7 +39,7 @@ public class Login {
|
||||
throws IOException, BadCredentialsException {
|
||||
this.symbol = symbol;
|
||||
|
||||
Document html = client.postPageByUrl(getLoginPageUrl(), new String[][]{
|
||||
Document html = client.postPageByUrl(LOGIN_PAGE_URL, new String[][]{
|
||||
{"LoginName", email},
|
||||
{"Password", password}
|
||||
});
|
||||
@ -64,8 +56,7 @@ public class Login {
|
||||
this.symbol = findSymbol(defaultSymbol, certificate);
|
||||
client.setSymbol(this.symbol);
|
||||
|
||||
Document html = client.postPageByUrl(getLoginEndpointPageUrl()
|
||||
.replace("{symbol}", this.symbol), new String[][]{
|
||||
Document html = client.postPageByUrl(LOGIN_ENDPOINT_PAGE_URL, new String[][]{
|
||||
{"wa", "wsignin1.0"},
|
||||
{"wresult", certificate}
|
||||
});
|
||||
@ -103,4 +94,4 @@ public class Login {
|
||||
|
||||
return els.get(1).text();
|
||||
}
|
||||
}
|
||||
}
|
@ -62,29 +62,29 @@ android {
|
||||
}
|
||||
|
||||
greendao {
|
||||
schemaVersion 19
|
||||
schemaVersion 20
|
||||
generateTests = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':api')
|
||||
implementation 'com.android.support:appcompat-v7:27.0.2'
|
||||
implementation 'com.android.support:design:27.0.2'
|
||||
implementation 'com.android.support:support-v4:27.0.2'
|
||||
implementation 'com.android.support:recyclerview-v7:27.0.2'
|
||||
implementation 'com.android.support:cardview-v7:27.0.2'
|
||||
implementation 'com.android.support:customtabs:27.0.2'
|
||||
implementation 'com.android.support:appcompat-v7:27.1.0'
|
||||
implementation 'com.android.support:design:27.1.0'
|
||||
implementation 'com.android.support:support-v4:27.1.0'
|
||||
implementation 'com.android.support:recyclerview-v7:27.1.0'
|
||||
implementation 'com.android.support:cardview-v7:27.1.0'
|
||||
implementation 'com.android.support:customtabs:27.1.0'
|
||||
implementation 'com.firebase:firebase-jobdispatcher:0.8.5'
|
||||
implementation 'com.thoughtbot:expandablerecyclerview:1.3'
|
||||
implementation 'org.apache.commons:commons-lang3:3.7'
|
||||
implementation 'eu.davidea:flexible-adapter:5.0.0-rc3'
|
||||
implementation 'eu.davidea:flexible-adapter:5.0.0-rc4'
|
||||
implementation 'eu.davidea:flexible-adapter-ui:1.0.0-b1'
|
||||
implementation 'org.apache.commons:commons-collections4:4.1'
|
||||
implementation 'org.greenrobot:greendao:3.2.2'
|
||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
||||
implementation 'joda-time:joda-time:2.9.9'
|
||||
implementation 'com.github.javiersantos:AppUpdater:2.6.4'
|
||||
implementation 'com.google.dagger:dagger-android:2.14.1'
|
||||
implementation 'com.google.dagger:dagger-android-support:2.14.1'
|
||||
implementation 'com.aurelhubert:ahbottomnavigation:2.1.0'
|
||||
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.8.0@aar') {
|
||||
transitive = true
|
||||
@ -94,6 +94,7 @@ dependencies {
|
||||
}
|
||||
|
||||
annotationProcessor 'com.google.dagger:dagger-android-processor:2.14.1'
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.14.1'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
|
||||
|
||||
debugImplementation 'com.amitshekhar.android:debug-db:1.0.1'
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
|
||||
|
@ -1,50 +0,0 @@
|
||||
package io.github.wulkanowy.db.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.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.db.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-db");
|
||||
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, new DatabaseAccess().getNewGrades(daoSession).size());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() {
|
||||
daoSession.getAccountDao().deleteAll();
|
||||
daoSession.getGradeDao().deleteAll();
|
||||
daoSession.getSubjectDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
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 org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.login.AccountPermissionException;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.api.login.LoginErrorException;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.db.dao.entities.AccountDao;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
import io.github.wulkanowy.utils.security.Safety;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class CurrentAccountLoginTest {
|
||||
|
||||
private static DaoSession daoSession;
|
||||
|
||||
private Context context;
|
||||
|
||||
private Context targetContext;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(InstrumentationRegistry.getTargetContext(), "wulkanowyTest-db");
|
||||
Database database = devOpenHelper.getWritableDb();
|
||||
daoSession = new DaoMaster(database).newSession();
|
||||
|
||||
DaoMaster.dropAllTables(database, true);
|
||||
DaoMaster.createAllTables(database, true);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
context = InstrumentationRegistry.getContext();
|
||||
targetContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
daoSession.getAccountDao().deleteAll();
|
||||
daoSession.clear();
|
||||
|
||||
setUserIdSharePreferences(0);
|
||||
}
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void emptyUserIdTest() throws CryptoException, BadCredentialsException,
|
||||
AccountPermissionException, IOException, LoginErrorException, VulcanOfflineException {
|
||||
|
||||
CurrentAccountLogin currentAccountLogin = new CurrentAccountLogin(context, daoSession, new Vulcan());
|
||||
currentAccountLogin.loginCurrentUser();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginCurrentUserTest() throws Exception {
|
||||
AccountDao accountDao = daoSession.getAccountDao();
|
||||
|
||||
Safety safety = new Safety();
|
||||
|
||||
Long userId = accountDao.insert(new Account()
|
||||
.setEmail("TEST@TEST")
|
||||
.setPassword(safety.encrypt("TEST@TEST", "TEST", context))
|
||||
.setSymbol(""));
|
||||
|
||||
setUserIdSharePreferences(userId);
|
||||
|
||||
Vulcan vulcan = Mockito.mock(Vulcan.class);
|
||||
Mockito.when(vulcan.login("TEST@TEST", "TEST", "TEST_SYMBOL", "TEST_ID")).thenReturn(new Vulcan());
|
||||
|
||||
CurrentAccountLogin currentAccountLogin = new CurrentAccountLogin(targetContext, daoSession, vulcan);
|
||||
LoginSession loginSession = currentAccountLogin.loginCurrentUser();
|
||||
|
||||
Assert.assertNotNull(loginSession);
|
||||
Assert.assertEquals(loginSession.getUserId(), userId);
|
||||
Assert.assertNotNull(loginSession.getDaoSession());
|
||||
Assert.assertEquals(loginSession.getVulcan(), vulcan);
|
||||
}
|
||||
|
||||
private void setUserIdSharePreferences(long id) {
|
||||
SharedPreferences sharedPreferences = targetContext.getSharedPreferences("LoginData", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putLong("userId", id);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() {
|
||||
daoSession.getAccountDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
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 org.mockito.Mockito;
|
||||
|
||||
import io.github.wulkanowy.api.StudentAndParent;
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.user.BasicInformation;
|
||||
import io.github.wulkanowy.api.user.PersonalData;
|
||||
import io.github.wulkanowy.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.utils.security.Safety;
|
||||
|
||||
public class FirstAccountLoginTest {
|
||||
|
||||
private static DaoSession daoSession;
|
||||
|
||||
private Context targetContext;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(InstrumentationRegistry.getTargetContext(), "wulkanowyTest-db");
|
||||
Database database = devOpenHelper.getWritableDb();
|
||||
daoSession = new DaoMaster(database).newSession();
|
||||
|
||||
DaoMaster.dropAllTables(database, true);
|
||||
DaoMaster.createAllTables(database, true);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
targetContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
daoSession.getAccountDao().deleteAll();
|
||||
daoSession.clear();
|
||||
|
||||
setUserIdSharePreferences(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginTest() throws Exception {
|
||||
StudentAndParent snp = Mockito.mock(StudentAndParent.class);
|
||||
Mockito.when(snp.getId()).thenReturn("TEST-ID");
|
||||
|
||||
PersonalData personalData = Mockito.mock(PersonalData.class);
|
||||
Mockito.doReturn("NAME-TEST").when(personalData).getFirstAndLastName();
|
||||
|
||||
BasicInformation basicInformation = Mockito.mock(BasicInformation.class);
|
||||
Mockito.doReturn(personalData).when(basicInformation).getPersonalData();
|
||||
|
||||
Vulcan vulcan = Mockito.mock(Vulcan.class);
|
||||
Mockito.doReturn("TEST-SYMBOL").when(vulcan).login(Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
|
||||
Mockito.doReturn(snp).when(vulcan).getStudentAndParent();
|
||||
Mockito.doReturn(basicInformation).when(vulcan).getBasicInformation();
|
||||
|
||||
FirstAccountLogin firstAccountLogin = new FirstAccountLogin(targetContext, daoSession, vulcan);
|
||||
LoginSession loginSession = firstAccountLogin.login("TEST@TEST", "TEST-PASS", "default");
|
||||
|
||||
Long userId = targetContext.getSharedPreferences("LoginData", Context.MODE_PRIVATE).getLong("userId", 0);
|
||||
|
||||
Assert.assertNotNull(loginSession);
|
||||
Assert.assertNotEquals(0, userId.longValue());
|
||||
Assert.assertEquals(loginSession.getUserId(), userId);
|
||||
Assert.assertNotNull(loginSession.getDaoSession());
|
||||
Assert.assertEquals(loginSession.getVulcan(), vulcan);
|
||||
|
||||
Safety safety = new Safety();
|
||||
Account account = daoSession.getAccountDao().load(userId);
|
||||
Assert.assertNotNull(account);
|
||||
Assert.assertEquals("TEST@TEST", account.getEmail());
|
||||
Assert.assertEquals("NAME-TEST", account.getName());
|
||||
Assert.assertEquals("TEST-PASS", safety.decrypt("TEST@TEST", account.getPassword()));
|
||||
Assert.assertEquals("TEST-SYMBOL", account.getSymbol());
|
||||
Assert.assertEquals("TEST-ID", account.getSnpId());
|
||||
}
|
||||
|
||||
private void setUserIdSharePreferences(long id) {
|
||||
SharedPreferences sharedPreferences = targetContext.getSharedPreferences("LoginData", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putLong("userId", id);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() {
|
||||
daoSession.getAccountDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
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 org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.grades.Grade;
|
||||
import io.github.wulkanowy.api.grades.GradesList;
|
||||
import io.github.wulkanowy.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.db.dao.entities.Subject;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class GradeSyncTest {
|
||||
|
||||
private static DaoSession daoSession;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(InstrumentationRegistry.getTargetContext(), "wulkanowyTest-db");
|
||||
Database database = devOpenHelper.getWritableDb();
|
||||
daoSession = new DaoMaster(database).newSession();
|
||||
|
||||
DaoMaster.dropAllTables(database, true);
|
||||
DaoMaster.createAllTables(database, true);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
daoSession.getAccountDao().deleteAll();
|
||||
daoSession.getGradeDao().deleteAll();
|
||||
daoSession.getSubjectDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void syncGradesEmptyDatabaseTest() throws Exception {
|
||||
Long userId = daoSession.getAccountDao().insert(new Account().setEmail("TEST@TEST"));
|
||||
Long subjectId = daoSession.getSubjectDao().insert(new Subject().setName("Matematyka").setUserId(userId));
|
||||
|
||||
List<Grade> gradeList = new ArrayList<>();
|
||||
gradeList.add(new Grade().setSubject("Matematyka").setValue("5"));
|
||||
|
||||
GradesList gradesListApi = Mockito.mock(GradesList.class);
|
||||
Mockito.doReturn(gradeList).when(gradesListApi).getAll();
|
||||
|
||||
Vulcan vulcan = Mockito.mock(Vulcan.class);
|
||||
Mockito.doReturn(gradesListApi).when(vulcan).getGradesList();
|
||||
|
||||
LoginSession loginSession = Mockito.mock(LoginSession.class);
|
||||
Mockito.doReturn(vulcan).when(loginSession).getVulcan();
|
||||
Mockito.doReturn(daoSession).when(loginSession).getDaoSession();
|
||||
Mockito.doReturn(userId).when(loginSession).getUserId();
|
||||
|
||||
GradesSync gradesSync = new GradesSync();
|
||||
gradesSync.sync(loginSession);
|
||||
|
||||
io.github.wulkanowy.db.dao.entities.Grade grade = daoSession.getGradeDao().load(1L);
|
||||
|
||||
Assert.assertNotNull(grade);
|
||||
Assert.assertEquals(userId, grade.getUserId());
|
||||
Assert.assertEquals(subjectId, grade.getSubjectId());
|
||||
Assert.assertEquals("Matematyka", grade.getSubject());
|
||||
Assert.assertEquals("5", grade.getValue());
|
||||
Assert.assertFalse(grade.getIsNew());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() {
|
||||
daoSession.getAccountDao().deleteAll();
|
||||
daoSession.getGradeDao().deleteAll();
|
||||
daoSession.getSubjectDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
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 org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.grades.SubjectsList;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.db.dao.entities.Subject;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SubjectSyncTest {
|
||||
|
||||
private static DaoSession daoSession;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(InstrumentationRegistry.getTargetContext(), "wulkanowyTest-db");
|
||||
Database database = devOpenHelper.getWritableDb();
|
||||
daoSession = new DaoMaster(database).newSession();
|
||||
|
||||
DaoMaster.dropAllTables(database, true);
|
||||
DaoMaster.createAllTables(database, true);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
daoSession.getSubjectDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void syncSubjectTest() throws Exception {
|
||||
List<io.github.wulkanowy.api.grades.Subject> subjectList = new ArrayList<>();
|
||||
subjectList.add(new io.github.wulkanowy.api.grades.Subject()
|
||||
.setName("Matematyka")
|
||||
.setFinalRating("5")
|
||||
.setPredictedRating("4"));
|
||||
|
||||
SubjectsList subjectsListApi = Mockito.mock(SubjectsList.class);
|
||||
Mockito.doReturn(subjectList).when(subjectsListApi).getAll();
|
||||
|
||||
Vulcan vulcan = Mockito.mock(Vulcan.class);
|
||||
Mockito.doReturn(subjectsListApi).when(vulcan).getSubjectsList();
|
||||
|
||||
LoginSession loginSession = Mockito.mock(LoginSession.class);
|
||||
Mockito.doReturn(vulcan).when(loginSession).getVulcan();
|
||||
Mockito.doReturn(2L).when(loginSession).getUserId();
|
||||
Mockito.doReturn(daoSession).when(loginSession).getDaoSession();
|
||||
|
||||
SubjectsSync subjectsSync = new SubjectsSync();
|
||||
subjectsSync.sync(loginSession);
|
||||
|
||||
Subject subject = daoSession.getSubjectDao().load(1L);
|
||||
|
||||
Assert.assertNotNull(subject);
|
||||
Assert.assertEquals(2, subject.getUserId().longValue());
|
||||
Assert.assertEquals("Matematyka", subject.getName());
|
||||
Assert.assertEquals("5", subject.getFinalRating());
|
||||
Assert.assertEquals("4", subject.getPredictedRating());
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() {
|
||||
daoSession.getSubjectDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.greenrobot.greendao.database.Database;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.timetable.Day;
|
||||
import io.github.wulkanowy.api.timetable.Lesson;
|
||||
import io.github.wulkanowy.api.timetable.Timetable;
|
||||
import io.github.wulkanowy.api.timetable.Week;
|
||||
import io.github.wulkanowy.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TimetableSyncTest {
|
||||
|
||||
private static DaoSession daoSession;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(InstrumentationRegistry.getTargetContext(), "wulkanowyTest-db");
|
||||
Database database = devOpenHelper.getWritableDb();
|
||||
daoSession = new DaoMaster(database).newSession();
|
||||
|
||||
DaoMaster.dropAllTables(database, true);
|
||||
DaoMaster.createAllTables(database, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void syncTimetableEmptyDatabaseTest() throws Exception {
|
||||
Long userId = daoSession.getAccountDao().insert(new Account().setEmail("TEST@TEST"));
|
||||
|
||||
List<Day> dayList = new ArrayList<>();
|
||||
dayList.add(new Day()
|
||||
.setDate("20.12.2012")
|
||||
.setLesson(new Lesson().setSubject("Matematyka").setRoom("20")));
|
||||
Week week = new Week().setDays(dayList);
|
||||
|
||||
List<Day> nextDayList = new ArrayList<>();
|
||||
dayList.add(new Day()
|
||||
.setDate("24.11.2013")
|
||||
.setLesson(new Lesson().setSubject("Matematyka").setRoom("22")));
|
||||
Week nextWeek = new Week().setDays(nextDayList);
|
||||
|
||||
Timetable timetable = mock(Timetable.class);
|
||||
doReturn(week).when(timetable).getWeekTable();
|
||||
doReturn(nextWeek).when(timetable).getWeekTable(anyString());
|
||||
|
||||
Vulcan vulcan = mock(Vulcan.class);
|
||||
doReturn(timetable).when(vulcan).getTimetable();
|
||||
|
||||
LoginSession loginSession = mock(LoginSession.class);
|
||||
doReturn(vulcan).when(loginSession).getVulcan();
|
||||
doReturn(daoSession).when(loginSession).getDaoSession();
|
||||
doReturn(userId).when(loginSession).getUserId();
|
||||
|
||||
TimetableSync timetableSync = new TimetableSync();
|
||||
timetableSync.sync(loginSession, null);
|
||||
|
||||
List<io.github.wulkanowy.db.dao.entities.Day> dayEntityList = daoSession.getDayDao().loadAll();
|
||||
List<io.github.wulkanowy.db.dao.entities.Lesson> lessonEntityList = dayEntityList.get(0).getLessons();
|
||||
|
||||
Assert.assertNotNull(dayEntityList.get(0));
|
||||
Assert.assertEquals(userId, dayEntityList.get(0).getUserId());
|
||||
Assert.assertEquals(1L, lessonEntityList.get(0).getDayId().longValue());
|
||||
Assert.assertEquals("Matematyka", lessonEntityList.get(0).getSubject());
|
||||
Assert.assertEquals("20", lessonEntityList.get(0).getRoom());
|
||||
Assert.assertEquals("20.12.2012", dayEntityList.get(0).getDate());
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanUp() {
|
||||
daoSession.getAccountDao().deleteAll();
|
||||
daoSession.getDayDao().deleteAll();
|
||||
daoSession.getLessonDao().deleteAll();
|
||||
daoSession.getWeekDao().deleteAll();
|
||||
daoSession.clear();
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class VulcanSyncTest {
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void syncNoLoginSessionSubjectTest() throws IOException {
|
||||
VulcanSync vulcanSync = new VulcanSync(new LoginSession());
|
||||
vulcanSync.syncSubjectsAndGrades();
|
||||
}
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void syncNoLoginSessionGradeTest() throws IOException {
|
||||
VulcanSync vulcanSync = new VulcanSync(new LoginSession());
|
||||
vulcanSync.syncGrades();
|
||||
}
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void syncNoLoginSessionTimetableTest() throws IOException {
|
||||
VulcanSync vulcanSync = new VulcanSync(new LoginSession());
|
||||
vulcanSync.syncTimetable();
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package io.github.wulkanowy.utils.security;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.filters.SdkSuppress;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SafetyTest {
|
||||
|
||||
@Test
|
||||
@SdkSuppress(minSdkVersion = 18)
|
||||
public void encryptDecryptTest() throws Exception {
|
||||
Context targetContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
Safety safety = new Safety();
|
||||
Assert.assertEquals("PASS", safety.decrypt("TEST", safety.encrypt("TEST", "PASS", targetContext)));
|
||||
}
|
||||
}
|
@ -1,59 +1,25 @@
|
||||
package io.github.wulkanowy.utils.security;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.filters.SdkSuppress;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@SdkSuppress(minSdkVersion = 18)
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ScramblerTest {
|
||||
|
||||
private Context targetContext;
|
||||
|
||||
private Scrambler scramblerLoad = new Scrambler();
|
||||
|
||||
@Before
|
||||
public void setUp() throws CryptoException {
|
||||
targetContext = InstrumentationRegistry.getTargetContext();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
scramblerLoad.loadKeyStore();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = CryptoException.class)
|
||||
@SdkSuppress(maxSdkVersion = 17)
|
||||
public void testNoSuchAlgorithm() throws CryptoException {
|
||||
scramblerLoad.loadKeyStore();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decryptEncryptStringTest() throws CryptoException {
|
||||
scramblerLoad.generateNewKey("TEST", targetContext);
|
||||
Assert.assertEquals("pass",
|
||||
scramblerLoad.decryptString("TEST", scramblerLoad.encryptString("TEST", "pass")));
|
||||
}
|
||||
@SdkSuppress(minSdkVersion = 18)
|
||||
public void encryptDecryptTest() throws Exception {
|
||||
Context targetContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
@Test(expected = CryptoException.class)
|
||||
public void decryptEmptyTest() throws CryptoException {
|
||||
scramblerLoad.decryptString("", "");
|
||||
Assert.assertEquals("PASS", Scrambler.decrypt("TEST",
|
||||
Scrambler.encrypt("TEST", "PASS", targetContext)));
|
||||
}
|
||||
|
||||
@Test(expected = CryptoException.class)
|
||||
public void encryptEmptyTest() throws CryptoException {
|
||||
scramblerLoad.encryptString("", "");
|
||||
}
|
||||
|
||||
@Test(expected = CryptoException.class)
|
||||
public void generateNewKeyEmptyTest() throws CryptoException {
|
||||
scramblerLoad.generateNewKey("", targetContext);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="io.github.wulkanowy"
|
||||
android:installLocation="internalOnly">
|
||||
|
||||
@ -11,8 +10,6 @@
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<uses-sdk tools:overrideLibrary="com.thoughtbot.expandablerecyclerview" />
|
||||
|
||||
<application
|
||||
android:name=".WulkanowyApp"
|
||||
android:allowBackup="false"
|
||||
@ -25,7 +22,7 @@
|
||||
android:name=".ui.splash.SplashActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/WulkanowyTheme.noActionBar">
|
||||
android:theme="@style/WulkanowyTheme.SplashTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@ -38,12 +35,12 @@
|
||||
android:label="@string/title_activity_login"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name=".ui.main.DashboardActivity"
|
||||
android:name=".ui.main.MainActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/activity_dashboard_text" />
|
||||
|
||||
<service
|
||||
android:name=".services.jobs.FullSyncJob$SyncService"
|
||||
android:name=".services.SyncJob"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
|
||||
|
@ -1,50 +1,48 @@
|
||||
package io.github.wulkanowy;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.crashlytics.android.core.CrashlyticsCore;
|
||||
|
||||
import org.greenrobot.greendao.query.QueryBuilder;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.utils.Log;
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.di.component.ApplicationComponent;
|
||||
import io.github.wulkanowy.di.component.DaggerApplicationComponent;
|
||||
import io.github.wulkanowy.di.modules.ApplicationModule;
|
||||
|
||||
public class WulkanowyApp extends Application {
|
||||
|
||||
public static final String DEBUG_TAG = "WulaknowyActivity";
|
||||
protected ApplicationComponent applicationComponent;
|
||||
|
||||
private DaoSession daoSession;
|
||||
@Inject
|
||||
RepositoryContract repository;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
applicationComponent = DaggerApplicationComponent
|
||||
.builder()
|
||||
.applicationModule(new ApplicationModule(this))
|
||||
.build();
|
||||
applicationComponent.inject(this);
|
||||
|
||||
initializeFabric();
|
||||
if (BuildConfig.DEBUG) {
|
||||
enableDebugLog();
|
||||
}
|
||||
|
||||
initializeFabric();
|
||||
|
||||
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this, "wulkanowy-db");
|
||||
|
||||
daoSession = new DaoMaster(devOpenHelper.getWritableDb()).newSession();
|
||||
|
||||
int schemaVersion = getSharedPreferences("LoginData", Context.MODE_PRIVATE).getInt("schemaVersion", 0);
|
||||
|
||||
if (DaoMaster.SCHEMA_VERSION != schemaVersion) {
|
||||
SharedPreferences sharedPreferences = getSharedPreferences("LoginData", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putLong("userId", 0);
|
||||
editor.putInt("schemaVersion", DaoMaster.SCHEMA_VERSION);
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationComponent getApplicationComponent() {
|
||||
return applicationComponent;
|
||||
}
|
||||
|
||||
private void enableDebugLog() {
|
||||
@ -62,6 +60,6 @@ public class WulkanowyApp extends Application {
|
||||
}
|
||||
|
||||
public DaoSession getDaoSession() {
|
||||
return daoSession;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
143
app/src/main/java/io/github/wulkanowy/data/Repository.java
Normal file
143
app/src/main/java/io/github/wulkanowy/data/Repository.java
Normal file
@ -0,0 +1,143 @@
|
||||
package io.github.wulkanowy.data;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.github.wulkanowy.api.login.AccountPermissionException;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.data.db.dao.entities.GradeDao;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Week;
|
||||
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
|
||||
import io.github.wulkanowy.data.db.resources.ResourcesContract;
|
||||
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||
import io.github.wulkanowy.data.sync.SyncContract;
|
||||
import io.github.wulkanowy.data.sync.login.LoginSyncContract;
|
||||
import io.github.wulkanowy.data.sync.timetable.TimetableSyncContract;
|
||||
import io.github.wulkanowy.di.annotations.SyncGrades;
|
||||
import io.github.wulkanowy.di.annotations.SyncSubjects;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
|
||||
@Singleton
|
||||
public class Repository implements RepositoryContract {
|
||||
|
||||
private final SharedPrefContract sharedPref;
|
||||
|
||||
private final ResourcesContract resources;
|
||||
|
||||
private final DaoSession daoSession;
|
||||
|
||||
private final LoginSyncContract loginSync;
|
||||
|
||||
private final TimetableSyncContract timetableSync;
|
||||
|
||||
private final SyncContract gradeSync;
|
||||
|
||||
private final SyncContract subjectSync;
|
||||
|
||||
@Inject
|
||||
Repository(SharedPrefContract sharedPref,
|
||||
ResourcesContract resources,
|
||||
DaoSession daoSession,
|
||||
LoginSyncContract loginSync,
|
||||
TimetableSyncContract timetableSync,
|
||||
@SyncGrades SyncContract gradeSync,
|
||||
@SyncSubjects SyncContract subjectSync) {
|
||||
this.sharedPref = sharedPref;
|
||||
this.resources = resources;
|
||||
this.daoSession = daoSession;
|
||||
this.loginSync = loginSync;
|
||||
this.timetableSync = timetableSync;
|
||||
this.gradeSync = gradeSync;
|
||||
this.subjectSync = subjectSync;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCurrentUserId() {
|
||||
return sharedPref.getCurrentUserId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSymbolsKeysArray() {
|
||||
return resources.getSymbolsKeysArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSymbolsValuesArray() {
|
||||
return resources.getSymbolsValuesArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorLoginMessage(Exception e) {
|
||||
return resources.getErrorLoginMessage(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loginUser(String email, String password, String symbol)
|
||||
throws NotLoggedInErrorException, AccountPermissionException, IOException,
|
||||
CryptoException, VulcanOfflineException, BadCredentialsException {
|
||||
loginSync.loginUser(email, password, symbol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loginCurrentUser() throws NotLoggedInErrorException, AccountPermissionException,
|
||||
IOException, CryptoException, VulcanOfflineException, BadCredentialsException {
|
||||
loginSync.loginCurrentUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncGrades() throws NotLoggedInErrorException, IOException, ParseException {
|
||||
gradeSync.sync();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncSubjects() throws NotLoggedInErrorException, IOException, ParseException {
|
||||
subjectSync.sync();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncTimetable() throws NotLoggedInErrorException, IOException, ParseException {
|
||||
timetableSync.syncTimetable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncTimetable(String date) throws NotLoggedInErrorException, IOException, ParseException {
|
||||
timetableSync.syncTimetable(date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncAll() throws NotLoggedInErrorException, IOException, ParseException {
|
||||
syncSubjects();
|
||||
syncGrades();
|
||||
syncTimetable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account getCurrentUser() {
|
||||
return daoSession.getAccountDao().load(sharedPref.getCurrentUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Week getWeek(String date) {
|
||||
return daoSession.getWeekDao().queryBuilder()
|
||||
.where(WeekDao.Properties.StartDayDate.eq(date),
|
||||
WeekDao.Properties.UserId.eq(getCurrentUserId()))
|
||||
.unique();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Grade> getNewGrades() {
|
||||
return daoSession.getGradeDao().queryBuilder()
|
||||
.where(GradeDao.Properties.IsNew.eq(1))
|
||||
.list();
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package io.github.wulkanowy.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Week;
|
||||
import io.github.wulkanowy.data.db.resources.ResourcesContract;
|
||||
import io.github.wulkanowy.data.sync.login.LoginSyncContract;
|
||||
import io.github.wulkanowy.data.sync.timetable.TimetableSyncContract;
|
||||
|
||||
@Singleton
|
||||
public interface RepositoryContract extends ResourcesContract, LoginSyncContract,
|
||||
TimetableSyncContract {
|
||||
|
||||
long getCurrentUserId();
|
||||
|
||||
void syncGrades() throws NotLoggedInErrorException, IOException, ParseException;
|
||||
|
||||
void syncSubjects() throws NotLoggedInErrorException, IOException, ParseException;
|
||||
|
||||
void syncAll() throws NotLoggedInErrorException, IOException, ParseException;
|
||||
|
||||
Account getCurrentUser();
|
||||
|
||||
Week getWeek(String date);
|
||||
|
||||
List<Grade> getNewGrades();
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package io.github.wulkanowy.data.db.dao;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.di.annotations.ApplicationContext;
|
||||
import io.github.wulkanowy.di.annotations.DatabaseInfo;
|
||||
|
||||
@Singleton
|
||||
public class DbHelper extends DaoMaster.DevOpenHelper {
|
||||
|
||||
@Inject
|
||||
DbHelper(@ApplicationContext Context context, @DatabaseInfo String dbName) {
|
||||
super(context, dbName);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.DaoException;
|
||||
import org.greenrobot.greendao.annotation.Entity;
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.DaoException;
|
||||
import org.greenrobot.greendao.annotation.Entity;
|
@ -1,7 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
@ -11,13 +8,15 @@ import org.greenrobot.greendao.annotation.Generated;
|
||||
import org.greenrobot.greendao.annotation.Id;
|
||||
import org.greenrobot.greendao.annotation.Property;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
|
||||
@Entity(
|
||||
nameInDb = "Grades",
|
||||
active = true
|
||||
)
|
||||
public class Grade implements Parcelable {
|
||||
public class Grade implements Serializable {
|
||||
|
||||
@Id(autoincrement = true)
|
||||
protected Long id;
|
||||
@ -61,9 +60,7 @@ public class Grade implements Parcelable {
|
||||
@Property(nameInDb = "READ")
|
||||
private boolean read = true;
|
||||
|
||||
protected Grade(Parcel source) {
|
||||
value = source.readString();
|
||||
}
|
||||
private static final long serialVersionUID = 42L;
|
||||
|
||||
@Generated(hash = 568899968)
|
||||
public Grade(Long id, Long subjectId, Long userId, String subject, String value,
|
||||
@ -90,36 +87,6 @@ public class Grade implements Parcelable {
|
||||
public Grade() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int i) {
|
||||
parcel.writeString(subject);
|
||||
parcel.writeString(value);
|
||||
parcel.writeString(color);
|
||||
parcel.writeString(symbol);
|
||||
parcel.writeString(description);
|
||||
parcel.writeString(weight);
|
||||
parcel.writeString(date);
|
||||
parcel.writeString(teacher);
|
||||
parcel.writeString(semester);
|
||||
}
|
||||
|
||||
public static final Creator<Grade> CREATOR = new Creator<Grade>() {
|
||||
@Override
|
||||
public Grade createFromParcel(Parcel source) {
|
||||
return new Grade(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Grade[] newArray(int size) {
|
||||
return new Grade[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to resolve relations
|
||||
*/
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.DaoException;
|
||||
import org.greenrobot.greendao.annotation.Entity;
|
||||
@ -7,12 +7,14 @@ import org.greenrobot.greendao.annotation.Id;
|
||||
import org.greenrobot.greendao.annotation.Index;
|
||||
import org.greenrobot.greendao.annotation.Property;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity(
|
||||
nameInDb = "Lessons",
|
||||
active = true,
|
||||
indexes ={@Index(value = "dayId,date,startTime,endTime", unique = true)}
|
||||
indexes = {@Index(value = "dayId,date,startTime,endTime", unique = true)}
|
||||
)
|
||||
public class Lesson {
|
||||
public class Lesson implements Serializable {
|
||||
|
||||
@Id(autoincrement = true)
|
||||
private Long id;
|
||||
@ -65,6 +67,8 @@ public class Lesson {
|
||||
@Property(nameInDb = "IS_NEW_MOVED_IN_CANCELED")
|
||||
private boolean isNewMovedInOrChanged = false;
|
||||
|
||||
private static final long serialVersionUID = 42L;
|
||||
|
||||
/**
|
||||
* Used to resolve relations
|
||||
*/
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.DaoException;
|
||||
import org.greenrobot.greendao.annotation.Entity;
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.db.dao.entities;
|
||||
package io.github.wulkanowy.data.db.dao.entities;
|
||||
|
||||
import org.greenrobot.greendao.DaoException;
|
||||
import org.greenrobot.greendao.annotation.Entity;
|
@ -0,0 +1,59 @@
|
||||
package io.github.wulkanowy.data.db.resources;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.di.annotations.ApplicationContext;
|
||||
import io.github.wulkanowy.utils.AppConstant;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
|
||||
@Singleton
|
||||
public class AppResources implements ResourcesContract {
|
||||
|
||||
private Resources resources;
|
||||
|
||||
@Inject
|
||||
AppResources(@ApplicationContext Context context) {
|
||||
resources = context.getResources();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSymbolsKeysArray() {
|
||||
return resources.getStringArray(R.array.symbols);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSymbolsValuesArray() {
|
||||
return resources.getStringArray(R.array.symbols_values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorLoginMessage(Exception exception) {
|
||||
LogUtils.error(AppConstant.APP_NAME + " encountered a error", exception);
|
||||
|
||||
if (exception instanceof CryptoException) {
|
||||
return resources.getString(R.string.encrypt_failed_text);
|
||||
} else if (exception instanceof UnknownHostException) {
|
||||
return resources.getString(R.string.noInternet_text);
|
||||
} else if (exception instanceof SocketTimeoutException) {
|
||||
return resources.getString(R.string.generic_timeout_error);
|
||||
} else if (exception instanceof NotLoggedInErrorException || exception instanceof IOException) {
|
||||
return resources.getString(R.string.login_denied_text);
|
||||
} else if (exception instanceof VulcanOfflineException) {
|
||||
return resources.getString(R.string.error_host_offline);
|
||||
} else {
|
||||
return exception.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package io.github.wulkanowy.data.db.resources;
|
||||
|
||||
public interface ResourcesContract {
|
||||
|
||||
String[] getSymbolsKeysArray();
|
||||
|
||||
String[] getSymbolsValuesArray();
|
||||
|
||||
String getErrorLoginMessage(Exception e);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package io.github.wulkanowy.data.db.shared;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.github.wulkanowy.di.annotations.ApplicationContext;
|
||||
import io.github.wulkanowy.di.annotations.SharedPreferencesInfo;
|
||||
|
||||
@Singleton
|
||||
public class SharedPref implements SharedPrefContract {
|
||||
|
||||
private static final String SHARED_KEY_USER_ID = "USER_ID";
|
||||
|
||||
private final SharedPreferences sharedPreferences;
|
||||
|
||||
@Inject
|
||||
SharedPref(@ApplicationContext Context context, @SharedPreferencesInfo String sharedName) {
|
||||
sharedPreferences = context.getSharedPreferences(sharedName, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCurrentUserId() {
|
||||
return sharedPreferences.getLong(SHARED_KEY_USER_ID, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentUserId(long userId) {
|
||||
sharedPreferences.edit().putLong(SHARED_KEY_USER_ID, userId).apply();
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package io.github.wulkanowy.data.db.shared;
|
||||
|
||||
public interface SharedPrefContract {
|
||||
|
||||
long getCurrentUserId();
|
||||
|
||||
void setCurrentUserId(long userId);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.data.sync;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
|
||||
public interface SyncContract {
|
||||
|
||||
void sync() throws NotLoggedInErrorException, IOException, ParseException;
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package io.github.wulkanowy.data.sync.grades;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.data.db.dao.entities.SubjectDao;
|
||||
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||
import io.github.wulkanowy.data.sync.SyncContract;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.EntitiesCompare;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
|
||||
@Singleton
|
||||
public class GradeSync implements SyncContract {
|
||||
|
||||
private final DaoSession daoSession;
|
||||
|
||||
private final Vulcan vulcan;
|
||||
|
||||
private final SharedPrefContract sharedPref;
|
||||
|
||||
@Inject
|
||||
GradeSync(DaoSession daoSession, SharedPrefContract sharedPref, Vulcan vulcan) {
|
||||
this.daoSession = daoSession;
|
||||
this.sharedPref = sharedPref;
|
||||
this.vulcan = vulcan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync() throws IOException, NotLoggedInErrorException, ParseException {
|
||||
|
||||
long userId = sharedPref.getCurrentUserId();
|
||||
|
||||
Account account = daoSession.getAccountDao().load(userId);
|
||||
account.resetGradeList();
|
||||
account.resetSubjectList();
|
||||
|
||||
List<Grade> gradesFromNet = DataObjectConverter
|
||||
.gradesToGradeEntities(vulcan.getGradesList().getAll());
|
||||
List<Grade> gradesFromDb = account.getGradeList();
|
||||
|
||||
List<Grade> updatedGrades = EntitiesCompare.compareGradeList(gradesFromNet, gradesFromDb);
|
||||
|
||||
daoSession.getGradeDao().deleteInTx(gradesFromDb);
|
||||
|
||||
List<Grade> lastList = new ArrayList<>();
|
||||
|
||||
for (Grade grade : updatedGrades) {
|
||||
grade.setUserId(userId);
|
||||
grade.setSubjectId(daoSession.getSubjectDao().queryBuilder()
|
||||
.where(SubjectDao.Properties.Name.eq(grade.getSubject()),
|
||||
SubjectDao.Properties.UserId.eq(userId))
|
||||
.build()
|
||||
.uniqueOrThrow().getId());
|
||||
lastList.add(grade);
|
||||
}
|
||||
|
||||
daoSession.getGradeDao().insertInTx(lastList);
|
||||
|
||||
LogUtils.debug("Synchronization grades (amount = " + lastList.size() + ")");
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package io.github.wulkanowy.data.sync.login;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.login.AccountPermissionException;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||
import io.github.wulkanowy.di.annotations.ApplicationContext;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
import io.github.wulkanowy.utils.security.Scrambler;
|
||||
|
||||
@Singleton
|
||||
public class LoginSync implements LoginSyncContract {
|
||||
|
||||
private final DaoSession daoSession;
|
||||
|
||||
private final SharedPrefContract sharedPref;
|
||||
|
||||
private final Vulcan vulcan;
|
||||
|
||||
private final Context context;
|
||||
|
||||
@Inject
|
||||
LoginSync(DaoSession daoSession, SharedPrefContract sharedPref,
|
||||
Vulcan vulcan, @ApplicationContext Context context) {
|
||||
this.daoSession = daoSession;
|
||||
this.sharedPref = sharedPref;
|
||||
this.vulcan = vulcan;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loginUser(String email, String password, String symbol)
|
||||
throws NotLoggedInErrorException, AccountPermissionException, IOException,
|
||||
CryptoException, VulcanOfflineException, BadCredentialsException {
|
||||
|
||||
LogUtils.debug("Login new user email=" + email);
|
||||
|
||||
vulcan.login(email, password, symbol);
|
||||
|
||||
Account account = new Account()
|
||||
.setName(vulcan.getBasicInformation().getPersonalData().getFirstAndLastName())
|
||||
.setEmail(email)
|
||||
.setPassword(Scrambler.encrypt(email, password, context))
|
||||
.setSymbol(vulcan.getSymbol())
|
||||
.setSnpId(vulcan.getStudentAndParent().getId());
|
||||
|
||||
sharedPref.setCurrentUserId(daoSession.getAccountDao().insert(account));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loginCurrentUser() throws NotLoggedInErrorException, AccountPermissionException,
|
||||
IOException, CryptoException, VulcanOfflineException, BadCredentialsException {
|
||||
|
||||
long userId = sharedPref.getCurrentUserId();
|
||||
|
||||
if (userId == 0) {
|
||||
throw new IOException("Can't find logged user");
|
||||
}
|
||||
|
||||
LogUtils.debug("Login current user id=" + userId);
|
||||
|
||||
Account account = daoSession.getAccountDao().load(userId);
|
||||
|
||||
vulcan.login(account.getEmail(),
|
||||
Scrambler.decrypt(account.getEmail(), account.getPassword()),
|
||||
account.getSymbol(),
|
||||
account.getSnpId());
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package io.github.wulkanowy.data.sync.login;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.github.wulkanowy.api.login.AccountPermissionException;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
|
||||
public interface LoginSyncContract {
|
||||
|
||||
void loginUser(String email, String password, String symbol)
|
||||
throws NotLoggedInErrorException, AccountPermissionException, IOException,
|
||||
CryptoException, VulcanOfflineException, BadCredentialsException;
|
||||
|
||||
void loginCurrentUser() throws NotLoggedInErrorException, AccountPermissionException, IOException,
|
||||
CryptoException, VulcanOfflineException, BadCredentialsException;
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package io.github.wulkanowy.data.sync.subjects;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.data.db.dao.entities.SubjectDao;
|
||||
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||
import io.github.wulkanowy.data.sync.SyncContract;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
|
||||
@Singleton
|
||||
public class SubjectSync implements SyncContract {
|
||||
|
||||
private final SubjectDao subjectDao;
|
||||
|
||||
private final Vulcan vulcan;
|
||||
|
||||
private final SharedPrefContract sharedPref;
|
||||
|
||||
@Inject
|
||||
SubjectSync(DaoSession daoSession, SharedPrefContract sharedPref, Vulcan vulcan) {
|
||||
this.subjectDao = daoSession.getSubjectDao();
|
||||
this.sharedPref = sharedPref;
|
||||
this.vulcan = vulcan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync() throws NotLoggedInErrorException, IOException, ParseException {
|
||||
|
||||
long userId = sharedPref.getCurrentUserId();
|
||||
|
||||
List<Subject> subjectsFromNet = DataObjectConverter
|
||||
.subjectsToSubjectEntities(vulcan.getSubjectsList().getAll());
|
||||
|
||||
subjectDao.deleteInTx(subjectDao.queryBuilder()
|
||||
.where(SubjectDao.Properties.UserId.eq(userId))
|
||||
.build()
|
||||
.list());
|
||||
|
||||
List<Subject> lastList = new ArrayList<>();
|
||||
|
||||
for (Subject subject : subjectsFromNet) {
|
||||
subject.setUserId(userId);
|
||||
lastList.add(subject);
|
||||
}
|
||||
|
||||
subjectDao.insertInTx(lastList);
|
||||
|
||||
LogUtils.debug("Synchronization subjects (amount = " + lastList.size() + ")");
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
package io.github.wulkanowy.data.sync.timetable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Day;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DayDao;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Lesson;
|
||||
import io.github.wulkanowy.data.db.dao.entities.LessonDao;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Week;
|
||||
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
|
||||
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import io.github.wulkanowy.utils.TimeUtils;
|
||||
|
||||
@Singleton
|
||||
public class TimetableSync implements TimetableSyncContract {
|
||||
|
||||
private final DaoSession daoSession;
|
||||
|
||||
private final Vulcan vulcan;
|
||||
|
||||
private final SharedPrefContract sharedPref;
|
||||
|
||||
@Inject
|
||||
TimetableSync(DaoSession daoSession, SharedPrefContract sharedPref, Vulcan vulcan) {
|
||||
this.daoSession = daoSession;
|
||||
this.sharedPref = sharedPref;
|
||||
this.vulcan = vulcan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncTimetable(String date) throws NotLoggedInErrorException, IOException, ParseException {
|
||||
long userId = sharedPref.getCurrentUserId();
|
||||
|
||||
io.github.wulkanowy.api.timetable.Week weekFromNet = date == null ? vulcan.getTimetable().getWeekTable()
|
||||
: vulcan.getTimetable().getWeekTable(String.valueOf(TimeUtils.getNetTicks(date)));
|
||||
|
||||
Week weekFromDb = daoSession.getWeekDao().queryBuilder()
|
||||
.where(WeekDao.Properties.UserId.eq(userId),
|
||||
WeekDao.Properties.StartDayDate.eq(weekFromNet.getStartDayDate()))
|
||||
.unique();
|
||||
|
||||
Long weekId;
|
||||
|
||||
if (weekFromDb == null) {
|
||||
Week weekFromNetEntity = DataObjectConverter.weekToWeekEntity(weekFromNet).setUserId(userId);
|
||||
weekId = daoSession.getWeekDao().insert(weekFromNetEntity);
|
||||
} else {
|
||||
weekId = weekFromDb.getId();
|
||||
}
|
||||
|
||||
List<io.github.wulkanowy.api.timetable.Day> dayListFromNet = weekFromNet.getDays();
|
||||
|
||||
List<Lesson> updatedLessonList = new ArrayList<>();
|
||||
|
||||
for (io.github.wulkanowy.api.timetable.Day dayFromNet : dayListFromNet) {
|
||||
Day dayFromNetEntity = DataObjectConverter.dayToDayEntity(dayFromNet);
|
||||
|
||||
Day dayFromDb = daoSession.getDayDao().queryBuilder()
|
||||
.where(DayDao.Properties.UserId.eq(userId),
|
||||
DayDao.Properties.WeekId.eq(weekId),
|
||||
DayDao.Properties.Date.eq(dayFromNetEntity.getDate()))
|
||||
.unique();
|
||||
|
||||
dayFromNetEntity.setUserId(userId);
|
||||
dayFromNetEntity.setWeekId(weekId);
|
||||
|
||||
Long dayId;
|
||||
|
||||
if (dayFromDb != null) {
|
||||
dayFromNetEntity.setId(dayFromDb.getId());
|
||||
daoSession.getDayDao().save(dayFromNetEntity);
|
||||
dayId = dayFromNetEntity.getId();
|
||||
} else {
|
||||
dayId = daoSession.getDayDao().insert(dayFromNetEntity);
|
||||
}
|
||||
|
||||
List<Lesson> lessonListFromNetEntities = DataObjectConverter
|
||||
.lessonsToLessonsEntities(dayFromNet.getLessons());
|
||||
|
||||
for (Lesson lessonFromNetEntity : lessonListFromNetEntities) {
|
||||
Lesson lessonFromDb = daoSession.getLessonDao().queryBuilder()
|
||||
.where(LessonDao.Properties.DayId.eq(dayId),
|
||||
LessonDao.Properties.Date.eq(lessonFromNetEntity.getDate()),
|
||||
LessonDao.Properties.StartTime.eq(lessonFromNetEntity.getStartTime()),
|
||||
LessonDao.Properties.EndTime.eq(lessonFromNetEntity.getEndTime()))
|
||||
.unique();
|
||||
|
||||
if (lessonFromDb != null) {
|
||||
lessonFromNetEntity.setId(lessonFromDb.getId());
|
||||
}
|
||||
|
||||
lessonFromNetEntity.setDayId(dayFromNetEntity.getId());
|
||||
|
||||
if (!"".equals(lessonFromNetEntity.getSubject())) {
|
||||
updatedLessonList.add(lessonFromNetEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
daoSession.getLessonDao().saveInTx(updatedLessonList);
|
||||
|
||||
LogUtils.debug("Synchronization lessons (amount = " + updatedLessonList.size() + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncTimetable() throws NotLoggedInErrorException, IOException, ParseException {
|
||||
syncTimetable(null);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package io.github.wulkanowy.data.sync.timetable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
|
||||
public interface TimetableSyncContract {
|
||||
|
||||
void syncTimetable(String date) throws NotLoggedInErrorException, IOException, ParseException;
|
||||
|
||||
void syncTimetable() throws NotLoggedInErrorException, IOException, ParseException;
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package io.github.wulkanowy.db.dao;
|
||||
|
||||
import org.greenrobot.greendao.query.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.db.dao.entities.GradeDao;
|
||||
|
||||
public class DatabaseAccess {
|
||||
|
||||
public List<Grade> getNewGrades(DaoSession daoSession) {
|
||||
Query<Grade> gradeQuery = daoSession.getGradeDao().queryBuilder()
|
||||
.where(GradeDao.Properties.IsNew.eq(1))
|
||||
.build();
|
||||
|
||||
return gradeQuery.list();
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.di.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ActivityContext {
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.di.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ApplicationContext {
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.di.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DatabaseInfo {
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.di.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Scope;
|
||||
|
||||
@Scope
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PerActivity {
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.di.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Scope;
|
||||
|
||||
@Scope
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PerFragment {
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.di.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SharedPreferencesInfo {
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.di.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SyncGrades {
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.github.wulkanowy.di.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SyncSubjects {
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package io.github.wulkanowy.di.component;
|
||||
|
||||
import dagger.Component;
|
||||
import io.github.wulkanowy.di.annotations.PerActivity;
|
||||
import io.github.wulkanowy.di.modules.ActivityModule;
|
||||
import io.github.wulkanowy.ui.login.LoginActivity;
|
||||
import io.github.wulkanowy.ui.main.MainActivity;
|
||||
import io.github.wulkanowy.ui.splash.SplashActivity;
|
||||
|
||||
@PerActivity
|
||||
@Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class)
|
||||
public interface ActivityComponent {
|
||||
|
||||
void inject(SplashActivity splashActivity);
|
||||
|
||||
void inject(LoginActivity loginActivity);
|
||||
|
||||
void inject(MainActivity mainActivity);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package io.github.wulkanowy.di.component;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Component;
|
||||
import io.github.wulkanowy.WulkanowyApp;
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.di.annotations.ApplicationContext;
|
||||
import io.github.wulkanowy.di.modules.ApplicationModule;
|
||||
import io.github.wulkanowy.services.SyncJob;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = ApplicationModule.class)
|
||||
public interface ApplicationComponent {
|
||||
|
||||
@ApplicationContext
|
||||
Context getContext();
|
||||
|
||||
RepositoryContract getRepository();
|
||||
|
||||
void inject(WulkanowyApp wulkanowyApp);
|
||||
|
||||
void inject(SyncJob syncJob);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package io.github.wulkanowy.di.component;
|
||||
|
||||
import dagger.Component;
|
||||
import io.github.wulkanowy.di.annotations.PerFragment;
|
||||
import io.github.wulkanowy.di.modules.FragmentModule;
|
||||
import io.github.wulkanowy.ui.main.attendance.AttendanceFragment;
|
||||
import io.github.wulkanowy.ui.main.dashboard.DashboardFragment;
|
||||
import io.github.wulkanowy.ui.main.grades.GradesFragment;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetableFragment;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetableTabFragment;
|
||||
|
||||
@PerFragment
|
||||
@Component(dependencies = ApplicationComponent.class, modules = FragmentModule.class)
|
||||
public interface FragmentComponent {
|
||||
|
||||
void inject(GradesFragment gradesFragment);
|
||||
|
||||
void inject(AttendanceFragment attendanceFragment);
|
||||
|
||||
void inject(DashboardFragment dashboardFragment);
|
||||
|
||||
void inject(TimetableFragment timetableFragment);
|
||||
|
||||
void inject(TimetableTabFragment timetableTabFragment);
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package io.github.wulkanowy.di.modules;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import io.github.wulkanowy.di.annotations.ActivityContext;
|
||||
import io.github.wulkanowy.di.annotations.PerActivity;
|
||||
import io.github.wulkanowy.ui.login.LoginContract;
|
||||
import io.github.wulkanowy.ui.login.LoginPresenter;
|
||||
import io.github.wulkanowy.ui.main.MainContract;
|
||||
import io.github.wulkanowy.ui.main.MainPagerAdapter;
|
||||
import io.github.wulkanowy.ui.main.MainPresenter;
|
||||
import io.github.wulkanowy.ui.splash.SplashContract;
|
||||
import io.github.wulkanowy.ui.splash.SplashPresenter;
|
||||
|
||||
@Module
|
||||
public class ActivityModule {
|
||||
|
||||
private AppCompatActivity activity;
|
||||
|
||||
public ActivityModule(AppCompatActivity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
@ActivityContext
|
||||
@Provides
|
||||
Context provideContext() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
@Provides
|
||||
AppCompatActivity provideActivity() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
@PerActivity
|
||||
@Provides
|
||||
SplashContract.Presenter provideSplashPresenter
|
||||
(SplashPresenter splashPresenter) {
|
||||
return splashPresenter;
|
||||
}
|
||||
|
||||
@PerActivity
|
||||
@Provides
|
||||
LoginContract.Presenter provideLoginPresenter
|
||||
(LoginPresenter loginPresenter) {
|
||||
return loginPresenter;
|
||||
}
|
||||
|
||||
@PerActivity
|
||||
@Provides
|
||||
MainContract.Presenter provideMainPresenter
|
||||
(MainPresenter mainPresenter) {
|
||||
return mainPresenter;
|
||||
}
|
||||
|
||||
@Provides
|
||||
MainPagerAdapter provideMainPagerAdapter() {
|
||||
return new MainPagerAdapter(activity.getSupportFragmentManager());
|
||||
}
|
||||
}
|
@ -3,13 +3,41 @@ package io.github.wulkanowy.di.modules;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
|
||||
import com.firebase.jobdispatcher.GooglePlayDriver;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.data.Repository;
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.data.db.dao.DbHelper;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.data.db.resources.AppResources;
|
||||
import io.github.wulkanowy.data.db.resources.ResourcesContract;
|
||||
import io.github.wulkanowy.data.db.shared.SharedPref;
|
||||
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||
import io.github.wulkanowy.data.sync.SyncContract;
|
||||
import io.github.wulkanowy.data.sync.grades.GradeSync;
|
||||
import io.github.wulkanowy.data.sync.login.LoginSync;
|
||||
import io.github.wulkanowy.data.sync.login.LoginSyncContract;
|
||||
import io.github.wulkanowy.data.sync.subjects.SubjectSync;
|
||||
import io.github.wulkanowy.data.sync.timetable.TimetableSync;
|
||||
import io.github.wulkanowy.data.sync.timetable.TimetableSyncContract;
|
||||
import io.github.wulkanowy.di.annotations.ApplicationContext;
|
||||
import io.github.wulkanowy.di.annotations.DatabaseInfo;
|
||||
import io.github.wulkanowy.di.annotations.SharedPreferencesInfo;
|
||||
import io.github.wulkanowy.di.annotations.SyncGrades;
|
||||
import io.github.wulkanowy.di.annotations.SyncSubjects;
|
||||
import io.github.wulkanowy.utils.AppConstant;
|
||||
|
||||
@Module
|
||||
public class ApplicationModule {
|
||||
|
||||
protected final Application application;
|
||||
private final Application application;
|
||||
|
||||
public ApplicationModule(Application application) {
|
||||
this.application = application;
|
||||
@ -20,8 +48,82 @@ public class ApplicationModule {
|
||||
return application;
|
||||
}
|
||||
|
||||
@ApplicationContext
|
||||
@Provides
|
||||
Context provideAppContext() {
|
||||
return application;
|
||||
}
|
||||
|
||||
@DatabaseInfo
|
||||
@Provides
|
||||
String provideDatabaseName() {
|
||||
return AppConstant.DATABASE_NAME;
|
||||
}
|
||||
|
||||
@SharedPreferencesInfo
|
||||
@Provides
|
||||
String provideSharedPreferencesName() {
|
||||
return AppConstant.SHARED_PREFERENCES_NAME;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
DaoSession provideDaoSession(DbHelper dbHelper) {
|
||||
return new DaoMaster(dbHelper.getWritableDb()).newSession();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
Vulcan provideVulcan() {
|
||||
return new Vulcan();
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
RepositoryContract provideRepository(Repository repository) {
|
||||
return repository;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
SharedPrefContract provideSharedPref(SharedPref sharedPref) {
|
||||
return sharedPref;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
ResourcesContract provideAppResources(AppResources appResources) {
|
||||
return appResources;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
LoginSyncContract provideLoginSync(LoginSync loginSync) {
|
||||
return loginSync;
|
||||
}
|
||||
|
||||
@SyncGrades
|
||||
@Singleton
|
||||
@Provides
|
||||
SyncContract provideGradesSync(GradeSync gradeSync) {
|
||||
return gradeSync;
|
||||
}
|
||||
|
||||
@SyncSubjects
|
||||
@Singleton
|
||||
@Provides
|
||||
SyncContract provideSubjectSync(SubjectSync subjectSync) {
|
||||
return subjectSync;
|
||||
}
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
TimetableSyncContract provideTimetableSync(TimetableSync timetableSync) {
|
||||
return timetableSync;
|
||||
}
|
||||
|
||||
@Provides
|
||||
FirebaseJobDispatcher provideDispatcher() {
|
||||
return new FirebaseJobDispatcher(new GooglePlayDriver(application));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
package io.github.wulkanowy.di.modules;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import io.github.wulkanowy.di.annotations.PerFragment;
|
||||
import io.github.wulkanowy.ui.main.attendance.AttendanceContract;
|
||||
import io.github.wulkanowy.ui.main.attendance.AttendancePresenter;
|
||||
import io.github.wulkanowy.ui.main.dashboard.DashboardContract;
|
||||
import io.github.wulkanowy.ui.main.dashboard.DashboardPresenter;
|
||||
import io.github.wulkanowy.ui.main.grades.GradeHeaderItem;
|
||||
import io.github.wulkanowy.ui.main.grades.GradesContract;
|
||||
import io.github.wulkanowy.ui.main.grades.GradesPresenter;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetableContract;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetableHeaderItem;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetablePagerAdapter;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetablePresenter;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetableTabContract;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetableTabPresenter;
|
||||
|
||||
@Module
|
||||
public class FragmentModule {
|
||||
|
||||
private final Fragment fragment;
|
||||
|
||||
public FragmentModule(Fragment fragment) {
|
||||
this.fragment = fragment;
|
||||
}
|
||||
|
||||
@PerFragment
|
||||
@Provides
|
||||
GradesContract.Presenter provideGradesPresenter(GradesPresenter gradesPresenter) {
|
||||
return gradesPresenter;
|
||||
}
|
||||
|
||||
@PerFragment
|
||||
@Provides
|
||||
AttendanceContract.Presenter provideAttendancePresenter(AttendancePresenter attendancePresenter) {
|
||||
return attendancePresenter;
|
||||
}
|
||||
|
||||
@PerFragment
|
||||
@Provides
|
||||
DashboardContract.Presenter provideDashboardPresenter(DashboardPresenter dashboardPresenter) {
|
||||
return dashboardPresenter;
|
||||
}
|
||||
|
||||
@PerFragment
|
||||
@Provides
|
||||
TimetableContract.Presenter provideTimetablePresenter(TimetablePresenter timetablePresenter) {
|
||||
return timetablePresenter;
|
||||
}
|
||||
|
||||
@PerFragment
|
||||
@Provides
|
||||
TimetableTabContract.Presenter provideTimetableTabPresenter(TimetableTabPresenter timetableTabPresenter) {
|
||||
return timetableTabPresenter;
|
||||
}
|
||||
|
||||
@Provides
|
||||
TimetablePagerAdapter provideTimetablePagerAdapter() {
|
||||
return new TimetablePagerAdapter(fragment.getChildFragmentManager());
|
||||
}
|
||||
|
||||
@Provides
|
||||
FlexibleAdapter<GradeHeaderItem> provideGradesAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
|
||||
@Provides
|
||||
FlexibleAdapter<TimetableHeaderItem> provideTimetableTabAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package io.github.wulkanowy.services;
|
||||
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
class NotificationService {
|
||||
|
||||
private static final String CHANNEL_ID = "Wulkanowy_New_Grade_Channel";
|
||||
|
||||
private static final String CHANNEL_NAME = "New Grade Channel";
|
||||
|
||||
private NotificationManager manager;
|
||||
|
||||
private Context context;
|
||||
|
||||
NotificationService(Context context) {
|
||||
this.context = context;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createChannel();
|
||||
}
|
||||
}
|
||||
|
||||
void notify(Notification notification) {
|
||||
getManager().notify(new Random().nextInt(1000), notification);
|
||||
}
|
||||
|
||||
NotificationCompat.Builder notificationBuilder() {
|
||||
return new NotificationCompat.Builder(context, CHANNEL_ID);
|
||||
}
|
||||
|
||||
@TargetApi(26)
|
||||
private void createChannel() {
|
||||
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
|
||||
NotificationManager.IMPORTANCE_HIGH);
|
||||
notificationChannel.enableLights(true);
|
||||
notificationChannel.enableVibration(true);
|
||||
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
|
||||
getManager().createNotificationChannel(notificationChannel);
|
||||
}
|
||||
|
||||
private NotificationManager getManager() {
|
||||
if (manager == null) {
|
||||
manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
}
|
114
app/src/main/java/io/github/wulkanowy/services/SyncJob.java
Normal file
114
app/src/main/java/io/github/wulkanowy/services/SyncJob.java
Normal file
@ -0,0 +1,114 @@
|
||||
package io.github.wulkanowy.services;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import com.firebase.jobdispatcher.Constraint;
|
||||
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
|
||||
import com.firebase.jobdispatcher.GooglePlayDriver;
|
||||
import com.firebase.jobdispatcher.JobParameters;
|
||||
import com.firebase.jobdispatcher.JobService;
|
||||
import com.firebase.jobdispatcher.Lifetime;
|
||||
import com.firebase.jobdispatcher.RetryStrategy;
|
||||
import com.firebase.jobdispatcher.SimpleJobService;
|
||||
import com.firebase.jobdispatcher.Trigger;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.WulkanowyApp;
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.ui.main.MainActivity;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
|
||||
public class SyncJob extends SimpleJobService {
|
||||
|
||||
private static final int DEFAULT_INTERVAL_START = 60 * 50;
|
||||
|
||||
private static final int DEFAULT_INTERVAL_END = DEFAULT_INTERVAL_START + (60 * 40);
|
||||
|
||||
public static final String EXTRA_INTENT_KEY = "cardId";
|
||||
|
||||
private List<Grade> gradeList;
|
||||
|
||||
@Inject
|
||||
RepositoryContract repository;
|
||||
|
||||
public static void start(Context context) {
|
||||
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
|
||||
|
||||
dispatcher.mustSchedule(dispatcher.newJobBuilder()
|
||||
.setLifetime(Lifetime.FOREVER)
|
||||
.setService(SyncJob.class)
|
||||
.setTag("SyncJob")
|
||||
.setRecurring(true)
|
||||
.setTrigger(Trigger.executionWindow(DEFAULT_INTERVAL_START, DEFAULT_INTERVAL_END))
|
||||
.setConstraints(Constraint.ON_ANY_NETWORK)
|
||||
.setReplaceCurrent(false)
|
||||
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
((WulkanowyApp) getApplication()).getApplicationComponent().inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onRunJob(JobParameters job) {
|
||||
try {
|
||||
repository.loginCurrentUser();
|
||||
repository.syncAll();
|
||||
|
||||
gradeList = repository.getNewGrades();
|
||||
|
||||
if (!gradeList.isEmpty()) {
|
||||
showNotification();
|
||||
}
|
||||
return JobService.RESULT_SUCCESS;
|
||||
} catch (Exception e) {
|
||||
LogUtils.error("During background synchronization an error occurred", e);
|
||||
return JobService.RESULT_FAIL_RETRY;
|
||||
}
|
||||
}
|
||||
|
||||
private void showNotification() {
|
||||
NotificationService service = new NotificationService(getApplicationContext());
|
||||
|
||||
service.notify(service.notificationBuilder()
|
||||
.setContentTitle(getStringTitle())
|
||||
.setContentText(getStringContent())
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setAutoCancel(true)
|
||||
.setDefaults(NotificationCompat.DEFAULT_ALL)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setColor(getResources().getColor(R.color.colorPrimary))
|
||||
.setContentIntent(PendingIntent.getActivity(getApplicationContext(), 0,
|
||||
MainActivity.getStartIntent(getApplicationContext()).putExtra(EXTRA_INTENT_KEY, 0)
|
||||
, 0
|
||||
))
|
||||
.build());
|
||||
}
|
||||
|
||||
private String getStringTitle() {
|
||||
if (gradeList.size() == 1) {
|
||||
return getResources().getQuantityString(R.plurals.newGradePlurals, 1);
|
||||
} else {
|
||||
return getResources().getQuantityString(R.plurals.newGradePlurals, 2);
|
||||
}
|
||||
}
|
||||
|
||||
private String getStringContent() {
|
||||
if (gradeList.size() == 1) {
|
||||
return gradeList.get(0).getSubject();
|
||||
} else {
|
||||
return getResources().getQuantityString(R.plurals.receivedNewGradePlurals,
|
||||
gradeList.size(), gradeList.size());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,189 +0,0 @@
|
||||
package io.github.wulkanowy.services;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.DownloadManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.javiersantos.appupdater.AppUpdaterUtils;
|
||||
import com.github.javiersantos.appupdater.enums.AppUpdaterError;
|
||||
import com.github.javiersantos.appupdater.enums.UpdateFrom;
|
||||
import com.github.javiersantos.appupdater.objects.Update;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import io.github.wulkanowy.BuildConfig;
|
||||
import io.github.wulkanowy.R;
|
||||
|
||||
public class Updater {
|
||||
|
||||
private static final String DEBUG_TAG = "WulkanowyUpdater";
|
||||
|
||||
private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 0;
|
||||
|
||||
private Activity activity;
|
||||
|
||||
private Update update;
|
||||
|
||||
private DownloadManager downloadManager;
|
||||
|
||||
private BroadcastReceiver onComplete = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
DownloadManager.Query query = new DownloadManager.Query();
|
||||
Cursor c = downloadManager.query(query);
|
||||
if (c.moveToFirst()) {
|
||||
String uriString = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
|
||||
|
||||
if (uriString.substring(0, 7).matches("file://")) {
|
||||
uriString = uriString.substring(7);
|
||||
}
|
||||
|
||||
File file = new File(uriString);
|
||||
|
||||
Intent install;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
install = new Intent(Intent.ACTION_INSTALL_PACKAGE);
|
||||
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
install.setData(FileProvider.getUriForFile(context,
|
||||
BuildConfig.APPLICATION_ID + ".fileprovider", file));
|
||||
} else {
|
||||
install = new Intent(Intent.ACTION_VIEW);
|
||||
install.setDataAndType(Uri.parse("file://" + file.getAbsolutePath()),
|
||||
"application/vnd.android.package-archive");
|
||||
}
|
||||
|
||||
context.startActivity(install);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Updater(Activity activity) {
|
||||
this.activity = activity;
|
||||
|
||||
downloadManager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
activity.registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
|
||||
}
|
||||
|
||||
private void downloadUpdate() {
|
||||
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
startDownload();
|
||||
} else {
|
||||
requestWriteStoragePermission();
|
||||
}
|
||||
}
|
||||
|
||||
private void requestWriteStoragePermission() {
|
||||
ActivityCompat.requestPermissions(activity,
|
||||
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||
PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
|
||||
}
|
||||
|
||||
private void startDownload() {
|
||||
Snackbar.make(activity.findViewById(R.id.fragment_container), "Downloading started.", Snackbar.LENGTH_SHORT).show();
|
||||
|
||||
String path = Environment.getExternalStorageDirectory().toString() + File.separator +
|
||||
Environment.DIRECTORY_DOWNLOADS + File.separator + "wulkanowy";
|
||||
|
||||
File dir = new File(path);
|
||||
if(!dir.mkdirs()) {
|
||||
for (String aChildren : dir.list()) {
|
||||
new File(dir, aChildren).delete();
|
||||
}
|
||||
}
|
||||
|
||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(update.getUrlToDownload().toString()))
|
||||
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE)
|
||||
.setAllowedOverRoaming(false)
|
||||
.setTitle("Wulkanowy v" + update.getLatestVersionCode())
|
||||
.setDescription(update.getLatestVersion())
|
||||
.setVisibleInDownloadsUi(true)
|
||||
.setMimeType("application/vnd.android.package-archive")
|
||||
.setDestinationUri(Uri.fromFile(new File(path + File.separator + update.getLatestVersion() + ".apk")));
|
||||
|
||||
downloadManager.enqueue(request);
|
||||
}
|
||||
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull int[] grantResults) {
|
||||
if (requestCode == PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE) {
|
||||
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
downloadUpdate();
|
||||
} else {
|
||||
Snackbar.make(activity.findViewById(R.id.fragment_container),
|
||||
"Write storage permission request was denied.",
|
||||
Snackbar.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Updater checkForUpdates() {
|
||||
AppUpdaterUtils appUpdaterUtils = new AppUpdaterUtils(activity)
|
||||
.setUpdateFrom(UpdateFrom.JSON)
|
||||
.setUpdateJSON(BuildConfig.UPDATE_URL)
|
||||
.withListener(new AppUpdaterUtils.UpdateListener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(final Update currentUpdate, Boolean isUpdateAvailable) {
|
||||
Log.d(DEBUG_TAG, "Latest Version: " + currentUpdate.getLatestVersion());
|
||||
Log.d(DEBUG_TAG, "Latest Version Code: " + currentUpdate.getLatestVersionCode().toString());
|
||||
Log.d(DEBUG_TAG, "URL: " + currentUpdate.getUrlToDownload().toString());
|
||||
Log.d(DEBUG_TAG, "Is update available?: " + Boolean.toString(isUpdateAvailable));
|
||||
|
||||
update = currentUpdate;
|
||||
showDialog(isUpdateAvailable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(AppUpdaterError error) {
|
||||
Log.e(DEBUG_TAG, "Something went wrong");
|
||||
Log.e(DEBUG_TAG, error.toString());
|
||||
}
|
||||
});
|
||||
appUpdaterUtils.start();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private void showDialog(boolean isUpdateAvailable) {
|
||||
if (isUpdateAvailable) {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle("Update is available")
|
||||
.setMessage("Update to version " + update.getLatestVersionCode().toString() +
|
||||
" is available. Your version is " + BuildConfig.VERSION_CODE + ". Update?")
|
||||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
downloadUpdate();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
public void onDestroy(Activity activity) {
|
||||
activity.unregisterReceiver(onComplete);
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
package io.github.wulkanowy.services.jobs;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import com.firebase.jobdispatcher.Constraint;
|
||||
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
|
||||
import com.firebase.jobdispatcher.Job;
|
||||
import com.firebase.jobdispatcher.Lifetime;
|
||||
import com.firebase.jobdispatcher.RetryStrategy;
|
||||
import com.firebase.jobdispatcher.Trigger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.WulkanowyApp;
|
||||
import io.github.wulkanowy.db.dao.DatabaseAccess;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.services.notifications.NotificationBuilder;
|
||||
import io.github.wulkanowy.services.sync.VulcanSync;
|
||||
import io.github.wulkanowy.ui.main.DashboardActivity;
|
||||
|
||||
public class FullSyncJob extends VulcanJobHelper {
|
||||
|
||||
private static final String UNIQUE_TAG = "FullSync";
|
||||
|
||||
private static final int DEFAULT_INTERVAL_START = 60 * 50;
|
||||
|
||||
private static final int DEFAULT_INTERVAL_END = DEFAULT_INTERVAL_START + (60 * 40);
|
||||
|
||||
@Override
|
||||
protected Job createJob(FirebaseJobDispatcher dispatcher) {
|
||||
return dispatcher.newJobBuilder()
|
||||
.setLifetime(Lifetime.FOREVER)
|
||||
.setService(SyncService.class)
|
||||
.setTag(UNIQUE_TAG)
|
||||
.setRecurring(true)
|
||||
.setTrigger(Trigger.executionWindow(DEFAULT_INTERVAL_START, DEFAULT_INTERVAL_END))
|
||||
.setConstraints(Constraint.ON_ANY_NETWORK)
|
||||
.setReplaceCurrent(false)
|
||||
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class SyncService extends VulcanService {
|
||||
|
||||
@Override
|
||||
public void workToBePerformed() throws Exception {
|
||||
DaoSession daoSession = ((WulkanowyApp) getApplication()).getDaoSession();
|
||||
|
||||
VulcanSync synchronization = new VulcanSync()
|
||||
.loginCurrentUser(getApplicationContext(), daoSession);
|
||||
synchronization.syncAll();
|
||||
List<Grade> newGradeList = new DatabaseAccess().getNewGrades(daoSession);
|
||||
|
||||
if (newGradeList.size() == 1) {
|
||||
buildNotify(getResources().getQuantityString(R.plurals.newGradePlurals, 1),
|
||||
newGradeList.get(0).getSubject());
|
||||
} else if (newGradeList.size() > 1) {
|
||||
buildNotify(getResources().getQuantityString(R.plurals.newGradePlurals, 2),
|
||||
getResources().getQuantityString(R.plurals.receivedNewGradePlurals, newGradeList.size(), newGradeList.size()));
|
||||
}
|
||||
}
|
||||
|
||||
private void buildNotify(String title, String bodyText) {
|
||||
Intent intent = new Intent(getApplicationContext(), DashboardActivity.class);
|
||||
intent.putExtra("cardID", 1);
|
||||
PendingIntent pendingIntent = PendingIntent
|
||||
.getActivity(getApplicationContext(), 0, intent, 0);
|
||||
|
||||
NotificationBuilder notificationBuilder = new NotificationBuilder(getApplicationContext());
|
||||
NotificationCompat.Builder builder = notificationBuilder
|
||||
.getNotifications(title, bodyText, pendingIntent);
|
||||
notificationBuilder.getManager().notify(new Random().nextInt(10000), builder.build());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package io.github.wulkanowy.services.jobs;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
|
||||
import com.firebase.jobdispatcher.GooglePlayDriver;
|
||||
import com.firebase.jobdispatcher.Job;
|
||||
|
||||
public abstract class VulcanJobHelper {
|
||||
|
||||
public static final String DEBUG_TAG = "SynchronizationService";
|
||||
|
||||
public final void scheduledJob(Context context) {
|
||||
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
|
||||
dispatcher.mustSchedule(createJob(dispatcher));
|
||||
Log.i(DEBUG_TAG, "Wulkanowy Job is initiation: " + this.toString());
|
||||
}
|
||||
|
||||
protected abstract Job createJob(FirebaseJobDispatcher dispatcher);
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package io.github.wulkanowy.services.jobs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import com.firebase.jobdispatcher.JobParameters;
|
||||
import com.firebase.jobdispatcher.JobService;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public abstract class VulcanService extends JobService {
|
||||
|
||||
private SyncTask syncTask;
|
||||
|
||||
@Override
|
||||
public boolean onStartJob(JobParameters params) {
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Wulkanowy services start");
|
||||
syncTask = new SyncTask(this, params);
|
||||
syncTask.execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters params) {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Wulkanowy services stop");
|
||||
if (syncTask != null) {
|
||||
syncTask.cancel(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract void workToBePerformed() throws Exception;
|
||||
|
||||
private static class SyncTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private JobParameters jobParameters;
|
||||
|
||||
private WeakReference<VulcanService> vulcanService;
|
||||
|
||||
public SyncTask(VulcanService vulcanService, JobParameters jobParameters) {
|
||||
this.jobParameters = jobParameters;
|
||||
this.vulcanService = new WeakReference<>(vulcanService);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
try {
|
||||
vulcanService.get().workToBePerformed();
|
||||
} catch (Exception e) {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "User logging in the background failed", e);
|
||||
} finally {
|
||||
vulcanService.get().jobFinished(jobParameters, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
package io.github.wulkanowy.services.notifications;
|
||||
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.os.Build;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
|
||||
public class NotificationBuilder extends ContextWrapper {
|
||||
|
||||
public static final String CHANNEL_ID = "Wulkanowy_New_Grade_Channel";
|
||||
|
||||
public static final String CHANNEL_NAME = "New Grade Channel";
|
||||
|
||||
private NotificationManager manager;
|
||||
|
||||
public NotificationBuilder(Context context) {
|
||||
super(context);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createChannel();
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(26)
|
||||
private void createChannel() {
|
||||
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
|
||||
NotificationManager.IMPORTANCE_HIGH);
|
||||
notificationChannel.enableLights(true);
|
||||
notificationChannel.enableVibration(true);
|
||||
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
|
||||
getManager().createNotificationChannel(notificationChannel);
|
||||
}
|
||||
|
||||
public NotificationCompat.Builder getNotifications(String title, String bodyText, PendingIntent pendingIntent) {
|
||||
return new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
|
||||
.setContentTitle(title)
|
||||
.setContentText(bodyText)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setChannelId(CHANNEL_ID)
|
||||
.setDefaults(NotificationCompat.DEFAULT_ALL)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setColor(getResources().getColor(R.color.colorPrimary));
|
||||
}
|
||||
|
||||
public NotificationManager getManager() {
|
||||
if (manager == null) {
|
||||
manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.login.AccountPermissionException;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.api.login.LoginErrorException;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.db.dao.entities.AccountDao;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
import io.github.wulkanowy.utils.security.Safety;
|
||||
|
||||
public class CurrentAccountLogin {
|
||||
|
||||
private final Context context;
|
||||
|
||||
private final DaoSession daoSession;
|
||||
|
||||
private final Vulcan vulcan;
|
||||
|
||||
public CurrentAccountLogin(Context context, DaoSession daoSession, Vulcan vulcan) {
|
||||
this.context = context;
|
||||
this.daoSession = daoSession;
|
||||
this.vulcan = vulcan;
|
||||
}
|
||||
|
||||
public LoginSession loginCurrentUser() throws CryptoException,
|
||||
BadCredentialsException, AccountPermissionException, IOException, LoginErrorException, VulcanOfflineException {
|
||||
|
||||
AccountDao accountDao = daoSession.getAccountDao();
|
||||
|
||||
long userId = context.getSharedPreferences("LoginData", Context.MODE_PRIVATE).getLong("userId", 0);
|
||||
|
||||
if (userId != 0) {
|
||||
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Login current user id=" + String.valueOf(userId));
|
||||
|
||||
Safety safety = new Safety();
|
||||
Account account = accountDao.load(userId);
|
||||
|
||||
vulcan.login(
|
||||
account.getEmail(),
|
||||
safety.decrypt(account.getEmail(), account.getPassword()),
|
||||
account.getSymbol(),
|
||||
account.getSnpId()
|
||||
);
|
||||
|
||||
return new LoginSession()
|
||||
.setDaoSession(daoSession)
|
||||
.setUserId(userId)
|
||||
.setVulcan(vulcan);
|
||||
} else {
|
||||
Log.wtf(VulcanJobHelper.DEBUG_TAG, "loginCurrentUser - USERID IS EMPTY");
|
||||
throw new IOException("Can't find user with index 0");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.login.AccountPermissionException;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.db.dao.entities.AccountDao;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
import io.github.wulkanowy.utils.security.Safety;
|
||||
|
||||
public class FirstAccountLogin {
|
||||
|
||||
private final Context context;
|
||||
|
||||
private final DaoSession daoSession;
|
||||
|
||||
private final Vulcan vulcan;
|
||||
|
||||
public FirstAccountLogin(Context context, DaoSession daoSession, Vulcan vulcan) {
|
||||
this.context = context;
|
||||
this.daoSession = daoSession;
|
||||
this.vulcan = vulcan;
|
||||
}
|
||||
|
||||
public LoginSession login(String email, String password, String symbol)
|
||||
throws NotLoggedInErrorException, AccountPermissionException, IOException, CryptoException, VulcanOfflineException, BadCredentialsException {
|
||||
|
||||
String realSymbol = vulcan.login(email, password, symbol);
|
||||
|
||||
AccountDao accountDao = daoSession.getAccountDao();
|
||||
Safety safety = new Safety();
|
||||
Account account = new Account()
|
||||
.setName(vulcan.getBasicInformation().getPersonalData().getFirstAndLastName())
|
||||
.setEmail(email)
|
||||
.setPassword(safety.encrypt(email, password, context))
|
||||
.setSymbol(realSymbol)
|
||||
.setSnpId(vulcan.getStudentAndParent().getId());
|
||||
|
||||
long userId = accountDao.insert(account);
|
||||
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences("LoginData", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.putLong("userId", userId);
|
||||
editor.apply();
|
||||
|
||||
return new LoginSession()
|
||||
.setVulcan(vulcan)
|
||||
.setUserId(userId)
|
||||
.setDaoSession(daoSession);
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.greenrobot.greendao.query.Query;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.api.grades.GradesList;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.db.dao.entities.AccountDao;
|
||||
import io.github.wulkanowy.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.db.dao.entities.GradeDao;
|
||||
import io.github.wulkanowy.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.db.dao.entities.SubjectDao;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.EntitiesCompare;
|
||||
|
||||
public class GradesSync {
|
||||
|
||||
public void sync(LoginSession loginSession) throws IOException,
|
||||
ParseException, NotLoggedInErrorException {
|
||||
|
||||
GradesList gradesList = loginSession.getVulcan().getGradesList();
|
||||
|
||||
GradeDao gradeDao = loginSession.getDaoSession().getGradeDao();
|
||||
AccountDao accountDao = loginSession.getDaoSession().getAccountDao();
|
||||
SubjectDao subjectDao = loginSession.getDaoSession().getSubjectDao();
|
||||
|
||||
Account account = accountDao.load(loginSession.getUserId());
|
||||
|
||||
account.resetGradeList();
|
||||
account.resetSubjectList();
|
||||
|
||||
List<Grade> gradesFromDb = account.getGradeList();
|
||||
List<Grade> gradeEntitiesList = DataObjectConverter.gradesToGradeEntities(gradesList.getAll());
|
||||
List<Grade> updatedList = EntitiesCompare.compareGradeList(gradeEntitiesList, gradesFromDb);
|
||||
List<Grade> lastList = new ArrayList<>();
|
||||
|
||||
GradeDao.dropTable(gradeDao.getDatabase(), true);
|
||||
GradeDao.createTable(gradeDao.getDatabase(), false);
|
||||
|
||||
for (Grade grade : updatedList) {
|
||||
|
||||
Query<Subject> subjectQuery = subjectDao.queryBuilder()
|
||||
.where(SubjectDao.Properties.Name.eq(grade.getSubject()))
|
||||
.build();
|
||||
|
||||
grade.setUserId(loginSession.getUserId());
|
||||
grade.setSubjectId((subjectQuery.uniqueOrThrow()).getId());
|
||||
|
||||
lastList.add(grade);
|
||||
}
|
||||
|
||||
gradeDao.insertInTx(lastList);
|
||||
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Synchronization grades (amount = " + String.valueOf(lastList.size() + ")"));
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
|
||||
|
||||
public class LoginSession {
|
||||
|
||||
private Long userId;
|
||||
|
||||
private Vulcan vulcan;
|
||||
|
||||
private DaoSession daoSession;
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public LoginSession setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vulcan getVulcan() {
|
||||
return vulcan;
|
||||
}
|
||||
|
||||
public LoginSession setVulcan(Vulcan vulcan) {
|
||||
this.vulcan = vulcan;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DaoSession getDaoSession() {
|
||||
return daoSession;
|
||||
}
|
||||
|
||||
public LoginSession setDaoSession(DaoSession daoSession) {
|
||||
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();
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.api.grades.SubjectsList;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.db.dao.entities.SubjectDao;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
|
||||
public class SubjectsSync {
|
||||
|
||||
public void sync(LoginSession loginSession) throws IOException,
|
||||
NotLoggedInErrorException {
|
||||
|
||||
SubjectsList subjectsList = loginSession.getVulcan().getSubjectsList();
|
||||
SubjectDao subjectDao = loginSession.getDaoSession().getSubjectDao();
|
||||
|
||||
List<Subject> subjectEntitiesList = DataObjectConverter.subjectsToSubjectEntities(subjectsList.getAll());
|
||||
List<Subject> preparedList = new ArrayList<>();
|
||||
|
||||
for (Subject subject : subjectEntitiesList) {
|
||||
subject.setUserId(loginSession.getUserId());
|
||||
preparedList.add(subject);
|
||||
}
|
||||
|
||||
SubjectDao.dropTable(subjectDao.getDatabase(), true);
|
||||
SubjectDao.createTable(subjectDao.getDatabase(), false);
|
||||
subjectDao.insertInTx(preparedList);
|
||||
|
||||
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Synchronization subjects (amount = " + String.valueOf(subjectEntitiesList.size() + ")"));
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import org.greenrobot.greendao.query.Query;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.api.timetable.Day;
|
||||
import io.github.wulkanowy.api.timetable.Week;
|
||||
import io.github.wulkanowy.db.dao.entities.DayDao;
|
||||
import io.github.wulkanowy.db.dao.entities.Lesson;
|
||||
import io.github.wulkanowy.db.dao.entities.LessonDao;
|
||||
import io.github.wulkanowy.db.dao.entities.WeekDao;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.TimeUtils;
|
||||
|
||||
public class TimetableSync {
|
||||
|
||||
public void sync(@NonNull LoginSession loginSession, @Nullable String dateOfMonday) throws NotLoggedInErrorException,
|
||||
IOException, ParseException {
|
||||
DayDao dayDao = loginSession.getDaoSession().getDayDao();
|
||||
LessonDao lessonDao = loginSession.getDaoSession().getLessonDao();
|
||||
WeekDao weekDao = loginSession.getDaoSession().getWeekDao();
|
||||
|
||||
Long weekId;
|
||||
|
||||
Week week = dateOfMonday == null ? loginSession.getVulcan().getTimetable().getWeekTable()
|
||||
: loginSession.getVulcan().getTimetable()
|
||||
.getWeekTable(String.valueOf(TimeUtils.getNetTicks(dateOfMonday, "yyyy-MM-dd")));
|
||||
|
||||
Query<io.github.wulkanowy.db.dao.entities.Week> weekQuery = weekDao.queryBuilder()
|
||||
.where(WeekDao.Properties.UserId.eq(loginSession.getUserId()), WeekDao.Properties.StartDayDate.eq(week.getStartDayDate())).build();
|
||||
|
||||
io.github.wulkanowy.db.dao.entities.Week week1 = weekQuery.unique();
|
||||
|
||||
if (week1 != null) {
|
||||
weekId = week1.getId();
|
||||
} else {
|
||||
weekId = weekDao.insert(DataObjectConverter.weekToWeekEntitie(week).setUserId(loginSession.getUserId()));
|
||||
}
|
||||
|
||||
List<Day> dayList = week.getDays();
|
||||
|
||||
dayDao.saveInTx(getPreparedDaysList(dayList, loginSession.getUserId(), weekId, dayDao));
|
||||
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Synchronization days (amount = " + dayList.size() + ")");
|
||||
|
||||
List<Lesson> lessonList = new ArrayList<>();
|
||||
lessonList.addAll(getPreparedLessonsList(dayList, dayDao, lessonDao, loginSession.getUserId(), weekId));
|
||||
|
||||
lessonDao.saveInTx(lessonList);
|
||||
|
||||
Log.d(VulcanJobHelper.DEBUG_TAG, "Synchronization lessons (amount = " + lessonList.size() + ")");
|
||||
}
|
||||
|
||||
private List<Lesson> getPreparedLessonsList(List<Day> dayList, DayDao dayDao, LessonDao lessonDao, long userId, long weekId) {
|
||||
List<Lesson> allLessonsList = new ArrayList<>();
|
||||
|
||||
for (Day day : dayList) {
|
||||
|
||||
Query<io.github.wulkanowy.db.dao.entities.Day> dayQuery = dayDao.queryBuilder()
|
||||
.where(DayDao.Properties.Date.eq(day.getDate()),
|
||||
DayDao.Properties.UserId.eq(userId),
|
||||
DayDao.Properties.WeekId.eq(weekId))
|
||||
.build();
|
||||
|
||||
List<Lesson> lessonEntityList = DataObjectConverter.lessonsToLessonsEntities(day.getLessons());
|
||||
List<Lesson> updatedLessonEntityList = new ArrayList<>();
|
||||
|
||||
for (Lesson lesson : lessonEntityList) {
|
||||
Lesson lesson1 = lessonDao.queryBuilder()
|
||||
.where(LessonDao.Properties.DayId.eq(dayQuery.uniqueOrThrow().getId()),
|
||||
LessonDao.Properties.Date.eq(lesson.getDate()),
|
||||
LessonDao.Properties.StartTime.eq(lesson.getStartTime()),
|
||||
LessonDao.Properties.EndTime.eq(lesson.getEndTime()))
|
||||
.unique();
|
||||
|
||||
if (lesson1 != null) {
|
||||
lesson.setId(lesson1.getId());
|
||||
}
|
||||
|
||||
lesson.setDayId(dayQuery.uniqueOrThrow().getId());
|
||||
if (!"".equals(lesson.getSubject())) {
|
||||
updatedLessonEntityList.add(lesson);
|
||||
}
|
||||
}
|
||||
allLessonsList.addAll(updatedLessonEntityList);
|
||||
}
|
||||
return allLessonsList;
|
||||
}
|
||||
|
||||
private List<io.github.wulkanowy.db.dao.entities.Day> getPreparedDaysList(List<Day> dayList, long userId, long weekId, DayDao dayDao) {
|
||||
List<io.github.wulkanowy.db.dao.entities.Day> updatedDayList = new ArrayList<>();
|
||||
List<io.github.wulkanowy.db.dao.entities.Day> dayEntityList = DataObjectConverter
|
||||
.daysToDaysEntities(dayList);
|
||||
for (io.github.wulkanowy.db.dao.entities.Day day : dayEntityList) {
|
||||
|
||||
Query<io.github.wulkanowy.db.dao.entities.Day> dayQuery = dayDao.queryBuilder().where(DayDao.Properties.UserId.eq(userId), DayDao.Properties.WeekId.eq(weekId), DayDao.Properties.Date.eq(day.getDate())).build();
|
||||
|
||||
io.github.wulkanowy.db.dao.entities.Day day1 = dayQuery.unique();
|
||||
|
||||
if (day1 != null) {
|
||||
day.setId(day1.getId());
|
||||
}
|
||||
|
||||
day.setUserId(userId);
|
||||
day.setWeekId(weekId);
|
||||
updatedDayList.add(day);
|
||||
}
|
||||
return updatedDayList;
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package io.github.wulkanowy.services.sync;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.login.AccountPermissionException;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.api.login.LoginErrorException;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
|
||||
public class VulcanSync {
|
||||
|
||||
private LoginSession loginSession;
|
||||
|
||||
public VulcanSync(LoginSession loginSession) {
|
||||
this.loginSession = loginSession;
|
||||
}
|
||||
|
||||
public VulcanSync() {
|
||||
this.loginSession = new LoginSession();
|
||||
}
|
||||
|
||||
public void firstLoginSignInStep(Context context, DaoSession daoSession, String email, String password, String symbol)
|
||||
throws NotLoggedInErrorException, AccountPermissionException, IOException, CryptoException, VulcanOfflineException, BadCredentialsException {
|
||||
FirstAccountLogin firstAccountLogin = new FirstAccountLogin(context, daoSession, new Vulcan());
|
||||
loginSession = firstAccountLogin.login(email, password, symbol);
|
||||
}
|
||||
|
||||
public VulcanSync loginCurrentUser(Context context, DaoSession daoSession) throws CryptoException,
|
||||
BadCredentialsException, AccountPermissionException, LoginErrorException, IOException, VulcanOfflineException {
|
||||
return loginCurrentUser(context, daoSession, new Vulcan());
|
||||
}
|
||||
|
||||
public VulcanSync loginCurrentUser(Context context, DaoSession daoSession, Vulcan vulcan)
|
||||
throws CryptoException, BadCredentialsException, AccountPermissionException,
|
||||
LoginErrorException, IOException, VulcanOfflineException {
|
||||
|
||||
CurrentAccountLogin currentAccountLogin = new CurrentAccountLogin(context, daoSession, vulcan);
|
||||
loginSession = currentAccountLogin.loginCurrentUser();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void syncAll() throws IOException {
|
||||
syncSubjectsAndGrades();
|
||||
syncTimetable();
|
||||
}
|
||||
|
||||
public void syncGrades() throws IOException {
|
||||
if (loginSession != null) {
|
||||
GradesSync gradesSync = new GradesSync();
|
||||
try {
|
||||
gradesSync.sync(loginSession);
|
||||
} catch (Exception e) {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Synchronisation of grades failed", e);
|
||||
throw new IOException(e.getCause());
|
||||
}
|
||||
} else {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Before sync, should login user to log",
|
||||
new UnsupportedOperationException());
|
||||
}
|
||||
}
|
||||
|
||||
public void syncSubjectsAndGrades() throws IOException {
|
||||
if (loginSession != null) {
|
||||
SubjectsSync subjectsSync = new SubjectsSync();
|
||||
try {
|
||||
subjectsSync.sync(loginSession);
|
||||
syncGrades();
|
||||
} catch (Exception e) {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Synchronisation of subjects failed", e);
|
||||
throw new IOException(e.getCause());
|
||||
}
|
||||
} else {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Before sync, should login user to log",
|
||||
new UnsupportedOperationException());
|
||||
}
|
||||
}
|
||||
|
||||
public void syncTimetable() throws IOException {
|
||||
syncTimetable(null);
|
||||
}
|
||||
|
||||
public void syncTimetable(@Nullable String date) throws IOException {
|
||||
if (loginSession != null) {
|
||||
TimetableSync timetableSync = new TimetableSync();
|
||||
try {
|
||||
timetableSync.sync(loginSession, date);
|
||||
} catch (Exception e) {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Synchronization of timetable failed", e);
|
||||
throw new IOException(e.getCause());
|
||||
}
|
||||
} else {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "Before sync, should login user to log",
|
||||
new UnsupportedOperationException());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package io.github.wulkanowy.ui.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import butterknife.Unbinder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.WulkanowyApp;
|
||||
import io.github.wulkanowy.di.component.ActivityComponent;
|
||||
import io.github.wulkanowy.di.component.DaggerActivityComponent;
|
||||
import io.github.wulkanowy.di.modules.ActivityModule;
|
||||
import io.github.wulkanowy.utils.NetworkUtils;
|
||||
|
||||
public abstract class BaseActivity extends AppCompatActivity implements BaseContract.View {
|
||||
|
||||
private ActivityComponent activityComponent;
|
||||
|
||||
private Unbinder unbinder;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
activityComponent = DaggerActivityComponent.builder()
|
||||
.activityModule(new ActivityModule(this))
|
||||
.applicationComponent(((WulkanowyApp) getApplication()).getApplicationComponent())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (unbinder != null) {
|
||||
unbinder.unbind();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int resId) {
|
||||
onError(getString(resId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String message) {
|
||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNoNetworkError() {
|
||||
onError(R.string.noInternet_text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNetworkConnected() {
|
||||
return NetworkUtils.isOnline(getApplicationContext());
|
||||
}
|
||||
|
||||
public ActivityComponent getActivityComponent() {
|
||||
return activityComponent;
|
||||
}
|
||||
|
||||
public void setButterKnife(Unbinder unbinder) {
|
||||
this.unbinder = unbinder;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package io.github.wulkanowy.ui.base;
|
||||
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
import io.github.wulkanowy.di.annotations.PerActivity;
|
||||
|
||||
public interface BaseContract {
|
||||
|
||||
interface View {
|
||||
|
||||
void onError(@StringRes int resId);
|
||||
|
||||
void onError(String message);
|
||||
|
||||
void onNoNetworkError();
|
||||
|
||||
boolean isNetworkConnected();
|
||||
}
|
||||
|
||||
@PerActivity
|
||||
interface Presenter<V extends View> {
|
||||
|
||||
void onStart(V view);
|
||||
|
||||
void onDestroy();
|
||||
}
|
||||
}
|
104
app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.java
Normal file
104
app/src/main/java/io/github/wulkanowy/ui/base/BaseFragment.java
Normal file
@ -0,0 +1,104 @@
|
||||
package io.github.wulkanowy.ui.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.View;
|
||||
|
||||
import butterknife.Unbinder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.WulkanowyApp;
|
||||
import io.github.wulkanowy.di.component.DaggerFragmentComponent;
|
||||
import io.github.wulkanowy.di.component.FragmentComponent;
|
||||
import io.github.wulkanowy.di.modules.FragmentModule;
|
||||
|
||||
public abstract class BaseFragment extends Fragment implements BaseContract.View {
|
||||
|
||||
private BaseActivity activity;
|
||||
|
||||
private Unbinder unbinder;
|
||||
|
||||
private FragmentComponent fragmentComponent;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof BaseActivity) {
|
||||
activity = (BaseActivity) context;
|
||||
}
|
||||
|
||||
fragmentComponent = DaggerFragmentComponent.builder()
|
||||
.fragmentModule(new FragmentModule(this))
|
||||
.applicationComponent(((WulkanowyApp) activity.getApplication()).getApplicationComponent())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
setUpOnViewCreated(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
activity = null;
|
||||
super.onDetach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (unbinder != null) {
|
||||
unbinder.unbind();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int resId) {
|
||||
onError(getString(resId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String message) {
|
||||
if (activity != null) {
|
||||
activity.onError(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNoNetworkError() {
|
||||
onError(R.string.noInternet_text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNetworkConnected() {
|
||||
return activity != null && activity.isNetworkConnected();
|
||||
}
|
||||
|
||||
public void setButterKnife(Unbinder unbinder) {
|
||||
this.unbinder = unbinder;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
if (activity != null) {
|
||||
activity.setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
public FragmentComponent getFragmentComponent() {
|
||||
return fragmentComponent;
|
||||
}
|
||||
|
||||
|
||||
protected void setUpOnViewCreated(View fragmentView) {
|
||||
// do something on view created
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package io.github.wulkanowy.ui.base;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
|
||||
public class BasePresenter<V extends BaseContract.View> implements BaseContract.Presenter<V> {
|
||||
|
||||
private final RepositoryContract repository;
|
||||
|
||||
private V view;
|
||||
|
||||
@Inject
|
||||
public BasePresenter(RepositoryContract repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(V view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
view = null;
|
||||
}
|
||||
|
||||
public final RepositoryContract getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
public V getView() {
|
||||
return view;
|
||||
}
|
||||
}
|
@ -1,226 +1,223 @@
|
||||
package io.github.wulkanowy.ui.login;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.OnEditorAction;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.services.Updater;
|
||||
import io.github.wulkanowy.ui.base.BaseActivity;
|
||||
import io.github.wulkanowy.ui.main.MainActivity;
|
||||
import io.github.wulkanowy.utils.AppConstant;
|
||||
import io.github.wulkanowy.utils.CommonUtils;
|
||||
import io.github.wulkanowy.utils.KeyboardUtils;
|
||||
|
||||
/**
|
||||
* A login screen that offers login via email/password.
|
||||
*/
|
||||
public class LoginActivity extends Activity {
|
||||
public class LoginActivity extends BaseActivity implements LoginContract.View {
|
||||
|
||||
private float touchPosition;
|
||||
@BindView(R.id.login_activity_email_edit)
|
||||
EditText emailView;
|
||||
|
||||
private EditText emailView;
|
||||
@BindView(R.id.login_activity_pass_edit)
|
||||
EditText passwordView;
|
||||
|
||||
private EditText passwordView;
|
||||
@BindView(R.id.login_activity_symbol_edit)
|
||||
AutoCompleteTextView symbolView;
|
||||
|
||||
private AutoCompleteTextView symbolView;
|
||||
@BindView(R.id.login_activity_form_scroll)
|
||||
View loginFormView;
|
||||
|
||||
private Updater updater;
|
||||
@BindView(R.id.login_activity_progress_container)
|
||||
View loadingBarView;
|
||||
|
||||
@BindView(R.id.login_activity_progress_text)
|
||||
TextView loginProgressText;
|
||||
|
||||
@BindView(R.id.login_activity_symbol_text_input)
|
||||
TextInputLayout symbolLayout;
|
||||
|
||||
@Inject
|
||||
LoginContract.Presenter presenter;
|
||||
|
||||
private EditText requestedView;
|
||||
|
||||
public static Intent getStartIntent(Context context) {
|
||||
return new Intent(context, LoginActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_login);
|
||||
|
||||
updater = new Updater(this).checkForUpdates();
|
||||
setButterKnife(ButterKnife.bind(this));
|
||||
getActivityComponent().inject(this);
|
||||
|
||||
// Set up the login form.
|
||||
emailView = findViewById(R.id.email);
|
||||
passwordView = findViewById(R.id.password);
|
||||
symbolView = findViewById(R.id.symbol);
|
||||
presenter.onStart(this);
|
||||
|
||||
passwordView.setOnEditorActionListener(getTextViewSignInListener());
|
||||
symbolView.setOnEditorActionListener(getTextViewSignInListener());
|
||||
setUpOnCreate();
|
||||
|
||||
populateAutoComplete();
|
||||
}
|
||||
|
||||
Button signInButton = findViewById(R.id.action_sign_in);
|
||||
signInButton.setOnClickListener(new OnClickListener() {
|
||||
protected void setUpOnCreate() {
|
||||
symbolView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
|
||||
getResources().getStringArray(R.array.symbols)));
|
||||
}
|
||||
|
||||
@OnClick(R.id.login_activity_sign_button)
|
||||
void onLoginButtonClick() {
|
||||
presenter.attemptLogin(
|
||||
emailView.getText().toString(),
|
||||
passwordView.getText().toString(),
|
||||
symbolView.getText().toString());
|
||||
}
|
||||
|
||||
@OnEditorAction(value = {R.id.login_activity_symbol_edit, R.id.login_activity_pass_edit})
|
||||
boolean onEditorAction(int id) {
|
||||
if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
|
||||
onLoginButtonClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@OnClick(R.id.login_activity_create_text)
|
||||
void onCreateAccountButtonClick() {
|
||||
CommonUtils.openInternalBrowserViewer(getApplicationContext(),
|
||||
AppConstant.VULCAN_CREATE_ACCOUNT_URL);
|
||||
}
|
||||
|
||||
@OnClick(R.id.login_activity_forgot_text)
|
||||
void onForgotPasswordButtonClick() {
|
||||
CommonUtils.openInternalBrowserViewer(getApplicationContext(),
|
||||
AppConstant.VULCAN_FORGOT_PASS_URL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorEmailRequired() {
|
||||
emailView.requestFocus();
|
||||
emailView.setError(getString(R.string.error_field_required));
|
||||
requestedView = emailView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorEmailInvalid() {
|
||||
emailView.requestFocus();
|
||||
emailView.setError(getString(R.string.error_invalid_email));
|
||||
requestedView = emailView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorPassRequired() {
|
||||
passwordView.requestFocus();
|
||||
passwordView.setError(getString(R.string.error_field_required));
|
||||
requestedView = passwordView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorPassInvalid() {
|
||||
passwordView.requestFocus();
|
||||
passwordView.setError(getString(R.string.error_invalid_password));
|
||||
requestedView = passwordView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorPassIncorrect() {
|
||||
passwordView.requestFocus();
|
||||
passwordView.setError(getString(R.string.error_incorrect_password));
|
||||
requestedView = passwordView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setErrorSymbolRequired() {
|
||||
symbolLayout.setVisibility(View.VISIBLE);
|
||||
symbolView.setError(getString(R.string.error_bad_account_permission));
|
||||
symbolView.requestFocus();
|
||||
requestedView = symbolView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetViewErrors() {
|
||||
emailView.setError(null);
|
||||
passwordView.setError(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showSoftInput() {
|
||||
KeyboardUtils.showSoftInput(requestedView, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideSoftInput() {
|
||||
KeyboardUtils.hideSoftInput(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String message) {
|
||||
Snackbar.make(findViewById(R.id.login_activity_container), message,
|
||||
Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStepOneLoginProgress() {
|
||||
onLoginProgressUpdate("1", getString(R.string.step_login));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStepTwoLoginProgress() {
|
||||
onLoginProgressUpdate("2", getString(R.string.step_synchronization));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openMainActivity() {
|
||||
startActivity(MainActivity.getStartIntent(this));
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showLoginProgress(final boolean show) {
|
||||
int animTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
|
||||
|
||||
loginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
|
||||
loginFormView.animate().setDuration(animTime).alpha(
|
||||
show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
attemptLogin();
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
loginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
findViewById(R.id.action_create_account).setOnClickListener(getButtonLinkListener(
|
||||
"https://cufs.vulcan.net.pl/Default/AccountManage/CreateAccount"
|
||||
));
|
||||
|
||||
findViewById(R.id.action_forgot_password).setOnClickListener(getButtonLinkListener(
|
||||
"https://cufs.vulcan.net.pl/Default/AccountManage/UnlockAccount"
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
updater.onRequestPermissionsResult(requestCode, grantResults);
|
||||
}
|
||||
|
||||
private TextView.OnEditorActionListener getTextViewSignInListener() {
|
||||
return new TextView.OnEditorActionListener() {
|
||||
loadingBarView.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
loadingBarView.animate().setDuration(animTime).alpha(
|
||||
show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
|
||||
if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
|
||||
attemptLogin();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
loadingBarView.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private OnClickListener getButtonLinkListener(final String url) {
|
||||
return new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
builder.setToolbarColor(getResources().getColor(R.color.colorPrimary));
|
||||
customTabsIntent.launchUrl(view.getContext(), Uri.parse(url));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void populateAutoComplete() {
|
||||
// Get the string array
|
||||
String[] countries = getResources().getStringArray(R.array.symbols);
|
||||
// Create the adapter and set it to the AutoCompleteTextView
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
|
||||
countries);
|
||||
symbolView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to sign in the account specified by the login form.
|
||||
*/
|
||||
private void attemptLogin() {
|
||||
// Reset errors.
|
||||
emailView.setError(null);
|
||||
passwordView.setError(null);
|
||||
|
||||
// Store values at the time of the login attempt.
|
||||
String email = emailView.getText().toString();
|
||||
String password = passwordView.getText().toString();
|
||||
String symbol = symbolView.getText().toString();
|
||||
|
||||
boolean cancel = false;
|
||||
View focusView = null;
|
||||
|
||||
// Check for a valid password.
|
||||
if (TextUtils.isEmpty(password)) {
|
||||
passwordView.setError(getString(R.string.error_field_required));
|
||||
focusView = passwordView;
|
||||
cancel = true;
|
||||
} else if (!isPasswordValid(password)) {
|
||||
passwordView.setError(getString(R.string.error_invalid_password));
|
||||
focusView = passwordView;
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
// Check for a valid email address.
|
||||
if (TextUtils.isEmpty(email)) {
|
||||
emailView.setError(getString(R.string.error_field_required));
|
||||
focusView = emailView;
|
||||
cancel = true;
|
||||
} else if (!isEmailValid(email)) {
|
||||
emailView.setError(getString(R.string.error_invalid_email));
|
||||
focusView = emailView;
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
// Check for a valid symbol.
|
||||
if (TextUtils.isEmpty(symbol)) {
|
||||
symbol = "Default";
|
||||
}
|
||||
|
||||
String[] keys = getResources().getStringArray(R.array.symbols);
|
||||
String[] values = getResources().getStringArray(R.array.symbols_values);
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < Math.min(keys.length, values.length); ++i) {
|
||||
map.put(keys[i], values[i]);
|
||||
}
|
||||
|
||||
if (map.containsKey(symbol)) {
|
||||
symbol = map.get(symbol);
|
||||
}
|
||||
|
||||
if (cancel) {
|
||||
// There was an error; don't attempt login and focus the first
|
||||
// form field with an error.
|
||||
focusView.requestFocus();
|
||||
} else {
|
||||
// Show a progress spinner and kick off a background task to
|
||||
// perform the user login attempt.
|
||||
LoginTask authTask = new LoginTask(this, email, password, symbol);
|
||||
authTask.showProgress(true);
|
||||
authTask.execute();
|
||||
KeyboardUtils.hideSoftInput(this);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmailValid(String email) {
|
||||
return email.contains("@") || email.contains("\\\\");
|
||||
}
|
||||
|
||||
private boolean isPasswordValid(String password) {
|
||||
return password.length() > 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
touchPosition = ev.getY();
|
||||
}
|
||||
if (ev.getAction() == MotionEvent.ACTION_UP) {
|
||||
float releasePosition = ev.getY();
|
||||
|
||||
if (touchPosition - releasePosition == 0) {
|
||||
View view = getCurrentFocus();
|
||||
if (view != null && (ev.getAction() == MotionEvent.ACTION_UP
|
||||
|| ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText
|
||||
&& !view.getClass().getName().startsWith("android.webkit.")) {
|
||||
|
||||
int[] coordinators = new int[2];
|
||||
view.getLocationOnScreen(coordinators);
|
||||
float x = ev.getRawX() + view.getLeft() - coordinators[0];
|
||||
float y = ev.getRawY() + view.getTop() - coordinators[1];
|
||||
if (x < view.getLeft() || x > view.getRight() || y < view.getTop()
|
||||
|| y > view.getBottom()) {
|
||||
KeyboardUtils.hideSoftInput(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent(ev);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
updater.onDestroy(this);
|
||||
presenter.onDestroy();
|
||||
}
|
||||
|
||||
private void onLoginProgressUpdate(String step, String message) {
|
||||
loginProgressText.setText(String.format("%1$s/2 - %2$s...", step, message));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
package io.github.wulkanowy.ui.login;
|
||||
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.di.annotations.PerActivity;
|
||||
import io.github.wulkanowy.ui.base.BaseContract;
|
||||
|
||||
public interface LoginContract {
|
||||
interface View extends BaseContract.View {
|
||||
|
||||
void setErrorEmailRequired();
|
||||
|
||||
void setErrorPassRequired();
|
||||
|
||||
void setErrorSymbolRequired();
|
||||
|
||||
void setErrorEmailInvalid();
|
||||
|
||||
void setErrorPassInvalid();
|
||||
|
||||
void setErrorPassIncorrect();
|
||||
|
||||
void resetViewErrors();
|
||||
|
||||
void setStepOneLoginProgress();
|
||||
|
||||
void setStepTwoLoginProgress();
|
||||
|
||||
void openMainActivity();
|
||||
|
||||
void showLoginProgress(boolean show);
|
||||
|
||||
void showSoftInput();
|
||||
|
||||
void hideSoftInput();
|
||||
|
||||
}
|
||||
|
||||
@PerActivity
|
||||
interface Presenter extends BaseContract.Presenter<View> {
|
||||
|
||||
void attemptLogin(String email, String password, String symbol);
|
||||
|
||||
void onStartAsync();
|
||||
|
||||
void onLoginProgress(int step);
|
||||
|
||||
void onEndAsync(boolean success, Exception exception);
|
||||
|
||||
void onCanceledAsync();
|
||||
|
||||
RepositoryContract getRepository();
|
||||
}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
package io.github.wulkanowy.ui.login;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.github.wulkanowy.api.login.AccountPermissionException;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.ui.base.BasePresenter;
|
||||
import io.github.wulkanowy.utils.AppConstant;
|
||||
|
||||
public class LoginPresenter extends BasePresenter<LoginContract.View>
|
||||
implements LoginContract.Presenter {
|
||||
|
||||
private LoginTask loginAsync;
|
||||
|
||||
@Inject
|
||||
LoginPresenter(RepositoryContract repository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (loginAsync != null) {
|
||||
loginAsync.cancel(true);
|
||||
loginAsync = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attemptLogin(String email, String password, String symbol) {
|
||||
getView().resetViewErrors();
|
||||
|
||||
if (!isAllFieldCorrect(password, email)) {
|
||||
getView().showSoftInput();
|
||||
return;
|
||||
}
|
||||
|
||||
if (getView().isNetworkConnected()) {
|
||||
// Dopóki używamy AsyncTask presenter będzie musiał "wiedzieć" o AsyncTaskach
|
||||
loginAsync = new LoginTask(this,
|
||||
email,
|
||||
password,
|
||||
getNormalizedSymbol(symbol));
|
||||
loginAsync.execute();
|
||||
|
||||
} else {
|
||||
getView().onNoNetworkError();
|
||||
}
|
||||
|
||||
getView().hideSoftInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartAsync() {
|
||||
getView().showLoginProgress(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoginProgress(int step) {
|
||||
if (step == 1) {
|
||||
getView().setStepOneLoginProgress();
|
||||
} else if (step == 2) {
|
||||
getView().setStepTwoLoginProgress();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEndAsync(boolean success, Exception exception) {
|
||||
if (success) {
|
||||
getView().openMainActivity();
|
||||
} else if (exception instanceof BadCredentialsException) {
|
||||
getView().setErrorPassIncorrect();
|
||||
getView().showSoftInput();
|
||||
getView().showLoginProgress(false);
|
||||
} else if (exception instanceof AccountPermissionException) {
|
||||
getView().setErrorSymbolRequired();
|
||||
getView().showSoftInput();
|
||||
getView().showLoginProgress(false);
|
||||
} else {
|
||||
getView().onError(getRepository().getErrorLoginMessage(exception));
|
||||
getView().showLoginProgress(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceledAsync() {
|
||||
getView().showLoginProgress(false);
|
||||
}
|
||||
|
||||
private boolean isEmailValid(String email) {
|
||||
return email.contains("@") || email.contains("\\\\");
|
||||
}
|
||||
|
||||
private boolean isPasswordValid(String password) {
|
||||
return password.length() > 4;
|
||||
}
|
||||
|
||||
private String getNormalizedSymbol(String symbol) {
|
||||
if (TextUtils.isEmpty(symbol)) {
|
||||
return AppConstant.DEFAULT_SYMBOL;
|
||||
}
|
||||
|
||||
String[] keys = getRepository().getSymbolsKeysArray();
|
||||
String[] values = getRepository().getSymbolsValuesArray();
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i < Math.min(keys.length, values.length); ++i) {
|
||||
map.put(keys[i], values[i]);
|
||||
}
|
||||
|
||||
if (map.containsKey(symbol)) {
|
||||
return map.get(symbol);
|
||||
}
|
||||
return AppConstant.DEFAULT_SYMBOL;
|
||||
}
|
||||
|
||||
private boolean isAllFieldCorrect(String password, String email) {
|
||||
boolean correct = true;
|
||||
|
||||
if (TextUtils.isEmpty(password)) {
|
||||
getView().setErrorPassRequired();
|
||||
correct = false;
|
||||
} else if (!isPasswordValid(password)) {
|
||||
getView().setErrorPassInvalid();
|
||||
correct = false;
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(email)) {
|
||||
getView().setErrorEmailRequired();
|
||||
correct = false;
|
||||
} else if (!isEmailValid(email)) {
|
||||
getView().setErrorEmailInvalid();
|
||||
correct = false;
|
||||
}
|
||||
return correct;
|
||||
}
|
||||
}
|
@ -1,64 +1,21 @@
|
||||
package io.github.wulkanowy.ui.login;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
public class LoginTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
private String email;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.WulkanowyApp;
|
||||
import io.github.wulkanowy.api.login.AccountPermissionException;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.api.login.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.services.jobs.FullSyncJob;
|
||||
import io.github.wulkanowy.services.sync.LoginSession;
|
||||
import io.github.wulkanowy.services.sync.VulcanSync;
|
||||
import io.github.wulkanowy.ui.main.DashboardActivity;
|
||||
import io.github.wulkanowy.utils.KeyboardUtils;
|
||||
import io.github.wulkanowy.utils.NetworkUtils;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Represents an asynchronous login/registration task used to authenticate
|
||||
* the user.
|
||||
*/
|
||||
public class LoginTask extends AsyncTask<Void, String, Integer> {
|
||||
private String symbol;
|
||||
|
||||
private final String email;
|
||||
private LoginContract.Presenter presenter;
|
||||
|
||||
private final String password;
|
||||
private Exception exception;
|
||||
|
||||
private final String symbol;
|
||||
|
||||
private WeakReference<Activity> activity;
|
||||
|
||||
private WeakReference<View> progressView;
|
||||
|
||||
private WeakReference<View> loginFormView;
|
||||
|
||||
private WeakReference<TextView> showText;
|
||||
|
||||
LoginTask(Activity activity, String email, String password, String symbol) {
|
||||
this.activity = new WeakReference<>(activity);
|
||||
LoginTask(LoginContract.Presenter presenter, String email, String password, String symbol) {
|
||||
this.presenter = presenter;
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.symbol = symbol;
|
||||
@ -66,159 +23,36 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
showText = new WeakReference<>((TextView) activity.get().findViewById(R.id.login_progress_text));
|
||||
presenter.onStartAsync();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(Void... params) {
|
||||
if (NetworkUtils.isOnline(activity.get())) {
|
||||
DaoSession daoSession = ((WulkanowyApp) activity.get().getApplication()).getDaoSession();
|
||||
VulcanSync vulcanSync = new VulcanSync(new LoginSession());
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
try {
|
||||
publishProgress(1);
|
||||
presenter.getRepository().loginUser(email, password, symbol);
|
||||
|
||||
try {
|
||||
publishProgress("1", activity.get().getResources().getString(R.string.step_login));
|
||||
vulcanSync.firstLoginSignInStep(activity.get(), daoSession, email, password, symbol);
|
||||
|
||||
publishProgress("2", activity.get().getResources().getString(R.string.step_synchronization));
|
||||
vulcanSync.syncAll();
|
||||
} catch (BadCredentialsException e) {
|
||||
return R.string.login_bad_credentials_text;
|
||||
} catch (AccountPermissionException e) {
|
||||
return R.string.error_bad_account_permission;
|
||||
} catch (CryptoException e) {
|
||||
return R.string.encrypt_failed_text;
|
||||
} catch (UnknownHostException e) {
|
||||
return R.string.noInternet_text;
|
||||
} catch (SocketTimeoutException e) {
|
||||
return R.string.generic_timeout_error;
|
||||
} catch (NotLoggedInErrorException | IOException e) {
|
||||
return R.string.login_denied_text;
|
||||
} catch (VulcanOfflineException e) {
|
||||
return R.string.error_host_offline;
|
||||
} catch (UnsupportedOperationException e) {
|
||||
return -1;
|
||||
} catch (Throwable e) {
|
||||
Crashlytics.logException(e);
|
||||
return R.string.login_denied_text;
|
||||
}
|
||||
|
||||
new FullSyncJob().scheduledJob(activity.get());
|
||||
|
||||
return R.string.login_accepted_text;
|
||||
|
||||
} else {
|
||||
return R.string.noInternet_text;
|
||||
publishProgress(2);
|
||||
presenter.getRepository().syncAll();
|
||||
} catch (Exception e) {
|
||||
exception = e;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(String... progress) {
|
||||
showText.get().setText(String.format("%1$s/2 - %2$s...", progress[0], progress[1]));
|
||||
protected void onProgressUpdate(Integer... progress) {
|
||||
presenter.onLoginProgress(progress[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer messageID) {
|
||||
showProgress(false);
|
||||
|
||||
switch (messageID) {
|
||||
// if success
|
||||
case R.string.login_accepted_text:
|
||||
logFirstLoginAction(true, activity.get().getString(messageID));
|
||||
Intent intent = new Intent(activity.get(), DashboardActivity.class);
|
||||
activity.get().finish();
|
||||
activity.get().startActivity(intent);
|
||||
break;
|
||||
|
||||
// if bad credentials entered
|
||||
case R.string.login_bad_credentials_text:
|
||||
logFirstLoginAction(false, activity.get().getString(messageID));
|
||||
EditText passwordView = activity.get().findViewById(R.id.password);
|
||||
passwordView.setError(activity.get().getString(R.string.error_incorrect_password));
|
||||
passwordView.requestFocus();
|
||||
KeyboardUtils.showSoftInput(passwordView, activity.get());
|
||||
break;
|
||||
|
||||
// if no permission
|
||||
case R.string.error_bad_account_permission:
|
||||
logFirstLoginAction(false, activity.get().getString(messageID));
|
||||
// Change to visible symbol input view
|
||||
TextInputLayout symbolLayout = activity.get().findViewById(R.id.to_symbol_input_layout);
|
||||
symbolLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
EditText symbolView = activity.get().findViewById(R.id.symbol);
|
||||
symbolView.setError(activity.get().getString(R.string.error_bad_account_permission));
|
||||
symbolView.requestFocus();
|
||||
KeyboardUtils.showSoftInput(symbolView, activity.get());
|
||||
break;
|
||||
|
||||
// if rooted and SDK < 18
|
||||
case -1:
|
||||
logFirstLoginAction(false, "Device rooted");
|
||||
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(activity.get())
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setTitle(R.string.alert_dialog_blocked_app)
|
||||
.setMessage(R.string.alert_dialog_blocked_app_message)
|
||||
.setPositiveButton(R.string.generic_dialog_close, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialogInterface, int i) {
|
||||
dialogInterface.dismiss();
|
||||
}
|
||||
});
|
||||
alertDialog.show();
|
||||
break;
|
||||
|
||||
default:
|
||||
logFirstLoginAction(false, activity.get().getString(messageID));
|
||||
Snackbar.make(activity.get().findViewById(R.id.fragment_container),
|
||||
messageID, Snackbar.LENGTH_LONG).show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void logFirstLoginAction(boolean success, String message) {
|
||||
Answers.getInstance().logCustom(new CustomEvent("First login")
|
||||
.putCustomAttribute("Symbol", symbol)
|
||||
.putCustomAttribute("Success", success ? 1 : 0)
|
||||
.putCustomAttribute("Message", message));
|
||||
protected void onPostExecute(Boolean success) {
|
||||
presenter.onEndAsync(success, exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCancelled() {
|
||||
showProgress(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the progress UI and hides the login form.
|
||||
*/
|
||||
void showProgress(final boolean show) {
|
||||
loginFormView = new WeakReference<>(activity.get().findViewById(R.id.login_form));
|
||||
progressView = new WeakReference<>(activity.get().findViewById(R.id.login_progress));
|
||||
|
||||
int animTime = activity.get().getResources().getInteger(android.R.integer.config_shortAnimTime);
|
||||
|
||||
changeLoginFormVisibility(show, animTime);
|
||||
changeProgressVisibility(show, animTime);
|
||||
}
|
||||
|
||||
private void changeLoginFormVisibility(final boolean show, final int animTime) {
|
||||
loginFormView.get().setVisibility(show ? View.GONE : View.VISIBLE);
|
||||
loginFormView.get().animate().setDuration(animTime).alpha(
|
||||
show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
loginFormView.get().setVisibility(show ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void changeProgressVisibility(final boolean show, final int animTime) {
|
||||
progressView.get().setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
progressView.get().animate().setDuration(animTime).alpha(
|
||||
show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
progressView.get().setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
});
|
||||
presenter.onCanceledAsync();
|
||||
}
|
||||
}
|
||||
|
@ -1,189 +0,0 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
|
||||
import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.WulkanowyApp;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.utils.NetworkUtils;
|
||||
|
||||
public abstract class AbstractFragment<T extends AbstractExpandableHeaderItem> extends Fragment
|
||||
implements AsyncResponse<T> {
|
||||
|
||||
private FlexibleAdapter<T> flexibleAdapter;
|
||||
|
||||
private List<T> itemList = new ArrayList<>();
|
||||
|
||||
private WeakReference<Activity> activityWeakReference;
|
||||
|
||||
private SwipeRefreshLayout swipeRefreshLayout;
|
||||
|
||||
private RecyclerView recyclerViewLayout;
|
||||
|
||||
private DaoSession daoSession;
|
||||
|
||||
private long userId;
|
||||
|
||||
public AbstractFragment() {
|
||||
//empty constructor for fragments
|
||||
}
|
||||
|
||||
public long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public SwipeRefreshLayout getRefreshLayoutView() {
|
||||
return swipeRefreshLayout;
|
||||
}
|
||||
|
||||
public DaoSession getDaoSession() {
|
||||
return daoSession;
|
||||
}
|
||||
|
||||
public Activity getActivityWeakReference() {
|
||||
return activityWeakReference.get();
|
||||
}
|
||||
|
||||
public abstract int getLayoutId();
|
||||
|
||||
public abstract int getRecyclerViewId();
|
||||
|
||||
public abstract int getLoadingBarId();
|
||||
|
||||
public abstract int getRefreshLayoutId();
|
||||
|
||||
public abstract List<T> getItems() throws Exception;
|
||||
|
||||
public abstract void onRefresh() throws Exception;
|
||||
|
||||
public abstract void onPostRefresh(int stringResult);
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(getLayoutId(), container, false);
|
||||
recyclerViewLayout = view.findViewById(getRecyclerViewId());
|
||||
swipeRefreshLayout = view.findViewById(getRefreshLayoutId());
|
||||
setUpRefreshLayout(swipeRefreshLayout);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
if (getActivity() != null && getView() != null) {
|
||||
activityWeakReference = new WeakReference<Activity>(getActivity());
|
||||
daoSession = ((WulkanowyApp) getActivity().getApplication()).getDaoSession();
|
||||
userId = getActivity().getSharedPreferences("LoginData", Context.MODE_PRIVATE)
|
||||
.getLong("userId", 0);
|
||||
|
||||
if (itemList != null)
|
||||
if (itemList.isEmpty()) {
|
||||
flexibleAdapter = getFlexibleAdapter(itemList);
|
||||
setAdapterOnRecyclerView(recyclerViewLayout);
|
||||
if (getUserVisibleHint()) {
|
||||
new DatabaseQueryTask(this).execute();
|
||||
}
|
||||
} else {
|
||||
setAdapterOnRecyclerView(recyclerViewLayout);
|
||||
setLoadingBarInvisible(getView());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isResumed() && isVisibleToUser && flexibleAdapter.getItemCount() == 0) {
|
||||
new DatabaseQueryTask(this).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuarryProcessFinish(@NonNull List<T> resultItemList) {
|
||||
itemList = resultItemList;
|
||||
flexibleAdapter = getFlexibleAdapter(itemList);
|
||||
setAdapterOnRecyclerView(recyclerViewLayout);
|
||||
if (getView() != null) {
|
||||
setLoadingBarInvisible(getView());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshProcessFinish(@Nullable List<T> resultItemList, int stringEventId) {
|
||||
if (resultItemList != null) {
|
||||
itemList = resultItemList;
|
||||
updateDataInRecyclerView();
|
||||
}
|
||||
onPostRefresh(stringEventId);
|
||||
getRefreshLayoutView().setRefreshing(false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected FlexibleAdapter<T> getFlexibleAdapter(@NonNull List<T> itemList) {
|
||||
return new FlexibleAdapter<>(itemList)
|
||||
.setAutoCollapseOnExpand(true)
|
||||
.setAutoScrollOnExpand(true)
|
||||
.expandItemsAtStartUp();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private SwipeRefreshLayout.OnRefreshListener getDefaultRefreshListener() {
|
||||
return new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
if (NetworkUtils.isOnline(getContext())) {
|
||||
new RefreshTask(AbstractFragment.this).execute();
|
||||
} else {
|
||||
Toast.makeText(getContext(), R.string.noInternet_text, Toast.LENGTH_SHORT).show();
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void updateDataInRecyclerView() {
|
||||
flexibleAdapter.updateDataSet(itemList);
|
||||
setAdapterOnRecyclerView(recyclerViewLayout);
|
||||
}
|
||||
|
||||
protected void setUpRefreshLayout(@NonNull SwipeRefreshLayout swipeRefreshLayout) {
|
||||
swipeRefreshLayout.setColorSchemeResources(android.R.color.black);
|
||||
swipeRefreshLayout.setOnRefreshListener(getDefaultRefreshListener());
|
||||
}
|
||||
|
||||
protected final void setLoadingBarInvisible(@NonNull View mainView) {
|
||||
mainView.findViewById(getLoadingBarId()).setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
protected void setAdapterOnRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
recyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(getActivityWeakReference()));
|
||||
recyclerView.setAdapter(flexibleAdapter);
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem;
|
||||
|
||||
public interface AsyncResponse<T extends AbstractExpandableHeaderItem> {
|
||||
void onQuarryProcessFinish(@NonNull List<T> resultItemList);
|
||||
|
||||
void onRefreshProcessFinish(@Nullable List<T> resultItemList, int stringErrorId);
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.BottomNavigationView;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.services.Updater;
|
||||
import io.github.wulkanowy.ui.main.attendance.AttendanceFragment;
|
||||
import io.github.wulkanowy.ui.main.board.BoardFragment;
|
||||
import io.github.wulkanowy.ui.main.grades.GradesFragment;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetableFragment;
|
||||
|
||||
public class DashboardActivity extends AppCompatActivity {
|
||||
|
||||
private Fragment currentFragment;
|
||||
|
||||
private GradesFragment gradesFragment = new GradesFragment();
|
||||
|
||||
private AttendanceFragment attendanceFragment = new AttendanceFragment();
|
||||
|
||||
private BoardFragment boardFragment = new BoardFragment();
|
||||
|
||||
private TimetableFragment timetableFragment = new TimetableFragment();
|
||||
|
||||
private Updater updater;
|
||||
|
||||
private boolean showed;
|
||||
|
||||
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
|
||||
= new BottomNavigationView.OnNavigationItemSelectedListener() {
|
||||
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.navigation_marks:
|
||||
setTitle(R.string.grades_text);
|
||||
currentFragment = gradesFragment;
|
||||
break;
|
||||
|
||||
case R.id.navigation_attendance:
|
||||
setTitle(R.string.attendance_text);
|
||||
currentFragment = attendanceFragment;
|
||||
break;
|
||||
|
||||
case R.id.navigation_lessonplan:
|
||||
setTitle(R.string.lessonplan_text);
|
||||
currentFragment = timetableFragment;
|
||||
break;
|
||||
|
||||
case R.id.navigation_dashboard:
|
||||
default:
|
||||
setTitle(R.string.dashboard_text);
|
||||
currentFragment = boardFragment;
|
||||
break;
|
||||
}
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
transaction.replace(R.id.fragment_container, currentFragment);
|
||||
transaction.commit();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_dashboard);
|
||||
|
||||
BottomNavigationView navigation = findViewById(R.id.navigation);
|
||||
navigation.setSelectedItemId(R.id.navigation_marks);
|
||||
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
currentFragment = getSupportFragmentManager().getFragment(savedInstanceState, "currentFragment");
|
||||
setTitle(savedInstanceState.getString("activityTitle"));
|
||||
} else {
|
||||
currentFragment = gradesFragment;
|
||||
setTitle(R.string.grades_text);
|
||||
}
|
||||
|
||||
int cardID = getIntent().getIntExtra("cardID", 0);
|
||||
|
||||
if (cardID == 1) {
|
||||
currentFragment = gradesFragment;
|
||||
}
|
||||
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.fragment_container, currentFragment).commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if (!showed) {
|
||||
updater = new Updater(this).checkForUpdates();
|
||||
showed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
updater.onRequestPermissionsResult(requestCode, grantResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString("activityTitle", getTitle().toString());
|
||||
getSupportFragmentManager().putFragment(outState, "currentFragment", currentFragment);
|
||||
}
|
||||
|
||||
public void onBackPressed() {
|
||||
|
||||
BottomNavigationView navigation = findViewById(R.id.navigation);
|
||||
|
||||
if (navigation.getSelectedItemId() != R.id.navigation_dashboard) {
|
||||
navigation.setSelectedItemId(R.id.navigation_dashboard);
|
||||
} else if (navigation.getSelectedItemId() == R.id.navigation_dashboard) {
|
||||
moveTaskToBack(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
updater.onDestroy(this);
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DatabaseQueryTask extends AsyncTask<Void, Void, List<?>> {
|
||||
|
||||
private AbstractFragment abstractFragment;
|
||||
|
||||
public DatabaseQueryTask(AbstractFragment<?> abstractFragment) {
|
||||
this.abstractFragment = abstractFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<?> doInBackground(Void... voids) {
|
||||
try {
|
||||
return abstractFragment.getItems();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void onPostExecute(List<?> objects) {
|
||||
super.onPostExecute(objects);
|
||||
abstractFragment.onQuarryProcessFinish(objects);
|
||||
}
|
||||
}
|
153
app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.java
Normal file
153
app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.java
Normal file
@ -0,0 +1,153 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.view.View;
|
||||
|
||||
import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
|
||||
import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
|
||||
import com.aurelhubert.ahbottomnavigation.AHBottomNavigationViewPager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.services.SyncJob;
|
||||
import io.github.wulkanowy.ui.base.BaseActivity;
|
||||
import io.github.wulkanowy.ui.main.dashboard.DashboardFragment;
|
||||
import io.github.wulkanowy.ui.main.grades.GradesFragment;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetableFragment;
|
||||
|
||||
public class MainActivity extends BaseActivity implements MainContract.View,
|
||||
AHBottomNavigation.OnTabSelectedListener, OnFragmentIsReadyListener {
|
||||
|
||||
private int initTabPosition = 0;
|
||||
|
||||
@BindView(R.id.main_activity_nav)
|
||||
AHBottomNavigation bottomNavigation;
|
||||
|
||||
@BindView(R.id.main_activity_view_pager)
|
||||
AHBottomNavigationViewPager viewPager;
|
||||
|
||||
@BindView(R.id.main_activity_progress_bar)
|
||||
View progressBar;
|
||||
|
||||
@Inject
|
||||
MainPagerAdapter pagerAdapter;
|
||||
|
||||
@Inject
|
||||
MainContract.Presenter presenter;
|
||||
|
||||
public static Intent getStartIntent(Context context) {
|
||||
return new Intent(context, MainActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
initTabPosition = getIntent().getIntExtra(SyncJob.EXTRA_INTENT_KEY, initTabPosition);
|
||||
|
||||
getActivityComponent().inject(this);
|
||||
setButterKnife(ButterKnife.bind(this));
|
||||
|
||||
presenter.onStart(this);
|
||||
|
||||
initiationViewPager();
|
||||
initiationBottomNav();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showProgressBar(boolean show) {
|
||||
progressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
|
||||
viewPager.setVisibility(show ? View.INVISIBLE : View.VISIBLE);
|
||||
bottomNavigation.setVisibility(show ? View.INVISIBLE : View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showActionBar() {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideActionBar() {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTabSelected(int position, boolean wasSelected) {
|
||||
presenter.onTabSelected(position, wasSelected);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentPage(int position) {
|
||||
viewPager.setCurrentItem(position, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentIsReady() {
|
||||
presenter.onFragmentIsReady();
|
||||
}
|
||||
|
||||
private void initiationBottomNav() {
|
||||
bottomNavigation.addItem(new AHBottomNavigationItem(
|
||||
getString(R.string.grades_text),
|
||||
getResources().getDrawable(R.drawable.icon_grade_26dp)
|
||||
));
|
||||
bottomNavigation.addItem(new AHBottomNavigationItem(
|
||||
getString(R.string.attendance_text),
|
||||
getResources().getDrawable(R.drawable.icon_attendance_24dp)
|
||||
));
|
||||
bottomNavigation.addItem(new AHBottomNavigationItem(
|
||||
getString(R.string.dashboard_text),
|
||||
getResources().getDrawable(R.drawable.ic_dashboard_black_24dp)
|
||||
));
|
||||
bottomNavigation.addItem(new AHBottomNavigationItem(
|
||||
getString(R.string.lessonplan_text),
|
||||
getResources().getDrawable(R.drawable.icon_lessonplan_24dp)
|
||||
));
|
||||
bottomNavigation.addItem(new AHBottomNavigationItem(
|
||||
getString(R.string.settings_text),
|
||||
getResources().getDrawable(R.drawable.icon_other_24dp)
|
||||
));
|
||||
|
||||
bottomNavigation.setAccentColor(getResources().getColor(R.color.colorPrimary));
|
||||
bottomNavigation.setInactiveColor(Color.BLACK);
|
||||
bottomNavigation.setBackgroundColor(getResources().getColor(R.color.colorBackgroundBottomNavi));
|
||||
bottomNavigation.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW);
|
||||
bottomNavigation.setOnTabSelectedListener(this);
|
||||
bottomNavigation.setCurrentItem(initTabPosition);
|
||||
bottomNavigation.setBehaviorTranslationEnabled(false);
|
||||
}
|
||||
|
||||
private void initiationViewPager() {
|
||||
pagerAdapter.addFragment(new GradesFragment());
|
||||
pagerAdapter.addFragment(new DashboardFragment());
|
||||
pagerAdapter.addFragment(new DashboardFragment());
|
||||
pagerAdapter.addFragment(new TimetableFragment());
|
||||
pagerAdapter.addFragment(new DashboardFragment());
|
||||
|
||||
viewPager.setPagingEnabled(false);
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
viewPager.setOffscreenPageLimit(4);
|
||||
viewPager.setCurrentItem(initTabPosition, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
presenter.onDestroy();
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
import io.github.wulkanowy.di.annotations.PerActivity;
|
||||
import io.github.wulkanowy.ui.base.BaseContract;
|
||||
|
||||
public interface MainContract {
|
||||
|
||||
interface View extends BaseContract.View {
|
||||
|
||||
void setCurrentPage(int position);
|
||||
|
||||
void showProgressBar(boolean show);
|
||||
|
||||
void showActionBar();
|
||||
|
||||
void hideActionBar();
|
||||
}
|
||||
|
||||
@PerActivity
|
||||
interface Presenter extends BaseContract.Presenter<View> {
|
||||
|
||||
void onTabSelected(int position, boolean wasSelected);
|
||||
|
||||
void onFragmentIsReady();
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MainPagerAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private List<Fragment> fragmentList = new ArrayList<>();
|
||||
|
||||
public MainPagerAdapter(FragmentManager fragmentManager) {
|
||||
super(fragmentManager);
|
||||
}
|
||||
|
||||
void addFragment(Fragment fragment) {
|
||||
fragmentList.add(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return fragmentList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return fragmentList.size();
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.ui.base.BasePresenter;
|
||||
|
||||
public class MainPresenter extends BasePresenter<MainContract.View>
|
||||
implements MainContract.Presenter {
|
||||
|
||||
private int fragmentCount = 0;
|
||||
|
||||
@Inject
|
||||
MainPresenter(RepositoryContract repository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(MainContract.View view) {
|
||||
super.onStart(view);
|
||||
getView().showProgressBar(true);
|
||||
getView().hideActionBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabSelected(int position, boolean wasSelected) {
|
||||
if (!wasSelected) {
|
||||
getView().setCurrentPage(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentIsReady() {
|
||||
if (fragmentCount < 5) {
|
||||
fragmentCount++;
|
||||
}
|
||||
|
||||
if (fragmentCount == 5) {
|
||||
getView().showActionBar();
|
||||
getView().showProgressBar(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
public interface OnFragmentIsReadyListener {
|
||||
|
||||
void onFragmentIsReady();
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package io.github.wulkanowy.ui.main;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
|
||||
public class RefreshTask extends AsyncTask<Void, Void, List<?>> {
|
||||
|
||||
public static final String DEBUG_TAG = "RefreshTask";
|
||||
|
||||
private int stringEventId = 0;
|
||||
|
||||
private AbstractFragment abstractFragment;
|
||||
|
||||
public RefreshTask(AbstractFragment abstractFragment) {
|
||||
this.abstractFragment = abstractFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<?> doInBackground(Void... voids) {
|
||||
try {
|
||||
abstractFragment.onRefresh();
|
||||
return abstractFragment.getItems();
|
||||
} catch (UnknownHostException e) {
|
||||
stringEventId = R.string.noInternet_text;
|
||||
Log.i(DEBUG_TAG, "Synchronization is failed because occur problem with internet",
|
||||
e.getCause());
|
||||
return null;
|
||||
} catch (SocketTimeoutException e) {
|
||||
stringEventId = R.string.generic_timeout_error;
|
||||
Log.i(DEBUG_TAG, "Too long wait for connection with internet", e);
|
||||
return null;
|
||||
} catch (VulcanOfflineException e) {
|
||||
stringEventId = R.string.error_host_offline;
|
||||
Log.i(DEBUG_TAG, "VULCAN services is offline");
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
stringEventId = R.string.refresh_error_text;
|
||||
Log.e(DEBUG_TAG, "There was a sync problem", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void onPostExecute(List<?> objects) {
|
||||
super.onPostExecute(objects);
|
||||
abstractFragment.onRefreshProcessFinish(objects, stringEventId);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package io.github.wulkanowy.ui.main.attendance;
|
||||
|
||||
import io.github.wulkanowy.di.annotations.PerFragment;
|
||||
import io.github.wulkanowy.ui.base.BaseContract;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public interface AttendanceContract {
|
||||
|
||||
interface View extends BaseContract.View {
|
||||
|
||||
void setActivityTitle();
|
||||
|
||||
boolean isMenuVisible();
|
||||
}
|
||||
|
||||
@PerFragment
|
||||
interface Presenter extends BaseContract.Presenter<View> {
|
||||
|
||||
void onStart(View view, OnFragmentIsReadyListener listener);
|
||||
|
||||
void onFragmentVisible(boolean isVisible);
|
||||
}
|
||||
}
|
@ -2,18 +2,58 @@ package io.github.wulkanowy.ui.main.attendance;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class AttendanceFragment extends Fragment {
|
||||
import butterknife.ButterKnife;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.di.component.FragmentComponent;
|
||||
import io.github.wulkanowy.ui.base.BaseFragment;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public class AttendanceFragment extends BaseFragment implements AttendanceContract.View {
|
||||
|
||||
@Inject
|
||||
AttendanceContract.Presenter presenter;
|
||||
|
||||
public AttendanceFragment() {
|
||||
// empty constructor for fragment
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_attendance, container, false);
|
||||
View view = inflater.inflate(R.layout.fragment_attendance, container, false);
|
||||
|
||||
FragmentComponent component = getFragmentComponent();
|
||||
if (component != null) {
|
||||
component.inject(this);
|
||||
setButterKnife(ButterKnife.bind(this, view));
|
||||
presenter.onStart(this, (OnFragmentIsReadyListener) getActivity());
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMenuVisibility(boolean menuVisible) {
|
||||
super.setMenuVisibility(menuVisible);
|
||||
if (presenter != null) {
|
||||
presenter.onFragmentVisible(menuVisible);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActivityTitle() {
|
||||
setTitle(getString(R.string.dashboard_text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
presenter.onDestroy();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package io.github.wulkanowy.ui.main.attendance;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.ui.base.BasePresenter;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public class AttendancePresenter extends BasePresenter<AttendanceContract.View>
|
||||
implements AttendanceContract.Presenter {
|
||||
|
||||
private OnFragmentIsReadyListener listener;
|
||||
|
||||
@Inject
|
||||
AttendancePresenter(RepositoryContract repository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(AttendanceContract.View view, OnFragmentIsReadyListener listener) {
|
||||
super.onStart(view);
|
||||
this.listener = listener;
|
||||
|
||||
if (getView().isMenuVisible()) {
|
||||
getView().setActivityTitle();
|
||||
}
|
||||
|
||||
this.listener.onFragmentIsReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentVisible(boolean isVisible) {
|
||||
if (isVisible) {
|
||||
getView().setActivityTitle();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package io.github.wulkanowy.ui.main.board;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
|
||||
public class BoardFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_board, container, false);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package io.github.wulkanowy.ui.main.dashboard;
|
||||
|
||||
import io.github.wulkanowy.di.annotations.PerActivity;
|
||||
import io.github.wulkanowy.ui.base.BaseContract;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public interface DashboardContract {
|
||||
|
||||
interface View extends BaseContract.View {
|
||||
|
||||
void setActivityTitle();
|
||||
|
||||
boolean isMenuVisible();
|
||||
}
|
||||
|
||||
@PerActivity
|
||||
interface Presenter extends BaseContract.Presenter<View> {
|
||||
|
||||
void onStart(View view, OnFragmentIsReadyListener listener);
|
||||
|
||||
void onFragmentVisible(boolean isVisible);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package io.github.wulkanowy.ui.main.dashboard;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.di.component.FragmentComponent;
|
||||
import io.github.wulkanowy.ui.base.BaseFragment;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public class DashboardFragment extends BaseFragment implements DashboardContract.View {
|
||||
|
||||
@Inject
|
||||
DashboardContract.Presenter presenter;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_board, container, false);
|
||||
|
||||
FragmentComponent component = getFragmentComponent();
|
||||
if (component != null) {
|
||||
component.inject(this);
|
||||
setButterKnife(ButterKnife.bind(this, view));
|
||||
presenter.onStart(this, (OnFragmentIsReadyListener) getActivity());
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMenuVisibility(boolean menuVisible) {
|
||||
super.setMenuVisibility(menuVisible);
|
||||
if (presenter != null) {
|
||||
presenter.onFragmentVisible(menuVisible);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActivityTitle() {
|
||||
setTitle(getString(R.string.dashboard_text));
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package io.github.wulkanowy.ui.main.dashboard;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.ui.base.BasePresenter;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public class DashboardPresenter extends BasePresenter<DashboardContract.View>
|
||||
implements DashboardContract.Presenter {
|
||||
|
||||
private OnFragmentIsReadyListener listener;
|
||||
|
||||
@Inject
|
||||
DashboardPresenter(RepositoryContract repository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(DashboardContract.View view, OnFragmentIsReadyListener listener) {
|
||||
super.onStart(view);
|
||||
this.listener = listener;
|
||||
|
||||
if (getView().isMenuVisible()) {
|
||||
getView().setActivityTitle();
|
||||
}
|
||||
|
||||
this.listener.onFragmentIsReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentVisible(boolean isVisible) {
|
||||
if (isVisible) {
|
||||
getView().setActivityTitle();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package io.github.wulkanowy.ui.main.grades;
|
||||
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem;
|
||||
import eu.davidea.viewholders.ExpandableViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.utils.AverageCalculator;
|
||||
|
||||
public class GradeHeaderItem
|
||||
extends AbstractExpandableHeaderItem<GradeHeaderItem.HeaderViewHolder, GradesSubItem> {
|
||||
|
||||
private Subject subject;
|
||||
|
||||
GradeHeaderItem(Subject subject) {
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GradeHeaderItem that = (GradeHeaderItem) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(subject, that.subject)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(subject)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.grade_header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
|
||||
return new HeaderViewHolder(view, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(FlexibleAdapter adapter, HeaderViewHolder holder, int position, List payloads) {
|
||||
holder.onBind(subject, getSubItems());
|
||||
}
|
||||
|
||||
static class HeaderViewHolder extends ExpandableViewHolder {
|
||||
|
||||
@BindView(R.id.grade_header_subject_text)
|
||||
TextView subjectName;
|
||||
|
||||
@BindView(R.id.grade_header_average_text)
|
||||
TextView averageText;
|
||||
|
||||
@BindView(R.id.grade_header_number_of_grade_text)
|
||||
TextView numberText;
|
||||
|
||||
@BindView(R.id.grade_header_alert_image)
|
||||
View alertImage;
|
||||
|
||||
Resources resources;
|
||||
|
||||
HeaderViewHolder(View view, FlexibleAdapter adapter) {
|
||||
super(view, adapter);
|
||||
ButterKnife.bind(this, view);
|
||||
resources = view.getResources();
|
||||
view.setOnClickListener(this);
|
||||
}
|
||||
|
||||
void onBind(Subject item, List<GradesSubItem> subItems) {
|
||||
subjectName.setText(item.getName());
|
||||
numberText.setText(resources.getQuantityString(R.plurals.numberOfGradesPlurals,
|
||||
subItems.size(), subItems.size()));
|
||||
averageText.setText(getGradesAverageString(item));
|
||||
alertImage.setVisibility(isSubItemsRead(subItems) ? View.INVISIBLE : View.VISIBLE);
|
||||
alertImage.setTag(item.getName());
|
||||
}
|
||||
|
||||
private boolean isSubItemsRead(List<GradesSubItem> subItems) {
|
||||
boolean isRead = true;
|
||||
|
||||
for (GradesSubItem item : subItems) {
|
||||
isRead = item.getGrade().getRead();
|
||||
}
|
||||
return isRead;
|
||||
}
|
||||
|
||||
private String getGradesAverageString(Subject item) {
|
||||
float average = AverageCalculator.calculate(item.getGradeList());
|
||||
|
||||
if (average < 0) {
|
||||
return resources.getString(R.string.info_no_average);
|
||||
} else {
|
||||
return resources.getString(R.string.info_average_grades, average);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
package io.github.wulkanowy.ui.main.grades;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.DialogFragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.thoughtbot.expandablerecyclerview.ExpandableRecyclerViewAdapter;
|
||||
import com.thoughtbot.expandablerecyclerview.models.ExpandableGroup;
|
||||
import com.thoughtbot.expandablerecyclerview.viewholders.ChildViewHolder;
|
||||
import com.thoughtbot.expandablerecyclerview.viewholders.GroupViewHolder;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.utils.AverageCalculator;
|
||||
|
||||
public class GradesAdapter extends ExpandableRecyclerViewAdapter<GradesAdapter.SubjectViewHolder, GradesAdapter.GradeViewHolder> {
|
||||
|
||||
private static int numberOfNotReadGrade;
|
||||
|
||||
private Activity activity;
|
||||
|
||||
public GradesAdapter(List<? extends ExpandableGroup> groups, Activity activity) {
|
||||
super(groups);
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.subject_item, parent, false);
|
||||
return new SubjectViewHolder(view, activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GradeViewHolder onCreateChildViewHolder(ViewGroup child, int viewType) {
|
||||
View view = LayoutInflater.from(child.getContext()).inflate(R.layout.grade_item, child, false);
|
||||
return new GradeViewHolder(view, activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindGroupViewHolder(SubjectViewHolder holder, int flatPosition, ExpandableGroup group) {
|
||||
holder.bind(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindChildViewHolder(GradeViewHolder holder, int flatPosition, ExpandableGroup group, int childIndex) {
|
||||
holder.bind((Grade) group.getItems().get(childIndex));
|
||||
}
|
||||
|
||||
public static class SubjectViewHolder extends GroupViewHolder {
|
||||
|
||||
private WeakReference<Activity> activity;
|
||||
|
||||
private TextView subjectName;
|
||||
|
||||
private TextView numberOfGrades;
|
||||
|
||||
private TextView averageGrades;
|
||||
|
||||
private ImageView subjectAlertNewGrades;
|
||||
|
||||
public SubjectViewHolder(View itemView, Activity activity) {
|
||||
super(itemView);
|
||||
this.activity = new WeakReference<>(activity);
|
||||
|
||||
subjectName = itemView.findViewById(R.id.subject_text);
|
||||
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);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void bind(ExpandableGroup group) {
|
||||
int volumeGrades = group.getItemCount();
|
||||
List<Grade> gradeList = group.getItems();
|
||||
float average = AverageCalculator.calculate(gradeList);
|
||||
|
||||
itemView.setTag(group.getTitle());
|
||||
|
||||
if (average < 0) {
|
||||
averageGrades.setText(R.string.info_no_average);
|
||||
} else {
|
||||
averageGrades.setText(activity.get().getResources().getString(R.string.info_average_grades, average));
|
||||
}
|
||||
subjectName.setText(group.getTitle());
|
||||
numberOfGrades.setText(activity.get().getResources().getQuantityString(R.plurals.numberOfGradesPlurals, volumeGrades, volumeGrades));
|
||||
|
||||
for (Grade grade : gradeList) {
|
||||
if (!grade.getRead()) {
|
||||
subjectAlertNewGrades.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
subjectAlertNewGrades.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class GradeViewHolder extends ChildViewHolder {
|
||||
|
||||
private WeakReference<Activity> activity;
|
||||
|
||||
private TextView gradeValue;
|
||||
|
||||
private TextView descriptionGrade;
|
||||
|
||||
private TextView dateGrade;
|
||||
|
||||
private ImageView alertNewGrade;
|
||||
|
||||
private View itemView;
|
||||
|
||||
private Grade gradeItem;
|
||||
|
||||
public GradeViewHolder(View itemView, Activity activity) {
|
||||
super(itemView);
|
||||
this.itemView = itemView;
|
||||
this.activity = new WeakReference<>(activity);
|
||||
|
||||
gradeValue = itemView.findViewById(R.id.grade_text);
|
||||
descriptionGrade = itemView.findViewById(R.id.description_grade_text);
|
||||
dateGrade = itemView.findViewById(R.id.grade_date_text);
|
||||
alertNewGrade = itemView.findViewById(R.id.grade_new_grades_alert);
|
||||
}
|
||||
|
||||
public void bind(Grade grade) {
|
||||
gradeValue.setText(grade.getValue());
|
||||
gradeValue.setBackgroundResource(grade.getValueColor());
|
||||
dateGrade.setText(grade.getDate());
|
||||
gradeItem = grade;
|
||||
|
||||
if (grade.getDescription() == null || "".equals(grade.getDescription())) {
|
||||
if (!"".equals(grade.getSymbol())) {
|
||||
descriptionGrade.setText(grade.getSymbol());
|
||||
} else {
|
||||
descriptionGrade.setText(R.string.noDescription_text);
|
||||
}
|
||||
} else {
|
||||
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.get().getFragmentManager(), gradeItem.toString());
|
||||
|
||||
if (!gradeItem.getRead()) {
|
||||
numberOfNotReadGrade--;
|
||||
}
|
||||
|
||||
if (numberOfNotReadGrade == 0) {
|
||||
View subjectView = activity.get().findViewById(R.id.subject_grade_recycler).findViewWithTag(gradeItem.getSubject());
|
||||
if (subjectView != null) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package io.github.wulkanowy.ui.main.grades;
|
||||
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.di.annotations.PerActivity;
|
||||
import io.github.wulkanowy.ui.base.BaseContract;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public interface GradesContract {
|
||||
|
||||
interface View extends BaseContract.View, SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
void updateAdapterList(List<GradeHeaderItem> headerItems);
|
||||
|
||||
void showNoItem(boolean show);
|
||||
|
||||
void onRefreshSuccessNoGrade();
|
||||
|
||||
void onRefreshSuccess(int number);
|
||||
|
||||
void hideRefreshingBar();
|
||||
|
||||
void setActivityTitle();
|
||||
|
||||
boolean isMenuVisible();
|
||||
|
||||
}
|
||||
|
||||
@PerActivity
|
||||
interface Presenter extends BaseContract.Presenter<View> {
|
||||
|
||||
void onFragmentVisible(boolean isVisible);
|
||||
|
||||
void onRefresh();
|
||||
|
||||
void onStart(View view, OnFragmentIsReadyListener listener);
|
||||
}
|
||||
}
|
@ -1,107 +1,116 @@
|
||||
package io.github.wulkanowy.ui.main.grades;
|
||||
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.utils.CommonUtils;
|
||||
|
||||
public class GradesDialogFragment extends DialogFragment {
|
||||
|
||||
private static final String ARGUMENT_KEY = "Item";
|
||||
|
||||
private Grade grade;
|
||||
|
||||
@BindView(R.id.grade_dialog_value)
|
||||
TextView value;
|
||||
|
||||
@BindView(R.id.grade_dialog_subject)
|
||||
TextView subject;
|
||||
|
||||
@BindView(R.id.grade_dialog_description_value)
|
||||
TextView description;
|
||||
|
||||
@BindView(R.id.grade_dialog_weight_value)
|
||||
TextView weight;
|
||||
|
||||
@BindView(R.id.grade_dialog_teacher_value)
|
||||
TextView teacher;
|
||||
|
||||
@BindView(R.id.grade_dialog_color_value)
|
||||
TextView color;
|
||||
|
||||
@BindView(R.id.grade_dialog_date_value)
|
||||
TextView date;
|
||||
|
||||
public GradesDialogFragment() {
|
||||
setRetainInstance(true);
|
||||
//empty constructor for fragment
|
||||
}
|
||||
|
||||
public static final GradesDialogFragment newInstance(Grade grade) {
|
||||
return new GradesDialogFragment().setGrade(grade);
|
||||
public static GradesDialogFragment newInstance(Grade item) {
|
||||
GradesDialogFragment dialogFragment = new GradesDialogFragment();
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(ARGUMENT_KEY, item);
|
||||
|
||||
dialogFragment.setArguments(bundle);
|
||||
|
||||
return dialogFragment;
|
||||
}
|
||||
|
||||
public static int colorHexToColorName(String hexColor) {
|
||||
switch (hexColor) {
|
||||
case "000000":
|
||||
return R.string.color_black_text;
|
||||
|
||||
case "F04C4C":
|
||||
return R.string.color_red_text;
|
||||
|
||||
case "20A4F7":
|
||||
return R.string.color_blue_text;
|
||||
|
||||
case "6ECD07":
|
||||
return R.string.color_green_text;
|
||||
|
||||
default:
|
||||
return R.string.noColor_text;
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
grade = (Grade) getArguments().getSerializable(ARGUMENT_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
private GradesDialogFragment setGrade(Grade grade) {
|
||||
this.grade = grade;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.grades_dialog, container, false);
|
||||
View view = inflater.inflate(R.layout.grade_dialog, container, false);
|
||||
|
||||
TextView gradeText = view.findViewById(R.id.dialog_grade_text);
|
||||
TextView subjectText = view.findViewById(R.id.subject_dialog_text_value);
|
||||
TextView descriptionText = view.findViewById(R.id.description_dialog_text_value);
|
||||
TextView weightText = view.findViewById(R.id.weight_dialog_text_value);
|
||||
TextView teacherText = view.findViewById(R.id.teacher_dialog_text_value);
|
||||
TextView dateText = view.findViewById(R.id.date_dialog_text_value);
|
||||
TextView colorText = view.findViewById(R.id.color_dialog_text_value);
|
||||
Button closeDialog = view.findViewById(R.id.close_dialog);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
subjectText.setText(grade.getSubject());
|
||||
gradeText.setText(grade.getValue());
|
||||
gradeText.setBackgroundResource(grade.getValueColor());
|
||||
weightText.setText(grade.getWeight());
|
||||
dateText.setText(grade.getDate());
|
||||
colorText.setText(colorHexToColorName(grade.getColor()));
|
||||
subject.setText(grade.getSubject());
|
||||
value.setText(grade.getValue());
|
||||
value.setBackgroundResource(grade.getValueColor());
|
||||
weight.setText(grade.getWeight());
|
||||
date.setText(grade.getDate());
|
||||
color.setText(CommonUtils.colorHexToColorName(grade.getColor()));
|
||||
teacher.setText(getTeacherString());
|
||||
description.setText(getDescriptionString());
|
||||
|
||||
if ("".equals(grade.getDescription())) {
|
||||
if (!"".equals(grade.getSymbol())) {
|
||||
descriptionText.setText(grade.getSymbol());
|
||||
}
|
||||
} else if (!"".equals(grade.getSymbol())) {
|
||||
descriptionText.setText(String.format("%1$s - %2$s", grade.getSymbol(), grade.getDescription()));
|
||||
} else {
|
||||
descriptionText.setText(grade.getDescription());
|
||||
}
|
||||
|
||||
if (!"".equals(grade.getTeacher())) {
|
||||
teacherText.setText(grade.getTeacher());
|
||||
}
|
||||
|
||||
closeDialog.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog != null && getRetainInstance()) {
|
||||
dialog.setDismissMessage(null);
|
||||
@OnClick(R.id.grade_dialog_close_button)
|
||||
void onClickClose() {
|
||||
dismiss();
|
||||
}
|
||||
|
||||
private String getDescriptionString() {
|
||||
if ("".equals(grade.getDescription())) {
|
||||
if (!"".equals(grade.getSymbol())) {
|
||||
return grade.getSymbol();
|
||||
} else {
|
||||
return getString(R.string.noDescription_text);
|
||||
}
|
||||
} else if (!"".equals(grade.getSymbol())) {
|
||||
return String.format("%1$s - %2$s", grade.getSymbol(), grade.getDescription());
|
||||
} else {
|
||||
return grade.getDescription();
|
||||
}
|
||||
}
|
||||
|
||||
private String getTeacherString() {
|
||||
if (grade.getTeacher() != null && !"".equals(grade.getTeacher())) {
|
||||
return grade.getTeacher();
|
||||
} else {
|
||||
return getString(R.string.generic_app_no_data);
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
}
|
||||
|
@ -1,211 +1,133 @@
|
||||
package io.github.wulkanowy.ui.main.grades;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
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.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.WulkanowyApp;
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
||||
import io.github.wulkanowy.db.dao.DatabaseAccess;
|
||||
import io.github.wulkanowy.db.dao.entities.Account;
|
||||
import io.github.wulkanowy.db.dao.entities.AccountDao;
|
||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.services.jobs.VulcanJobHelper;
|
||||
import io.github.wulkanowy.services.sync.LoginSession;
|
||||
import io.github.wulkanowy.services.sync.VulcanSync;
|
||||
import io.github.wulkanowy.utils.NetworkUtils;
|
||||
import io.github.wulkanowy.di.component.FragmentComponent;
|
||||
import io.github.wulkanowy.ui.base.BaseFragment;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public class GradesFragment extends Fragment {
|
||||
public class GradesFragment extends BaseFragment implements GradesContract.View {
|
||||
|
||||
private static List<SubjectWithGrades> subjectWithGradesList = new ArrayList<>();
|
||||
@BindView(R.id.grade_fragment_recycler)
|
||||
RecyclerView recyclerView;
|
||||
|
||||
private static long userId;
|
||||
@BindView(R.id.grade_fragment_no_item_container)
|
||||
View noItemView;
|
||||
|
||||
@BindView(R.id.grade_fragment_swipe_refresh)
|
||||
SwipeRefreshLayout refreshLayout;
|
||||
|
||||
@Inject
|
||||
FlexibleAdapter<GradeHeaderItem> adapter;
|
||||
|
||||
@Inject
|
||||
GradesContract.Presenter presenter;
|
||||
|
||||
public GradesFragment() {
|
||||
//empty constructor for fragments
|
||||
// empty constructor for fragment
|
||||
}
|
||||
|
||||
private static void createExpList(View mainView, Activity activity) {
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_grades, container, false);
|
||||
|
||||
RecyclerView recyclerView = mainView.findViewById(R.id.subject_grade_recycler);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
|
||||
GradesAdapter gradesAdapter = new GradesAdapter(subjectWithGradesList, activity);
|
||||
recyclerView.setAdapter(gradesAdapter);
|
||||
FragmentComponent component = getFragmentComponent();
|
||||
if (component != null) {
|
||||
component.inject(this);
|
||||
setButterKnife(ButterKnife.bind(this, view));
|
||||
presenter.onStart(this, (OnFragmentIsReadyListener) getActivity());
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private static void downloadGradesFormDatabase(DaoSession daoSession) {
|
||||
@Override
|
||||
protected void setUpOnViewCreated(View fragmentView) {
|
||||
noItemView.setVisibility(View.GONE);
|
||||
|
||||
subjectWithGradesList = new ArrayList<>();
|
||||
adapter.setAutoCollapseOnExpand(true);
|
||||
adapter.setAutoScrollOnExpand(true);
|
||||
adapter.expandItemsAtStartUp();
|
||||
|
||||
AccountDao accountDao = daoSession.getAccountDao();
|
||||
Account account = accountDao.load(userId);
|
||||
recyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(fragmentView.getContext()));
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
for (Subject subject : account.getSubjectList()) {
|
||||
List<Grade> gradeList = subject.getGradeList();
|
||||
if (!gradeList.isEmpty()) {
|
||||
SubjectWithGrades subjectWithGrades = new SubjectWithGrades(subject.getName(), gradeList);
|
||||
subjectWithGradesList.add(subjectWithGrades);
|
||||
}
|
||||
refreshLayout.setColorSchemeResources(android.R.color.black);
|
||||
refreshLayout.setOnRefreshListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMenuVisibility(boolean menuVisible) {
|
||||
super.setMenuVisibility(menuVisible);
|
||||
if (presenter != null) {
|
||||
presenter.onFragmentVisible(menuVisible);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_grades, container, false);
|
||||
view.findViewById(R.id.fragment_no_grades).setVisibility(View.GONE);
|
||||
public void setActivityTitle() {
|
||||
setTitle(getString(R.string.grades_text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
presenter.onRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showNoItem(boolean show) {
|
||||
noItemView.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideRefreshingBar() {
|
||||
refreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAdapterList(List<GradeHeaderItem> headerItems) {
|
||||
adapter.updateDataSet(headerItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSuccessNoGrade() {
|
||||
onError(R.string.snackbar_no_grades);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSuccess(int number) {
|
||||
onError(getString(R.string.snackbar_new_grade, number));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String message) {
|
||||
if (getActivity() != null) {
|
||||
DaoSession daoSession = ((WulkanowyApp) getActivity().getApplication()).getDaoSession();
|
||||
userId = getActivity().getSharedPreferences("LoginData", Context.MODE_PRIVATE)
|
||||
.getLong("userId", 0);
|
||||
|
||||
prepareRefreshLayout(view, daoSession);
|
||||
|
||||
if (subjectWithGradesList.equals(new ArrayList<>())) {
|
||||
createExpList(view, getActivity());
|
||||
new GenerateListTask(getActivity(), view, daoSession).execute();
|
||||
} else {
|
||||
createExpList(view, getActivity());
|
||||
view.findViewById(R.id.loadingPanel).setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private void prepareRefreshLayout(final View mainView, final DaoSession daoSession) {
|
||||
|
||||
final SwipeRefreshLayout swipeRefreshLayout = mainView.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 (NetworkUtils.isOnline(getContext())) {
|
||||
new RefreshTask(getActivity(), mainView, daoSession).execute();
|
||||
} else {
|
||||
Toast.makeText(mainView.getContext(), R.string.noInternet_text, Toast.LENGTH_SHORT).show();
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class GenerateListTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private WeakReference<View> mainView;
|
||||
|
||||
private WeakReference<Activity> activity;
|
||||
|
||||
private DaoSession daoSession;
|
||||
|
||||
public GenerateListTask(Activity activity, View mainView, DaoSession daoSession) {
|
||||
this.activity = new WeakReference<>(activity);
|
||||
this.mainView = new WeakReference<>(mainView);
|
||||
this.daoSession = daoSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
downloadGradesFormDatabase(daoSession);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
super.onPostExecute(result);
|
||||
createExpList(mainView.get(), activity.get());
|
||||
mainView.get().findViewById(R.id.loadingPanel).setVisibility(View.INVISIBLE);
|
||||
if (subjectWithGradesList.isEmpty()) {
|
||||
mainView.get().findViewById(R.id.fragment_no_grades).setVisibility(View.VISIBLE);
|
||||
}
|
||||
Snackbar.make(getActivity().findViewById(R.id.main_activity_view_pager),
|
||||
message, Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private static class RefreshTask extends AsyncTask<Void, Void, Integer> {
|
||||
|
||||
private DaoSession daoSession;
|
||||
|
||||
private WeakReference<Activity> activity;
|
||||
|
||||
private WeakReference<View> mainView;
|
||||
|
||||
public RefreshTask(Activity activity, View mainView, DaoSession daoSession) {
|
||||
this.activity = new WeakReference<>(activity);
|
||||
this.daoSession = daoSession;
|
||||
this.mainView = new WeakReference<>(mainView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(Void... params) {
|
||||
VulcanSync vulcanSync = new VulcanSync(new LoginSession());
|
||||
try {
|
||||
vulcanSync.loginCurrentUser(activity.get(), daoSession, new Vulcan());
|
||||
vulcanSync.syncGrades();
|
||||
downloadGradesFormDatabase(daoSession);
|
||||
return 1;
|
||||
} catch (VulcanOfflineException e) {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "There was a sync problem, because vulcan is offline", e);
|
||||
return R.string.error_host_offline;
|
||||
} catch (Exception e) {
|
||||
Log.e(VulcanJobHelper.DEBUG_TAG, "There was a sync problem", e);
|
||||
return R.string.refresh_error_text;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Integer messageID) {
|
||||
super.onPostExecute(messageID);
|
||||
|
||||
if (1 == messageID) {
|
||||
if (mainView.get() != null && activity.get() != null) {
|
||||
createExpList(mainView.get(), activity.get());
|
||||
}
|
||||
|
||||
int volumeGrades = new DatabaseAccess().getNewGrades(daoSession).size();
|
||||
|
||||
if (volumeGrades == 0) {
|
||||
Snackbar.make(activity.get().findViewById(R.id.fragment_container),
|
||||
R.string.snackbar_no_grades,
|
||||
Snackbar.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Snackbar.make(activity.get().findViewById(R.id.fragment_container),
|
||||
activity.get().getString(R.string.snackbar_new_grade, volumeGrades),
|
||||
Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(activity.get(), messageID, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
if (mainView.get() != null) {
|
||||
SwipeRefreshLayout swipeRefreshLayout = mainView.get().findViewById(R.id.grade_swipe_refresh);
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
presenter.onDestroy();
|
||||
super.onDestroyView();
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user