forked from github/wulkanowy-mirror
MVP (#46)
This commit is contained in:
parent
a1a3427142
commit
79bdbbbb16
@ -1,5 +1,5 @@
|
|||||||
exclude:
|
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
|
component_depth: 1
|
||||||
languages:
|
languages:
|
||||||
- java
|
- java
|
||||||
|
@ -48,7 +48,7 @@ public class Vulcan {
|
|||||||
this.login = login;
|
this.login = login;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String login(String email, String password, String symbol)
|
public void login(String email, String password, String symbol)
|
||||||
throws BadCredentialsException, AccountPermissionException,
|
throws BadCredentialsException, AccountPermissionException,
|
||||||
LoginErrorException, IOException, VulcanOfflineException {
|
LoginErrorException, IOException, VulcanOfflineException {
|
||||||
|
|
||||||
@ -56,8 +56,6 @@ public class Vulcan {
|
|||||||
login = getLogin();
|
login = getLogin();
|
||||||
|
|
||||||
this.symbol = login.login(this.email, password, symbol);
|
this.symbol = login.login(this.email, password, symbol);
|
||||||
|
|
||||||
return this.symbol;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vulcan login(String email, String password, String symbol, String id)
|
public Vulcan login(String email, String password, String symbol, String id)
|
||||||
@ -82,6 +80,10 @@ public class Vulcan {
|
|||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSymbol() {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
private void setFullEndpointInfo(String email) {
|
private void setFullEndpointInfo(String email) {
|
||||||
String[] creds = email.split("\\\\");
|
String[] creds = email.split("\\\\");
|
||||||
|
|
||||||
|
@ -27,14 +27,6 @@ public class Login {
|
|||||||
this.client = client;
|
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)
|
public String login(String email, String password, String symbol)
|
||||||
throws BadCredentialsException, LoginErrorException,
|
throws BadCredentialsException, LoginErrorException,
|
||||||
AccountPermissionException, IOException, VulcanOfflineException {
|
AccountPermissionException, IOException, VulcanOfflineException {
|
||||||
@ -47,7 +39,7 @@ public class Login {
|
|||||||
throws IOException, BadCredentialsException {
|
throws IOException, BadCredentialsException {
|
||||||
this.symbol = symbol;
|
this.symbol = symbol;
|
||||||
|
|
||||||
Document html = client.postPageByUrl(getLoginPageUrl(), new String[][]{
|
Document html = client.postPageByUrl(LOGIN_PAGE_URL, new String[][]{
|
||||||
{"LoginName", email},
|
{"LoginName", email},
|
||||||
{"Password", password}
|
{"Password", password}
|
||||||
});
|
});
|
||||||
@ -64,8 +56,7 @@ public class Login {
|
|||||||
this.symbol = findSymbol(defaultSymbol, certificate);
|
this.symbol = findSymbol(defaultSymbol, certificate);
|
||||||
client.setSymbol(this.symbol);
|
client.setSymbol(this.symbol);
|
||||||
|
|
||||||
Document html = client.postPageByUrl(getLoginEndpointPageUrl()
|
Document html = client.postPageByUrl(LOGIN_ENDPOINT_PAGE_URL, new String[][]{
|
||||||
.replace("{symbol}", this.symbol), new String[][]{
|
|
||||||
{"wa", "wsignin1.0"},
|
{"wa", "wsignin1.0"},
|
||||||
{"wresult", certificate}
|
{"wresult", certificate}
|
||||||
});
|
});
|
||||||
@ -103,4 +94,4 @@ public class Login {
|
|||||||
|
|
||||||
return els.get(1).text();
|
return els.get(1).text();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -62,29 +62,29 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
greendao {
|
greendao {
|
||||||
schemaVersion 19
|
schemaVersion 20
|
||||||
generateTests = true
|
generateTests = true
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':api')
|
implementation project(':api')
|
||||||
implementation 'com.android.support:appcompat-v7:27.0.2'
|
implementation 'com.android.support:appcompat-v7:27.1.0'
|
||||||
implementation 'com.android.support:design:27.0.2'
|
implementation 'com.android.support:design:27.1.0'
|
||||||
implementation 'com.android.support:support-v4:27.0.2'
|
implementation 'com.android.support:support-v4:27.1.0'
|
||||||
implementation 'com.android.support:recyclerview-v7:27.0.2'
|
implementation 'com.android.support:recyclerview-v7:27.1.0'
|
||||||
implementation 'com.android.support:cardview-v7:27.0.2'
|
implementation 'com.android.support:cardview-v7:27.1.0'
|
||||||
implementation 'com.android.support:customtabs:27.0.2'
|
implementation 'com.android.support:customtabs:27.1.0'
|
||||||
implementation 'com.firebase:firebase-jobdispatcher:0.8.5'
|
implementation 'com.firebase:firebase-jobdispatcher:0.8.5'
|
||||||
implementation 'com.thoughtbot:expandablerecyclerview:1.3'
|
|
||||||
implementation 'org.apache.commons:commons-lang3:3.7'
|
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.apache.commons:commons-collections4:4.1'
|
||||||
implementation 'org.greenrobot:greendao:3.2.2'
|
implementation 'org.greenrobot:greendao:3.2.2'
|
||||||
implementation 'com.jakewharton:butterknife:8.8.1'
|
implementation 'com.jakewharton:butterknife:8.8.1'
|
||||||
implementation 'joda-time:joda-time:2.9.9'
|
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:2.14.1'
|
||||||
implementation 'com.google.dagger:dagger-android-support: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') {
|
implementation('com.crashlytics.sdk.android:crashlytics:2.8.0@aar') {
|
||||||
transitive = true
|
transitive = true
|
||||||
@ -94,6 +94,7 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
annotationProcessor 'com.google.dagger:dagger-android-processor:2.14.1'
|
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'
|
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
|
||||||
|
|
||||||
debugImplementation 'com.amitshekhar.android:debug-db:1.0.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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
package io.github.wulkanowy.utils.security;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
|
||||||
import android.support.test.InstrumentationRegistry;
|
import android.support.test.InstrumentationRegistry;
|
||||||
import android.support.test.filters.SdkSuppress;
|
import android.support.test.filters.SdkSuppress;
|
||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@SdkSuppress(minSdkVersion = 18)
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class ScramblerTest {
|
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
|
@Test
|
||||||
public void decryptEncryptStringTest() throws CryptoException {
|
@SdkSuppress(minSdkVersion = 18)
|
||||||
scramblerLoad.generateNewKey("TEST", targetContext);
|
public void encryptDecryptTest() throws Exception {
|
||||||
Assert.assertEquals("pass",
|
Context targetContext = InstrumentationRegistry.getTargetContext();
|
||||||
scramblerLoad.decryptString("TEST", scramblerLoad.encryptString("TEST", "pass")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = CryptoException.class)
|
Assert.assertEquals("PASS", Scrambler.decrypt("TEST",
|
||||||
public void decryptEmptyTest() throws CryptoException {
|
Scrambler.encrypt("TEST", "PASS", targetContext)));
|
||||||
scramblerLoad.decryptString("", "");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
package="io.github.wulkanowy"
|
package="io.github.wulkanowy"
|
||||||
android:installLocation="internalOnly">
|
android:installLocation="internalOnly">
|
||||||
|
|
||||||
@ -11,8 +10,6 @@
|
|||||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
<uses-sdk tools:overrideLibrary="com.thoughtbot.expandablerecyclerview" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".WulkanowyApp"
|
android:name=".WulkanowyApp"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
@ -25,7 +22,7 @@
|
|||||||
android:name=".ui.splash.SplashActivity"
|
android:name=".ui.splash.SplashActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@style/WulkanowyTheme.noActionBar">
|
android:theme="@style/WulkanowyTheme.SplashTheme">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
@ -38,12 +35,12 @@
|
|||||||
android:label="@string/title_activity_login"
|
android:label="@string/title_activity_login"
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.main.DashboardActivity"
|
android:name=".ui.main.MainActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:label="@string/activity_dashboard_text" />
|
android:label="@string/activity_dashboard_text" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".services.jobs.FullSyncJob$SyncService"
|
android:name=".services.SyncJob"
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
|
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
|
||||||
|
@ -1,50 +1,48 @@
|
|||||||
package io.github.wulkanowy;
|
package io.github.wulkanowy;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import com.crashlytics.android.Crashlytics;
|
import com.crashlytics.android.Crashlytics;
|
||||||
import com.crashlytics.android.core.CrashlyticsCore;
|
import com.crashlytics.android.core.CrashlyticsCore;
|
||||||
|
|
||||||
import org.greenrobot.greendao.query.QueryBuilder;
|
import org.greenrobot.greendao.query.QueryBuilder;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||||
import eu.davidea.flexibleadapter.utils.Log;
|
import eu.davidea.flexibleadapter.utils.Log;
|
||||||
import io.fabric.sdk.android.Fabric;
|
import io.fabric.sdk.android.Fabric;
|
||||||
import io.github.wulkanowy.db.dao.entities.DaoMaster;
|
import io.github.wulkanowy.data.RepositoryContract;
|
||||||
import io.github.wulkanowy.db.dao.entities.DaoSession;
|
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 class WulkanowyApp extends Application {
|
||||||
|
|
||||||
public static final String DEBUG_TAG = "WulaknowyActivity";
|
protected ApplicationComponent applicationComponent;
|
||||||
|
|
||||||
private DaoSession daoSession;
|
@Inject
|
||||||
|
RepositoryContract repository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
applicationComponent = DaggerApplicationComponent
|
||||||
|
.builder()
|
||||||
|
.applicationModule(new ApplicationModule(this))
|
||||||
|
.build();
|
||||||
|
applicationComponent.inject(this);
|
||||||
|
|
||||||
|
initializeFabric();
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
enableDebugLog();
|
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() {
|
private void enableDebugLog() {
|
||||||
@ -62,6 +60,6 @@ public class WulkanowyApp extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DaoSession getDaoSession() {
|
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.DaoException;
|
||||||
import org.greenrobot.greendao.annotation.Entity;
|
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.DaoException;
|
||||||
import org.greenrobot.greendao.annotation.Entity;
|
import org.greenrobot.greendao.annotation.Entity;
|
@ -1,7 +1,4 @@
|
|||||||
package io.github.wulkanowy.db.dao.entities;
|
package io.github.wulkanowy.data.db.dao.entities;
|
||||||
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
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.Id;
|
||||||
import org.greenrobot.greendao.annotation.Property;
|
import org.greenrobot.greendao.annotation.Property;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import io.github.wulkanowy.R;
|
import io.github.wulkanowy.R;
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
nameInDb = "Grades",
|
nameInDb = "Grades",
|
||||||
active = true
|
active = true
|
||||||
)
|
)
|
||||||
public class Grade implements Parcelable {
|
public class Grade implements Serializable {
|
||||||
|
|
||||||
@Id(autoincrement = true)
|
@Id(autoincrement = true)
|
||||||
protected Long id;
|
protected Long id;
|
||||||
@ -61,9 +60,7 @@ public class Grade implements Parcelable {
|
|||||||
@Property(nameInDb = "READ")
|
@Property(nameInDb = "READ")
|
||||||
private boolean read = true;
|
private boolean read = true;
|
||||||
|
|
||||||
protected Grade(Parcel source) {
|
private static final long serialVersionUID = 42L;
|
||||||
value = source.readString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Generated(hash = 568899968)
|
@Generated(hash = 568899968)
|
||||||
public Grade(Long id, Long subjectId, Long userId, String subject, String value,
|
public Grade(Long id, Long subjectId, Long userId, String subject, String value,
|
||||||
@ -90,36 +87,6 @@ public class Grade implements Parcelable {
|
|||||||
public Grade() {
|
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
|
* 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.DaoException;
|
||||||
import org.greenrobot.greendao.annotation.Entity;
|
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.Index;
|
||||||
import org.greenrobot.greendao.annotation.Property;
|
import org.greenrobot.greendao.annotation.Property;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
nameInDb = "Lessons",
|
nameInDb = "Lessons",
|
||||||
active = true,
|
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)
|
@Id(autoincrement = true)
|
||||||
private Long id;
|
private Long id;
|
||||||
@ -65,6 +67,8 @@ public class Lesson {
|
|||||||
@Property(nameInDb = "IS_NEW_MOVED_IN_CANCELED")
|
@Property(nameInDb = "IS_NEW_MOVED_IN_CANCELED")
|
||||||
private boolean isNewMovedInOrChanged = false;
|
private boolean isNewMovedInOrChanged = false;
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 42L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to resolve relations
|
* 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.DaoException;
|
||||||
import org.greenrobot.greendao.annotation.Entity;
|
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.DaoException;
|
||||||
import org.greenrobot.greendao.annotation.Entity;
|
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.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
|
||||||
|
import com.firebase.jobdispatcher.GooglePlayDriver;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
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
|
@Module
|
||||||
public class ApplicationModule {
|
public class ApplicationModule {
|
||||||
|
|
||||||
protected final Application application;
|
private final Application application;
|
||||||
|
|
||||||
public ApplicationModule(Application application) {
|
public ApplicationModule(Application application) {
|
||||||
this.application = application;
|
this.application = application;
|
||||||
@ -20,8 +48,82 @@ public class ApplicationModule {
|
|||||||
return application;
|
return application;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApplicationContext
|
||||||
@Provides
|
@Provides
|
||||||
Context provideAppContext() {
|
Context provideAppContext() {
|
||||||
return application;
|
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;
|
package io.github.wulkanowy.ui.login;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.animation.Animator;
|
||||||
import android.net.Uri;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.customtabs.CustomTabsIntent;
|
import android.support.design.widget.TextInputLayout;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.AutoCompleteTextView;
|
import android.widget.AutoCompleteTextView;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
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.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;
|
import io.github.wulkanowy.utils.KeyboardUtils;
|
||||||
|
|
||||||
/**
|
public class LoginActivity extends BaseActivity implements LoginContract.View {
|
||||||
* A login screen that offers login via email/password.
|
|
||||||
*/
|
|
||||||
public class LoginActivity extends Activity {
|
|
||||||
|
|
||||||
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
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_login);
|
setContentView(R.layout.activity_login);
|
||||||
|
|
||||||
updater = new Updater(this).checkForUpdates();
|
setButterKnife(ButterKnife.bind(this));
|
||||||
|
getActivityComponent().inject(this);
|
||||||
|
|
||||||
// Set up the login form.
|
presenter.onStart(this);
|
||||||
emailView = findViewById(R.id.email);
|
|
||||||
passwordView = findViewById(R.id.password);
|
|
||||||
symbolView = findViewById(R.id.symbol);
|
|
||||||
|
|
||||||
passwordView.setOnEditorActionListener(getTextViewSignInListener());
|
setUpOnCreate();
|
||||||
symbolView.setOnEditorActionListener(getTextViewSignInListener());
|
|
||||||
|
|
||||||
populateAutoComplete();
|
}
|
||||||
|
|
||||||
Button signInButton = findViewById(R.id.action_sign_in);
|
protected void setUpOnCreate() {
|
||||||
signInButton.setOnClickListener(new OnClickListener() {
|
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
|
@Override
|
||||||
public void onClick(View view) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
attemptLogin();
|
loginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
findViewById(R.id.action_create_account).setOnClickListener(getButtonLinkListener(
|
loadingBarView.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
"https://cufs.vulcan.net.pl/Default/AccountManage/CreateAccount"
|
loadingBarView.animate().setDuration(animTime).alpha(
|
||||||
));
|
show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
|
||||||
|
|
||||||
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() {
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
|
loadingBarView.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||||
attemptLogin();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
}
|
|
||||||
|
|
||||||
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
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.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;
|
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.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;
|
public class LoginTask extends AsyncTask<Void, Integer, Boolean> {
|
||||||
import com.crashlytics.android.answers.Answers;
|
|
||||||
import com.crashlytics.android.answers.CustomEvent;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
private String email;
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.net.SocketTimeoutException;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
import io.github.wulkanowy.R;
|
private String password;
|
||||||
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 symbol;
|
||||||
* Represents an asynchronous login/registration task used to authenticate
|
|
||||||
* the user.
|
|
||||||
*/
|
|
||||||
public class LoginTask extends AsyncTask<Void, String, Integer> {
|
|
||||||
|
|
||||||
private final String email;
|
private LoginContract.Presenter presenter;
|
||||||
|
|
||||||
private final String password;
|
private Exception exception;
|
||||||
|
|
||||||
private final String symbol;
|
LoginTask(LoginContract.Presenter presenter, String email, String password, String symbol) {
|
||||||
|
this.presenter = presenter;
|
||||||
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);
|
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.symbol = symbol;
|
this.symbol = symbol;
|
||||||
@ -66,159 +23,36 @@ public class LoginTask extends AsyncTask<Void, String, Integer> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPreExecute() {
|
protected void onPreExecute() {
|
||||||
showText = new WeakReference<>((TextView) activity.get().findViewById(R.id.login_progress_text));
|
presenter.onStartAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Integer doInBackground(Void... params) {
|
protected Boolean doInBackground(Void... params) {
|
||||||
if (NetworkUtils.isOnline(activity.get())) {
|
try {
|
||||||
DaoSession daoSession = ((WulkanowyApp) activity.get().getApplication()).getDaoSession();
|
publishProgress(1);
|
||||||
VulcanSync vulcanSync = new VulcanSync(new LoginSession());
|
presenter.getRepository().loginUser(email, password, symbol);
|
||||||
|
|
||||||
try {
|
publishProgress(2);
|
||||||
publishProgress("1", activity.get().getResources().getString(R.string.step_login));
|
presenter.getRepository().syncAll();
|
||||||
vulcanSync.firstLoginSignInStep(activity.get(), daoSession, email, password, symbol);
|
} catch (Exception e) {
|
||||||
|
exception = e;
|
||||||
publishProgress("2", activity.get().getResources().getString(R.string.step_synchronization));
|
return false;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onProgressUpdate(String... progress) {
|
protected void onProgressUpdate(Integer... progress) {
|
||||||
showText.get().setText(String.format("%1$s/2 - %2$s...", progress[0], progress[1]));
|
presenter.onLoginProgress(progress[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(final Integer messageID) {
|
protected void onPostExecute(Boolean success) {
|
||||||
showProgress(false);
|
presenter.onEndAsync(success, exception);
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCancelled() {
|
protected void onCancelled() {
|
||||||
showProgress(false);
|
presenter.onCanceledAsync();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
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
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
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;
|
package io.github.wulkanowy.ui.main.grades;
|
||||||
|
|
||||||
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.app.DialogFragment;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.OnClick;
|
||||||
import io.github.wulkanowy.R;
|
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 {
|
public class GradesDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
|
private static final String ARGUMENT_KEY = "Item";
|
||||||
|
|
||||||
private Grade grade;
|
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() {
|
public GradesDialogFragment() {
|
||||||
setRetainInstance(true);
|
//empty constructor for fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final GradesDialogFragment newInstance(Grade grade) {
|
public static GradesDialogFragment newInstance(Grade item) {
|
||||||
return new GradesDialogFragment().setGrade(grade);
|
GradesDialogFragment dialogFragment = new GradesDialogFragment();
|
||||||
|
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putSerializable(ARGUMENT_KEY, item);
|
||||||
|
|
||||||
|
dialogFragment.setArguments(bundle);
|
||||||
|
|
||||||
|
return dialogFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int colorHexToColorName(String hexColor) {
|
@Override
|
||||||
switch (hexColor) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
case "000000":
|
super.onCreate(savedInstanceState);
|
||||||
return R.string.color_black_text;
|
if (getArguments() != null) {
|
||||||
|
grade = (Grade) getArguments().getSerializable(ARGUMENT_KEY);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private GradesDialogFragment setGrade(Grade grade) {
|
|
||||||
this.grade = grade;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
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);
|
ButterKnife.bind(this, view);
|
||||||
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);
|
|
||||||
|
|
||||||
subjectText.setText(grade.getSubject());
|
subject.setText(grade.getSubject());
|
||||||
gradeText.setText(grade.getValue());
|
value.setText(grade.getValue());
|
||||||
gradeText.setBackgroundResource(grade.getValueColor());
|
value.setBackgroundResource(grade.getValueColor());
|
||||||
weightText.setText(grade.getWeight());
|
weight.setText(grade.getWeight());
|
||||||
dateText.setText(grade.getDate());
|
date.setText(grade.getDate());
|
||||||
colorText.setText(colorHexToColorName(grade.getColor()));
|
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;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@OnClick(R.id.grade_dialog_close_button)
|
||||||
public void onDestroyView() {
|
void onClickClose() {
|
||||||
Dialog dialog = getDialog();
|
dismiss();
|
||||||
if (dialog != null && getRetainInstance()) {
|
}
|
||||||
dialog.setDismissMessage(null);
|
|
||||||
|
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;
|
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.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
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.R;
|
||||||
import io.github.wulkanowy.WulkanowyApp;
|
import io.github.wulkanowy.di.component.FragmentComponent;
|
||||||
import io.github.wulkanowy.api.Vulcan;
|
import io.github.wulkanowy.ui.base.BaseFragment;
|
||||||
import io.github.wulkanowy.api.login.VulcanOfflineException;
|
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||||
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;
|
|
||||||
|
|
||||||
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() {
|
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);
|
FragmentComponent component = getFragmentComponent();
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
|
if (component != null) {
|
||||||
GradesAdapter gradesAdapter = new GradesAdapter(subjectWithGradesList, activity);
|
component.inject(this);
|
||||||
recyclerView.setAdapter(gradesAdapter);
|
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();
|
recyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(fragmentView.getContext()));
|
||||||
Account account = accountDao.load(userId);
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
for (Subject subject : account.getSubjectList()) {
|
refreshLayout.setColorSchemeResources(android.R.color.black);
|
||||||
List<Grade> gradeList = subject.getGradeList();
|
refreshLayout.setOnRefreshListener(this);
|
||||||
if (!gradeList.isEmpty()) {
|
}
|
||||||
SubjectWithGrades subjectWithGrades = new SubjectWithGrades(subject.getName(), gradeList);
|
|
||||||
subjectWithGradesList.add(subjectWithGrades);
|
@Override
|
||||||
}
|
public void setMenuVisibility(boolean menuVisible) {
|
||||||
|
super.setMenuVisibility(menuVisible);
|
||||||
|
if (presenter != null) {
|
||||||
|
presenter.onFragmentVisible(menuVisible);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public void setActivityTitle() {
|
||||||
Bundle savedInstanceState) {
|
setTitle(getString(R.string.grades_text));
|
||||||
View view = inflater.inflate(R.layout.fragment_grades, container, false);
|
}
|
||||||
view.findViewById(R.id.fragment_no_grades).setVisibility(View.GONE);
|
|
||||||
|
|
||||||
|
@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) {
|
if (getActivity() != null) {
|
||||||
DaoSession daoSession = ((WulkanowyApp) getActivity().getApplication()).getDaoSession();
|
Snackbar.make(getActivity().findViewById(R.id.main_activity_view_pager),
|
||||||
userId = getActivity().getSharedPreferences("LoginData", Context.MODE_PRIVATE)
|
message, Snackbar.LENGTH_LONG).show();
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class RefreshTask extends AsyncTask<Void, Void, Integer> {
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
private DaoSession daoSession;
|
presenter.onDestroy();
|
||||||
|
super.onDestroyView();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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