Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
dab1bd4ac6 | |||
11578aa735 | |||
b63e28f9a9 | |||
072c504d2b | |||
7b7be1eef1 | |||
81d177c270 | |||
8d014ab7e9 | |||
a06d114127 | |||
0e16519baf | |||
dde5775a41 | |||
e2003e2538 | |||
228f680e5d | |||
306092ce45 |
@ -1,4 +1,5 @@
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'org.sonarqube'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'com.jfrog.bintray'
|
||||
@ -31,6 +32,9 @@ dependencies {
|
||||
implementation "org.jsoup:jsoup:$jsoup"
|
||||
implementation "org.apache.commons:commons-lang3:$apacheLang"
|
||||
implementation "com.google.code.gson:gson:$gson"
|
||||
implementation "org.slf4j:slf4j-api:$slf4jApi"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
|
||||
testImplementation "junit:junit:$junit"
|
||||
testImplementation "org.mockito:mockito-core:$mockito"
|
||||
@ -115,3 +119,29 @@ artifacts {
|
||||
archives sourcesJar
|
||||
archives javadocJar
|
||||
}
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.2.41'
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package io.github.wulkanowy.api;
|
||||
import org.jsoup.Connection;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
@ -27,6 +29,8 @@ public class Client {
|
||||
|
||||
private Cookies cookies = new Cookies();
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Client.class);
|
||||
|
||||
Client(String email, String password, String symbol) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
@ -58,10 +62,15 @@ public class Client {
|
||||
return;
|
||||
}
|
||||
|
||||
clearCookies();
|
||||
this.symbol = new Login(this).login(email, password, symbol);
|
||||
logger.info("Login successful on {} at {}", getHost(), new Date());
|
||||
}
|
||||
|
||||
private boolean isLoggedIn() {
|
||||
logger.debug("Last success request: {}", lastSuccessRequest);
|
||||
logger.debug("Cookies: {}", getCookies().size());
|
||||
|
||||
return getCookies().size() > 0 && lastSuccessRequest != null &&
|
||||
5 > TimeUnit.MILLISECONDS.toMinutes(new Date().getTime() - lastSuccessRequest.getTime());
|
||||
|
||||
@ -75,14 +84,14 @@ public class Client {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
public void addCookies(Map<String, String> items) {
|
||||
cookies.addItems(items);
|
||||
}
|
||||
|
||||
private Map<String, String> getCookies() {
|
||||
return cookies.getItems();
|
||||
}
|
||||
|
||||
public void clearCookies() {
|
||||
cookies = new Cookies();
|
||||
}
|
||||
|
||||
String getHost() {
|
||||
return host;
|
||||
}
|
||||
@ -111,7 +120,11 @@ public class Client {
|
||||
this.cookies.addItems(cookies);
|
||||
}
|
||||
|
||||
Connection.Response response = Jsoup.connect(getFilledUrl(url))
|
||||
url = getFilledUrl(url);
|
||||
|
||||
logger.debug("GET {}", url);
|
||||
|
||||
Connection.Response response = Jsoup.connect(url)
|
||||
.followRedirects(true)
|
||||
.cookies(getCookies())
|
||||
.execute();
|
||||
@ -128,7 +141,11 @@ public class Client {
|
||||
}
|
||||
|
||||
public synchronized Document postPageByUrl(String url, String[][] params) throws IOException, VulcanException {
|
||||
Connection connection = Jsoup.connect(getFilledUrl(url));
|
||||
url = getFilledUrl(url);
|
||||
|
||||
logger.debug("POST {}", url);
|
||||
|
||||
Connection connection = Jsoup.connect(url);
|
||||
|
||||
for (String[] data : params) {
|
||||
connection.data(data[0], data[1]);
|
||||
@ -150,7 +167,11 @@ public class Client {
|
||||
public String getJsonStringByUrl(String url) throws IOException, VulcanException {
|
||||
login();
|
||||
|
||||
Connection.Response response = Jsoup.connect(getFilledUrl(url))
|
||||
url = getFilledUrl(url);
|
||||
|
||||
logger.debug("GET {}", url);
|
||||
|
||||
Connection.Response response = Jsoup.connect(url)
|
||||
.followRedirects(true)
|
||||
.ignoreContentType(true)
|
||||
.cookies(getCookies())
|
||||
@ -164,7 +185,11 @@ public class Client {
|
||||
public String postJsonStringByUrl(String url, String[][] params) throws IOException, VulcanException {
|
||||
login();
|
||||
|
||||
Connection connection = Jsoup.connect(getFilledUrl(url));
|
||||
url = getFilledUrl(url);
|
||||
|
||||
logger.debug("POST {}", url);
|
||||
|
||||
Connection connection = Jsoup.connect(url);
|
||||
|
||||
for (String[] data : params) {
|
||||
connection.data(data[0], data[1]);
|
||||
@ -196,7 +221,7 @@ public class Client {
|
||||
}
|
||||
|
||||
if ("Błąd strony".equals(title)) {
|
||||
throw new NotLoggedInErrorException(title + " " + doc.selectFirst("p, body") + ", status: " + code);
|
||||
throw new NotLoggedInErrorException(title + " " + doc.body() + ", status: " + code);
|
||||
}
|
||||
|
||||
return doc;
|
||||
|
53
api/src/main/java/io/github/wulkanowy/api/DateTimeUtils.kt
Normal file
53
api/src/main/java/io/github/wulkanowy/api/DateTimeUtils.kt
Normal file
@ -0,0 +1,53 @@
|
||||
package io.github.wulkanowy.api
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
const val LOG_DATE_PATTERN = "dd.MM.yyyy"
|
||||
const val API_DATE_PATTERN = "yyyy-MM-dd"
|
||||
|
||||
const val TICKS_AT_EPOCH = 621355968000000000L
|
||||
const val TICKS_PER_MILLISECOND = 10000
|
||||
|
||||
fun getFormattedDate(date: String): String {
|
||||
return getFormattedDate(date, API_DATE_PATTERN)
|
||||
}
|
||||
|
||||
fun getFormattedDate(date: String, format: String): String {
|
||||
return getFormattedDate(date, LOG_DATE_PATTERN, format)
|
||||
}
|
||||
|
||||
fun getFormattedDate(date: String, fromFormat: String, toFormat: String): String {
|
||||
val sdf = SimpleDateFormat(fromFormat, Locale.ROOT)
|
||||
val d = sdf.parse(date)
|
||||
sdf.applyPattern(toFormat)
|
||||
|
||||
return sdf.format(d)
|
||||
}
|
||||
|
||||
fun getDateAsTick(dateString: String?): String {
|
||||
if (dateString.isNullOrEmpty()) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return getDateAsTick(dateString as String, API_DATE_PATTERN).toString()
|
||||
}
|
||||
|
||||
fun getDateAsTick(dateString: String, dateFormat: String): Long {
|
||||
val format = SimpleDateFormat(dateFormat, Locale.ROOT)
|
||||
format.timeZone = TimeZone.getTimeZone("UTC")
|
||||
val dateObject = format.parse(dateString)
|
||||
|
||||
return getDateAsTick(dateObject)
|
||||
}
|
||||
|
||||
fun getDateAsTick(date: Date): Long {
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.time = date
|
||||
|
||||
return calendar.timeInMillis * TICKS_PER_MILLISECOND + TICKS_AT_EPOCH
|
||||
}
|
||||
|
||||
fun getDate(netTicks: Long): Date {
|
||||
return Date((netTicks - TICKS_AT_EPOCH) / TICKS_PER_MILLISECOND)
|
||||
}
|
@ -6,6 +6,11 @@ import org.jsoup.nodes.Element;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.api.generic.Diary;
|
||||
import io.github.wulkanowy.api.generic.ParamItem;
|
||||
import io.github.wulkanowy.api.generic.Semester;
|
||||
import io.github.wulkanowy.api.generic.Student;
|
||||
|
||||
public interface SnP {
|
||||
|
||||
String getSchoolID();
|
||||
|
@ -3,6 +3,8 @@ package io.github.wulkanowy.api;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
@ -11,6 +13,11 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.github.wulkanowy.api.generic.Diary;
|
||||
import io.github.wulkanowy.api.generic.ParamItem;
|
||||
import io.github.wulkanowy.api.generic.Semester;
|
||||
import io.github.wulkanowy.api.generic.Student;
|
||||
|
||||
public class StudentAndParent implements SnP {
|
||||
|
||||
private static final String START_PAGE_URL = "{schema}://uonetplus.{host}/{symbol}/Start.mvc/Index";
|
||||
@ -27,6 +34,8 @@ public class StudentAndParent implements SnP {
|
||||
|
||||
private String diaryID;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StudentAndParent.class);
|
||||
|
||||
StudentAndParent(Client client, String schoolID, String studentID, String diaryID) {
|
||||
this.client = client;
|
||||
this.schoolID = schoolID;
|
||||
@ -38,6 +47,11 @@ public class StudentAndParent implements SnP {
|
||||
if (null == getStudentID() || "".equals(getStudentID())) {
|
||||
Document doc = client.getPageByUrl(getSnpHomePageUrl());
|
||||
|
||||
if (doc.select("#idSection").isEmpty()) {
|
||||
logger.error("Expected SnP page, got page with title: {} {}", doc.title(), doc.selectFirst("body"));
|
||||
throw new VulcanException("Nieznany błąd podczas pobierania danych. Strona: " + doc.title());
|
||||
}
|
||||
|
||||
Student student = getCurrent(getStudents(doc));
|
||||
studentID = student.getId();
|
||||
|
||||
@ -67,24 +81,27 @@ public class StudentAndParent implements SnP {
|
||||
|
||||
// get url to uonetplus-opiekun.fakelog.cf
|
||||
Document startPage = client.getPageByUrl(START_PAGE_URL);
|
||||
Element studentTileLink = startPage.select(".panel.linkownia.pracownik.klient > a").first();
|
||||
Elements studentTileLink = startPage.select(".panel.linkownia.pracownik.klient > a");
|
||||
|
||||
if (null == studentTileLink) {
|
||||
logger.debug("studentTileLink: {}", studentTileLink.size());
|
||||
|
||||
if (studentTileLink.isEmpty()) {
|
||||
throw new VulcanException("Na pewno używasz konta z dostępem do Witryny ucznia i rodzica?");
|
||||
}
|
||||
|
||||
String snpPageUrl = studentTileLink.attr("href");
|
||||
String snpPageUrl = studentTileLink.last().attr("href");
|
||||
|
||||
this.schoolID = getExtractedIdFromUrl(snpPageUrl);
|
||||
|
||||
return snpPageUrl;
|
||||
}
|
||||
|
||||
String getExtractedIdFromUrl(String snpPageUrl) throws NotLoggedInErrorException {
|
||||
String getExtractedIdFromUrl(String snpPageUrl) throws VulcanException {
|
||||
String[] path = snpPageUrl.split(client.getHost())[1].split("/");
|
||||
|
||||
if (5 != path.length) {
|
||||
throw new NotLoggedInErrorException("You are probably not logged in " + snpPageUrl);
|
||||
logger.error("Expected snp url, got {}", snpPageUrl);
|
||||
throw new VulcanException("Na pewno używasz konta z dostępem do Witryny ucznia i rodzica?");
|
||||
}
|
||||
|
||||
return path[2];
|
||||
@ -102,12 +119,12 @@ public class StudentAndParent implements SnP {
|
||||
Map<String, String> cookies = new HashMap<>();
|
||||
cookies.put("idBiezacyDziennik", diaryID);
|
||||
cookies.put("idBiezacyUczen", studentID);
|
||||
client.addCookies(cookies);
|
||||
|
||||
Document doc = client.getPageByUrl(getBaseUrl() + url, true, cookies);
|
||||
|
||||
if (!doc.title().startsWith("Witryna ucznia i rodzica")) {
|
||||
throw new VulcanException("Expected SnP page, got page with title: " + doc.title());
|
||||
logger.error("Expected SnP page, got page with title: {} {}", doc.title(), doc.selectFirst("body"));
|
||||
throw new VulcanException("Nieznany błąd podczas pobierania danych. Strona: " + doc.title());
|
||||
}
|
||||
|
||||
if (doc.title().endsWith("Strona główna")) {
|
||||
|
@ -1,5 +1,8 @@
|
||||
package io.github.wulkanowy.api;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.github.wulkanowy.api.attendance.AttendanceStatistics;
|
||||
@ -8,6 +11,8 @@ import io.github.wulkanowy.api.exams.ExamsWeek;
|
||||
import io.github.wulkanowy.api.grades.GradesList;
|
||||
import io.github.wulkanowy.api.grades.SubjectsList;
|
||||
import io.github.wulkanowy.api.messages.Messages;
|
||||
import io.github.wulkanowy.api.mobile.RegisterDevice;
|
||||
import io.github.wulkanowy.api.mobile.RegisteredDevices;
|
||||
import io.github.wulkanowy.api.notes.AchievementsList;
|
||||
import io.github.wulkanowy.api.notes.NotesList;
|
||||
import io.github.wulkanowy.api.school.SchoolInfo;
|
||||
@ -28,17 +33,21 @@ public class Vulcan {
|
||||
|
||||
private String diaryId;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Vulcan.class);
|
||||
|
||||
public void setCredentials(String email, String password, String symbol, String schoolId, String studentId, String diaryId) {
|
||||
this.schoolId = schoolId;
|
||||
this.studentId = studentId;
|
||||
this.diaryId = diaryId;
|
||||
|
||||
client = new Client(email, password, symbol);
|
||||
|
||||
logger.debug("Client created with symbol " + symbol);
|
||||
}
|
||||
|
||||
public Client getClient() throws NotLoggedInErrorException {
|
||||
if (null == client) {
|
||||
throw new NotLoggedInErrorException("Use setCredentials() method first");
|
||||
throw new NotLoggedInErrorException("Vulcan must be initialized by calling setCredentials() prior to fetch data");
|
||||
}
|
||||
|
||||
return client;
|
||||
@ -108,6 +117,14 @@ public class Vulcan {
|
||||
return new FamilyInformation(getStudentAndParent());
|
||||
}
|
||||
|
||||
public RegisteredDevices getRegisteredDevices() throws VulcanException, IOException {
|
||||
return new RegisteredDevices(getStudentAndParent());
|
||||
}
|
||||
|
||||
public RegisterDevice getRegisterDevice() throws VulcanException, IOException {
|
||||
return new RegisterDevice(getStudentAndParent());
|
||||
}
|
||||
|
||||
public Messages getMessages() throws VulcanException {
|
||||
return new Messages(getClient());
|
||||
}
|
||||
|
@ -4,12 +4,8 @@ import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import io.github.wulkanowy.api.SnP;
|
||||
import io.github.wulkanowy.api.VulcanException;
|
||||
@ -17,6 +13,9 @@ import io.github.wulkanowy.api.generic.Day;
|
||||
import io.github.wulkanowy.api.generic.Lesson;
|
||||
import io.github.wulkanowy.api.generic.Week;
|
||||
|
||||
import static io.github.wulkanowy.api.DateTimeUtilsKt.getDateAsTick;
|
||||
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
|
||||
|
||||
public class AttendanceTable {
|
||||
|
||||
private final static String ATTENDANCE_PAGE_URL = "Frekwencja.mvc?data=";
|
||||
@ -27,13 +26,12 @@ public class AttendanceTable {
|
||||
this.snp = snp;
|
||||
}
|
||||
|
||||
public Week<Day> getWeekTable() throws IOException, ParseException, VulcanException {
|
||||
public Week<Day> getWeekTable() throws IOException, VulcanException {
|
||||
return getWeekTable("");
|
||||
}
|
||||
|
||||
public Week<Day> getWeekTable(String tick) throws IOException, ParseException, VulcanException {
|
||||
Element table = snp.getSnPPageDocument(ATTENDANCE_PAGE_URL + tick)
|
||||
|
||||
public Week<Day> getWeekTable(String date) throws IOException, VulcanException {
|
||||
Element table = snp.getSnPPageDocument(ATTENDANCE_PAGE_URL + getDateAsTick(date))
|
||||
.select(".mainContainer .presentData").first();
|
||||
|
||||
Elements headerCells = table.select("thead th");
|
||||
@ -42,14 +40,10 @@ public class AttendanceTable {
|
||||
for (int i = 1; i < headerCells.size(); i++) {
|
||||
String[] dayHeaderCell = headerCells.get(i).html().split("<br>");
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
|
||||
Date d = sdf.parse(dayHeaderCell[1].trim());
|
||||
sdf.applyPattern("yyyy-MM-dd");
|
||||
|
||||
Day day = new Day();
|
||||
day.setDayName(dayHeaderCell[0]);
|
||||
day.setDate(sdf.format(d));
|
||||
days.add(day);
|
||||
days.add(new Day()
|
||||
.setDayName(dayHeaderCell[0])
|
||||
.setDate(getFormattedDate(dayHeaderCell[1].trim()))
|
||||
);
|
||||
}
|
||||
|
||||
Elements hoursInDays = table.select("tbody tr");
|
||||
|
@ -6,17 +6,16 @@ import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import io.github.wulkanowy.api.SnP;
|
||||
import io.github.wulkanowy.api.VulcanException;
|
||||
import io.github.wulkanowy.api.generic.Week;
|
||||
|
||||
import static io.github.wulkanowy.api.DateTimeUtilsKt.getDateAsTick;
|
||||
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
|
||||
|
||||
public class ExamsWeek {
|
||||
|
||||
private static final String EXAMS_PAGE_URL = "Sprawdziany.mvc/Terminarz?rodzajWidoku=2&data=";
|
||||
@ -27,12 +26,12 @@ public class ExamsWeek {
|
||||
this.snp = snp;
|
||||
}
|
||||
|
||||
public Week<ExamDay> getCurrent() throws IOException, VulcanException, ParseException {
|
||||
public Week<ExamDay> getCurrent() throws IOException, VulcanException {
|
||||
return getWeek("", true);
|
||||
}
|
||||
|
||||
public Week<ExamDay> getWeek(String tick, final boolean onlyNotEmpty) throws IOException, VulcanException, ParseException {
|
||||
Document examsPage = snp.getSnPPageDocument(EXAMS_PAGE_URL + tick);
|
||||
public Week<ExamDay> getWeek(String date, final boolean onlyNotEmpty) throws IOException, VulcanException {
|
||||
Document examsPage = snp.getSnPPageDocument(EXAMS_PAGE_URL + getDateAsTick(date));
|
||||
Elements examsDays = examsPage.select(".mainContainer > div:not(.navigation)");
|
||||
|
||||
List<ExamDay> days = new ArrayList<>();
|
||||
@ -71,11 +70,4 @@ public class ExamsWeek {
|
||||
.first().text().split(" ")[1]))
|
||||
.setDays(days);
|
||||
}
|
||||
|
||||
private String getFormattedDate(String date) throws ParseException {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
|
||||
Date d = sdf.parse(date);
|
||||
sdf.applyPattern("yyyy-MM-dd");
|
||||
return sdf.format(d);
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,8 @@ public class Day {
|
||||
return dayName;
|
||||
}
|
||||
|
||||
public void setDayName(String dayName) {
|
||||
public Day setDayName(String dayName) {
|
||||
this.dayName = dayName;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.api;
|
||||
package io.github.wulkanowy.api.generic;
|
||||
|
||||
public class Diary implements ParamItem {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package io.github.wulkanowy.api;
|
||||
package io.github.wulkanowy.api.generic;
|
||||
|
||||
interface ParamItem {
|
||||
public interface ParamItem {
|
||||
|
||||
ParamItem setId(String id);
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.api;
|
||||
package io.github.wulkanowy.api.generic;
|
||||
|
||||
public class Semester implements ParamItem {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.wulkanowy.api;
|
||||
package io.github.wulkanowy.api.generic;
|
||||
|
||||
public class Student implements ParamItem {
|
||||
|
@ -5,42 +5,32 @@ import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import io.github.wulkanowy.api.SnP;
|
||||
import io.github.wulkanowy.api.VulcanException;
|
||||
|
||||
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
|
||||
|
||||
public class GradesList {
|
||||
|
||||
private static final String GRADES_PAGE_URL = "Oceny/Wszystkie?details=2&okres=";
|
||||
|
||||
private SnP snp;
|
||||
|
||||
private List<Grade> grades = new ArrayList<>();
|
||||
|
||||
public GradesList(SnP snp) {
|
||||
this.snp = snp;
|
||||
}
|
||||
|
||||
private String getGradesPageUrl() {
|
||||
return GRADES_PAGE_URL;
|
||||
}
|
||||
|
||||
public List<Grade> getAll() throws IOException, ParseException, VulcanException {
|
||||
return getAll("");
|
||||
}
|
||||
|
||||
public List<Grade> getAll(String semester) throws IOException, ParseException, VulcanException {
|
||||
Document gradesPage = snp.getSnPPageDocument(getGradesPageUrl() + semester);
|
||||
public List<Grade> getAll(String semester) throws IOException, VulcanException {
|
||||
Document gradesPage = snp.getSnPPageDocument(GRADES_PAGE_URL + semester);
|
||||
Elements gradesRows = gradesPage.select(".ocenySzczegoly-table > tbody > tr");
|
||||
|
||||
List<Grade> grades = new ArrayList<>();
|
||||
|
||||
for (Element row : gradesRows) {
|
||||
if ("Brak ocen".equals(row.select("td:nth-child(2)").text())) {
|
||||
continue;
|
||||
@ -52,13 +42,13 @@ public class GradesList {
|
||||
return grades;
|
||||
}
|
||||
|
||||
private Grade getGrade(Element row) throws ParseException {
|
||||
private Grade getGrade(Element row) {
|
||||
String descriptions = row.select("td:nth-child(3)").text();
|
||||
|
||||
String symbol = descriptions.split(", ")[0];
|
||||
String description = descriptions.replaceFirst(Pattern.quote(symbol), "").replaceFirst(", ", "");
|
||||
String color = getColor(row.select("td:nth-child(2) span.ocenaCzastkowa").attr("style"));
|
||||
String date = formatDate(row.select("td:nth-child(5)").text());
|
||||
String date = getFormattedDate(row.select("td:nth-child(5)").text());
|
||||
|
||||
return new Grade()
|
||||
.setSubject(row.select("td:nth-child(1)").text())
|
||||
@ -82,12 +72,4 @@ public class GradesList {
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
private String formatDate(String date) throws ParseException {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
|
||||
Date d = sdf.parse(date);
|
||||
sdf.applyPattern("yyyy-MM-dd");
|
||||
|
||||
return sdf.format(d);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.parser.Parser;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -21,6 +23,8 @@ public class Login {
|
||||
|
||||
private Client client;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Login.class);
|
||||
|
||||
public Login(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
@ -29,7 +33,8 @@ public class Login {
|
||||
Document certDoc = sendCredentials(email, password);
|
||||
|
||||
if ("Błąd".equals(certDoc.title())) {
|
||||
throw new NotLoggedInErrorException(certDoc.selectFirst("body").text());
|
||||
client.clearCookies();
|
||||
throw new NotLoggedInErrorException(certDoc.body().text());
|
||||
}
|
||||
|
||||
return sendCertificate(certDoc, symbol);
|
||||
@ -88,6 +93,7 @@ public class Login {
|
||||
String title = targetDoc.title();
|
||||
|
||||
if ("Working...".equals(title)) { // on adfs login
|
||||
logger.info("ADFS login");
|
||||
title = sendCertData(targetDoc).title();
|
||||
}
|
||||
|
||||
@ -96,6 +102,7 @@ public class Login {
|
||||
}
|
||||
|
||||
if (!"Uonet+".equals(title)) {
|
||||
logger.debug("Login failed. Body: {}", targetDoc.body());
|
||||
throw new LoginErrorException("Expected page title `UONET+`, got " + title);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,33 @@
|
||||
package io.github.wulkanowy.api.mobile
|
||||
|
||||
import io.github.wulkanowy.api.SnP
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class RegisterDevice(private val snp: SnP) {
|
||||
|
||||
companion object {
|
||||
const val REGISTER_URL = "DostepMobilny.mvc/Rejestruj"
|
||||
}
|
||||
|
||||
data class Token(
|
||||
val token: String,
|
||||
val symbol: String,
|
||||
val pin: String
|
||||
)
|
||||
|
||||
fun getToken(): Token {
|
||||
val form = snp.getSnPPageDocument(REGISTER_URL).selectFirst("#rejestracja-formularz")
|
||||
|
||||
val fields = form.select(".blockElement")
|
||||
|
||||
return Token(
|
||||
getValue(fields[1]),
|
||||
getValue(fields[2]),
|
||||
getValue(fields[3])
|
||||
)
|
||||
}
|
||||
|
||||
fun getValue(e: Element): String {
|
||||
return e.text().split(":")[1].trim()
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package io.github.wulkanowy.api.mobile
|
||||
|
||||
import io.github.wulkanowy.api.SnP
|
||||
import io.github.wulkanowy.api.getFormattedDate
|
||||
|
||||
class RegisteredDevices(private val snp: SnP) {
|
||||
|
||||
companion object {
|
||||
const val DEVICES_LIST_URL = "DostepMobilny.mvc"
|
||||
}
|
||||
|
||||
data class Device(
|
||||
val name: String,
|
||||
val system: String,
|
||||
val date: String,
|
||||
val id: Int
|
||||
)
|
||||
|
||||
fun getList(): List<Device> {
|
||||
val items = snp.getSnPPageDocument(DEVICES_LIST_URL).select("table tbody tr")
|
||||
val devices: MutableList<Device> = mutableListOf()
|
||||
|
||||
for (item in items) {
|
||||
val cells = item.select("td")
|
||||
val system = cells[0].text().split("(").last().removeSuffix(")")
|
||||
|
||||
devices.add(Device(
|
||||
cells[0].text().replace(" ($system)", ""),
|
||||
system,
|
||||
getFormattedDate(cells[1].text(), "dd.MM.yyyy 'godz:' HH:mm:ss", "yyyy-MM-dd HH:mm:ss"),
|
||||
cells[2].select("a").attr("href")
|
||||
.split("/").last().toInt()
|
||||
))
|
||||
}
|
||||
|
||||
return devices
|
||||
}
|
||||
}
|
@ -14,9 +14,7 @@ public class AchievementsList {
|
||||
|
||||
private static final String NOTES_PAGE_URL = "UwagiOsiagniecia.mvc/Wszystkie";
|
||||
|
||||
private SnP snp = null;
|
||||
|
||||
private List<String> achievements = new ArrayList<>();
|
||||
private SnP snp;
|
||||
|
||||
public AchievementsList(SnP snp) {
|
||||
this.snp = snp;
|
||||
@ -27,6 +25,8 @@ public class AchievementsList {
|
||||
.select(".mainContainer > div").get(1);
|
||||
Elements items = pageFragment.select("article");
|
||||
|
||||
List<String> achievements = new ArrayList<>();
|
||||
|
||||
for (Element item : items) {
|
||||
achievements.add(item.text());
|
||||
}
|
||||
|
@ -10,13 +10,13 @@ import java.util.List;
|
||||
import io.github.wulkanowy.api.SnP;
|
||||
import io.github.wulkanowy.api.VulcanException;
|
||||
|
||||
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
|
||||
|
||||
public class NotesList {
|
||||
|
||||
private static final String NOTES_PAGE_URL = "UwagiOsiagniecia.mvc/Wszystkie";
|
||||
|
||||
private SnP snp = null;
|
||||
|
||||
private List<Note> notes = new ArrayList<>();
|
||||
private SnP snp;
|
||||
|
||||
public NotesList(SnP snp) {
|
||||
this.snp = snp;
|
||||
@ -28,10 +28,12 @@ public class NotesList {
|
||||
Elements items = pageFragment.select("article");
|
||||
Elements dates = pageFragment.select("h2");
|
||||
|
||||
List<Note> notes = new ArrayList<>();
|
||||
|
||||
int index = 0;
|
||||
for (Element item : items) {
|
||||
notes.add(new Note()
|
||||
.setDate(dates.get(index++).text())
|
||||
.setDate(getFormattedDate(dates.get(index++).text()))
|
||||
.setTeacher(snp.getRowDataChildValue(item, 1))
|
||||
.setCategory(snp.getRowDataChildValue(item, 2))
|
||||
.setContent(snp.getRowDataChildValue(item, 3))
|
||||
|
@ -11,7 +11,7 @@ public class SchoolInfo {
|
||||
|
||||
private static final String SCHOOL_PAGE_URL = "Szkola.mvc/Nauczyciele";
|
||||
|
||||
private SnP snp = null;
|
||||
private SnP snp;
|
||||
|
||||
public SchoolInfo(SnP snp) {
|
||||
this.snp = snp;
|
||||
|
@ -15,7 +15,7 @@ public class TeachersInfo {
|
||||
|
||||
private static final String SCHOOL_PAGE_URL = "Szkola.mvc/Nauczyciele";
|
||||
|
||||
private SnP snp = null;
|
||||
private SnP snp;
|
||||
|
||||
public TeachersInfo(SnP snp) {
|
||||
this.snp = snp;
|
||||
|
@ -3,36 +3,39 @@ package io.github.wulkanowy.api.timetable;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import io.github.wulkanowy.api.SnP;
|
||||
import io.github.wulkanowy.api.VulcanException;
|
||||
import io.github.wulkanowy.api.generic.Lesson;
|
||||
import io.github.wulkanowy.api.generic.Week;
|
||||
|
||||
import static io.github.wulkanowy.api.DateTimeUtilsKt.getDateAsTick;
|
||||
import static io.github.wulkanowy.api.DateTimeUtilsKt.getFormattedDate;
|
||||
|
||||
public class Timetable {
|
||||
|
||||
private static final String TIMETABLE_PAGE_URL = "Lekcja.mvc/PlanZajec?data=";
|
||||
|
||||
private SnP snp;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Timetable.class);
|
||||
|
||||
public Timetable(SnP snp) {
|
||||
this.snp = snp;
|
||||
}
|
||||
|
||||
public Week<TimetableDay> getWeekTable() throws IOException, ParseException, VulcanException {
|
||||
public Week<TimetableDay> getWeekTable() throws IOException, VulcanException {
|
||||
return getWeekTable("");
|
||||
}
|
||||
|
||||
public Week<TimetableDay> getWeekTable(final String tick) throws IOException, ParseException, VulcanException {
|
||||
Element table = snp.getSnPPageDocument(TIMETABLE_PAGE_URL + tick)
|
||||
public Week<TimetableDay> getWeekTable(final String date) throws IOException, VulcanException {
|
||||
Element table = snp.getSnPPageDocument(TIMETABLE_PAGE_URL + getDateAsTick(date))
|
||||
.select(".mainContainer .presentData").first();
|
||||
|
||||
List<TimetableDay> days = getDays(table.select("thead th"));
|
||||
@ -44,19 +47,20 @@ public class Timetable {
|
||||
.setDays(days);
|
||||
}
|
||||
|
||||
private List<TimetableDay> getDays(Elements tableHeaderCells) throws ParseException {
|
||||
private List<TimetableDay> getDays(Elements tableHeaderCells) {
|
||||
List<TimetableDay> days = new ArrayList<>();
|
||||
int numberOfDays = tableHeaderCells.size();
|
||||
|
||||
for (int i = 2; i < 7; i++) {
|
||||
if (numberOfDays > 7) {
|
||||
logger.info("Number of days: {}", numberOfDays);
|
||||
}
|
||||
|
||||
for (int i = 2; i < numberOfDays; i++) {
|
||||
String[] dayHeaderCell = tableHeaderCells.get(i).html().split("<br>");
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
|
||||
Date d = sdf.parse(dayHeaderCell[1].trim());
|
||||
sdf.applyPattern("yyyy-MM-dd");
|
||||
|
||||
TimetableDay day = new TimetableDay();
|
||||
day.setDayName(dayHeaderCell[0]);
|
||||
day.setDate(sdf.format(d));
|
||||
day.setDate(getFormattedDate(dayHeaderCell[1].trim()));
|
||||
|
||||
if (tableHeaderCells.get(i).hasClass("free-day")) {
|
||||
day.setFreeDay(true);
|
||||
@ -132,6 +136,11 @@ public class Timetable {
|
||||
private void addLessonInfoFromElement(Lesson lesson, Element e) {
|
||||
Elements spans = e.select("span");
|
||||
|
||||
if (spans.isEmpty()) {
|
||||
logger.warn("Lesson span is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
addTypeInfo(lesson, spans);
|
||||
addNormalLessonInfo(lesson, spans);
|
||||
addChangesInfo(lesson, spans);
|
||||
@ -218,6 +227,10 @@ public class Timetable {
|
||||
}
|
||||
|
||||
private String[] getLessonAndGroupInfoFromSpan(Element span) {
|
||||
if (!span.text().contains("[")) {
|
||||
return new String[] {span.text(), ""};
|
||||
}
|
||||
|
||||
String[] subjectNameArray = span.text().split(" ");
|
||||
String groupName = subjectNameArray[subjectNameArray.length - 1];
|
||||
|
||||
|
@ -0,0 +1,53 @@
|
||||
package io.github.wulkanowy.api
|
||||
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class DateTimeUtilsTest {
|
||||
|
||||
@Test
|
||||
fun getTicksDateObjectTest() {
|
||||
val format = SimpleDateFormat("dd.MM.yyyy", Locale.ROOT)
|
||||
format.timeZone = TimeZone.getTimeZone("UTC")
|
||||
val date = format.parse("31.07.2017")
|
||||
|
||||
Assert.assertEquals(636370560000000000L, getDateAsTick(date))
|
||||
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.time = date
|
||||
calendar.add(Calendar.DAY_OF_YEAR, -14)
|
||||
val dateTwoWeekBefore = calendar.time
|
||||
|
||||
Assert.assertEquals(636358464000000000L, getDateAsTick(dateTwoWeekBefore))
|
||||
}
|
||||
|
||||
@Test(expected = ParseException::class)
|
||||
fun getTicsStringInvalidFormatTest() {
|
||||
Assert.assertEquals(636370560000000000L, getDateAsTick("31.07.2017", "dd.MMM.yyyy"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getTicsStringFormatTest() {
|
||||
Assert.assertEquals(636370560000000000L, getDateAsTick("31.07.2017", "dd.MM.yyyy"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getTicsStringTest() {
|
||||
Assert.assertEquals("636370560000000000", getDateAsTick("2017-07-31"))
|
||||
Assert.assertEquals("636334272000000000", getDateAsTick("2017-06-19"))
|
||||
Assert.assertEquals("636189120000000000", getDateAsTick("2017-01-02"))
|
||||
Assert.assertEquals("636080256000000000", getDateAsTick("2016-08-29"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getDateTest() {
|
||||
val format = SimpleDateFormat("dd.MM.yyyy", Locale.ROOT)
|
||||
format.timeZone = TimeZone.getTimeZone("UTC")
|
||||
val date = format.parse("31.07.2017")
|
||||
|
||||
Assert.assertEquals(date, getDate(636370560000000000L))
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.github.wulkanowy.api.generic.Semester;
|
||||
|
||||
public class StudentAndParentTest {
|
||||
|
||||
private Client client;
|
||||
@ -81,7 +83,7 @@ public class StudentAndParentTest {
|
||||
snp.getExtractedIdFromUrl("https://uonetplus-opiekun.vulcan.net.pl/demoupowiat/demo12345/Start/Index/"));
|
||||
}
|
||||
|
||||
@Test(expected = NotLoggedInErrorException.class)
|
||||
@Test(expected = VulcanException.class)
|
||||
public void getExtractedIDNotLoggedTest() throws Exception {
|
||||
Mockito.when(client.getHost()).thenReturn("vulcan.net.pl");
|
||||
StudentAndParent snp = new StudentAndParent(client, "symbol", null, null);
|
||||
@ -129,8 +131,8 @@ public class StudentAndParentTest {
|
||||
|
||||
@Test
|
||||
public void getDiariesAndStudentTest() throws IOException, VulcanException {
|
||||
Document snpHome = Jsoup.parse(FixtureHelper.getAsString(
|
||||
getClass().getResourceAsStream("StudentAndParent.html")));
|
||||
String input = FixtureHelper.getAsString(getClass().getResourceAsStream("WitrynaUczniaIRodzica.html"));
|
||||
Document snpHome = Jsoup.parse(input);
|
||||
|
||||
client = Mockito.mock(Client.class);
|
||||
Mockito.when(client.getPageByUrl(Mockito.anyString())).thenReturn(snpHome);
|
||||
|
@ -5,6 +5,8 @@ import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import io.github.wulkanowy.api.generic.Semester;
|
||||
|
||||
public abstract class StudentAndParentTestCase {
|
||||
|
||||
protected StudentAndParent getSnp(String fixtureFileName) throws Exception {
|
||||
|
@ -19,12 +19,12 @@ public class GradesListTest extends StudentAndParentTestCase {
|
||||
|
||||
@Test
|
||||
public void getAllTest() throws Exception {
|
||||
Assert.assertEquals(7, filled.getAll().size()); // 2 items are skipped
|
||||
Assert.assertEquals(7, filled.getAll("").size()); // 2 items are skipped
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSubjectTest() throws Exception {
|
||||
List<Grade> list = filled.getAll();
|
||||
List<Grade> list = filled.getAll("");
|
||||
|
||||
Assert.assertEquals("Zajęcia z wychowawcą", list.get(0).getSubject());
|
||||
Assert.assertEquals("Język angielski", list.get(3).getSubject());
|
||||
@ -34,7 +34,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
||||
|
||||
@Test
|
||||
public void getValueTest() throws Exception {
|
||||
List<Grade> list = filled.getAll();
|
||||
List<Grade> list = filled.getAll("");
|
||||
|
||||
Assert.assertEquals("5", list.get(0).getValue());
|
||||
Assert.assertEquals("5", list.get(3).getValue());
|
||||
@ -44,7 +44,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
||||
|
||||
@Test
|
||||
public void getColorTest() throws Exception {
|
||||
List<Grade> list = filled.getAll();
|
||||
List<Grade> list = filled.getAll("");
|
||||
|
||||
Assert.assertEquals("000000", list.get(0).getColor());
|
||||
Assert.assertEquals("1289F7", list.get(3).getColor());
|
||||
@ -54,7 +54,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
||||
|
||||
@Test
|
||||
public void getSymbolTest() throws Exception {
|
||||
List<Grade> list = filled.getAll();
|
||||
List<Grade> list = filled.getAll("");
|
||||
|
||||
Assert.assertEquals("A1", list.get(0).getSymbol());
|
||||
Assert.assertEquals("BW3", list.get(3).getSymbol());
|
||||
@ -65,7 +65,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
||||
|
||||
@Test
|
||||
public void getDescriptionTest() throws Exception {
|
||||
List<Grade> list = filled.getAll();
|
||||
List<Grade> list = filled.getAll("");
|
||||
|
||||
Assert.assertEquals("Dzień Kobiet w naszej klasie", list.get(0).getDescription());
|
||||
Assert.assertEquals("Writing", list.get(3).getDescription());
|
||||
@ -76,7 +76,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
||||
|
||||
@Test
|
||||
public void getWeightTest() throws Exception {
|
||||
List<Grade> list = filled.getAll();
|
||||
List<Grade> list = filled.getAll("");
|
||||
|
||||
Assert.assertEquals("1,00", list.get(0).getWeight());
|
||||
Assert.assertEquals("3,00", list.get(3).getWeight());
|
||||
@ -86,7 +86,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
||||
|
||||
@Test
|
||||
public void getDateTest() throws Exception {
|
||||
List<Grade> list = filled.getAll();
|
||||
List<Grade> list = filled.getAll("");
|
||||
|
||||
Assert.assertEquals("2017-03-21", list.get(0).getDate());
|
||||
Assert.assertEquals("2017-06-02", list.get(3).getDate());
|
||||
@ -96,7 +96,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
||||
|
||||
@Test
|
||||
public void getTeacherTest() throws Exception {
|
||||
List<Grade> list = filled.getAll();
|
||||
List<Grade> list = filled.getAll("");
|
||||
|
||||
Assert.assertEquals("Patryk Maciejewski", list.get(0).getTeacher());
|
||||
Assert.assertEquals("Oliwia Woźniak", list.get(3).getTeacher());
|
||||
|
@ -0,0 +1,17 @@
|
||||
package io.github.wulkanowy.api.mobile
|
||||
|
||||
import io.github.wulkanowy.api.StudentAndParentTestCase
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class RegisterDeviceTest : StudentAndParentTestCase() {
|
||||
|
||||
@Test
|
||||
fun getTokenTest() {
|
||||
val registration = RegisterDevice(getSnp("Rejestruj.html"))
|
||||
|
||||
assertEquals("3S1A1B2C", registration.getToken().token)
|
||||
assertEquals("Default", registration.getToken().symbol)
|
||||
assertEquals("1234567", registration.getToken().pin)
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package io.github.wulkanowy.api.mobile
|
||||
|
||||
import io.github.wulkanowy.api.StudentAndParentTestCase
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class RegisteredDevicesListTest : StudentAndParentTestCase() {
|
||||
|
||||
private val filled = RegisteredDevices(getSnp("DostepMobilny-filled.html"))
|
||||
|
||||
@Test
|
||||
fun getListTest() {
|
||||
assertEquals(2, filled.getList().size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNameTest() {
|
||||
assertEquals("google Android SDK built for x86", filled.getList()[0].name)
|
||||
assertEquals("google (Android SDK) built for x86", filled.getList()[1].name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getSystemTest() {
|
||||
assertEquals("Android 8.1.0", filled.getList()[0].system)
|
||||
assertEquals("Android 8.1.0", filled.getList()[1].system)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getDateTest() {
|
||||
assertEquals("2018-01-20 22:35:30", filled.getList()[0].date)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getIdTest() {
|
||||
assertEquals(321, filled.getList()[0].id)
|
||||
}
|
||||
}
|
@ -30,8 +30,8 @@ public class NotesListTest extends StudentAndParentTestCase {
|
||||
public void getDateTest() throws Exception {
|
||||
List<Note> filledList = filled.getAllNotes();
|
||||
|
||||
Assert.assertEquals("06.06.2017", filledList.get(0).getDate());
|
||||
Assert.assertEquals("01.10.2016", filledList.get(2).getDate());
|
||||
Assert.assertEquals("2017-06-06", filledList.get(0).getDate());
|
||||
Assert.assertEquals("2016-10-01", filledList.get(2).getDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -156,6 +156,7 @@ public class TimetableTest extends StudentAndParentTestCase {
|
||||
Assert.assertEquals("poprzednio: Wychowanie fizyczne", full.getWeekTable().getDay(4).getLesson(2).getDescription());
|
||||
Assert.assertEquals("egzamin", full.getWeekTable().getDay(3).getLesson(0).getDescription());
|
||||
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getDescription());
|
||||
Assert.assertEquals("poprzednio: Zajęcia z wychowawcą", full.getWeekTable().getDay(4).getLesson(5).getDescription());
|
||||
Assert.assertEquals("opis w uwadze bez klasy w spanie", full.getWeekTable().getDay(4).getLesson(4).getDescription());
|
||||
Assert.assertEquals("", holidays.getWeekTable().getDay(3).getLesson(3).getDescription());
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pl">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Witryna ucznia i rodzica – dostęp mobilny</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<main class="mainContainer">
|
||||
<h1>Dostęp mobilny</h1>
|
||||
|
||||
<article>
|
||||
<h2>Zarejestrowane urządzenia</h2>
|
||||
</article>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Urządzenie</th>
|
||||
<th>Data rejestracji</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="text-center">
|
||||
<td>google Android SDK built for x86 (Android 8.1.0)</td>
|
||||
<td>20.01.2018 godz: 22:35:30</td>
|
||||
<td class="cellWithButton">
|
||||
<a href="/Default/123456/DostepMobilny.mvc/Wyrejestruj/321" class="button">Wyrejestruj</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="text-center">
|
||||
<td>google (Android SDK) built for x86 (Android 8.1.0)</td>
|
||||
<td>20.01.2018 godz: 22:35:30</td>
|
||||
<td class="cellWithButton">
|
||||
<a href="/Default/123456/DostepMobilny.mvc/Wyrejestruj/213" class="button">Wyrejestruj</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</main>
|
||||
|
||||
<footer>wersja: 18.01.0001.27311</footer>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pl">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Witryna ucznia i rodzica – Rejestracja urządzenia mobilnego</title>
|
||||
<style>
|
||||
.blockElement {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="mainContainer">
|
||||
<h1>Rejestracja urządzenia mobilnego</h1>
|
||||
<article class="text-center" id="rejestracja-formularz">
|
||||
<span class="blockElement">Za pomocą aplikacji "Dzienniczek+" zeskanuj kod QR.</span>
|
||||
<img src=" data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gUdCTohm9rlswAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAFKklEQVR42u3dYYqDQAyA0abk/lfO/l+6LLZYksx7J3C09SPgaFRVPQDgoqdTAICAACAgAAgIAAICAAICgIAAICAACAgAAgIAAgKAgAAgIAAICAACAgACAoCAACAgAAgIAAICAAICgIAAICAACAgAAgIAAgKAgAAgIAAICAACAgACAoCAACAgAAgIAAICAFdltwOKiNUnvKqOXj/4/9y3fhMIACMICAACAoCAACAgAAgIAAgIAJ/IaQfc7Tno3+5+Dr37+sH/p+/6TSAACAgAAgKAgACAgAAgIAAICADj5bYF2YcBuH+YQAAQEAAEBAAEBAABAUBAABAQAAQEAAQEAAEBQEAAEBAABAQABAQAAQFAQAAQEAAEBAAEBAABAUBAABAQAAQEAP6R2xZUVa4q4P5hAgFAQAAQEAAQEAAEBAABAUBAANho3D6QiHDVAPcPEwgAAgKAgACAgAAgIAAICAACAsCJ2u0D8T5+wP3DBAKAgACAgAAgIAAICAACAoCAAMBL7faBeF8/4P7wWrd9LiYQAAQEAAEBQEAAEBAAEBAABASAr8tpB+x9/7DX6f/vaftcTCAACAgAAgKAgAAgIAAgIAAICAACAoCAACAgACAgAAgIAAICgIAAICAAICAACAgAAgKAgAAgIAAgIAAICAACAoCAACAgACAgAAgIAAICgIAAICAAICAACAgAAgKAgAAgIAAgIAAICAACAoCAAICAACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAoCAAICAACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAoCAAICAACAgAAgIAAICgIA4BQAICAACAoCAACAgACAgAAgIAAICgIAAICAAICAACAgAAgKAgAAgIAAgIAAICAACAoCAACAgACAgAAgIAAICgIAAICAAICAACAgAAgKAgAAgIAAgIAAICAACAoCAACAgACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAoCAAICAACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAoCAAICAACAgAAgIAAICgIAAgIAAICAACAgAAgKAgACAgAAgIAAICAACAgACAoCAACAgAAgIAAICAAICgIAAICAACAgAAgIAAgKAgAAgIAAICAACAgACAoCAACAgAAgIAAICAAICgIAAICAACAgAAgIAAgKAgAAgIAAICAACAgACAoCAANBWTjvgiDj6glWVXy1gAgFAQAAQEAAQEAAEBAABAUBAuOb0x5CBPdrtAzl9n4PAACYQAAQEAAQEAAEBQEAAEBAABAQA/tBuH8j2fRC+5wGYQAAQEAAQEAAEBAABAUBAAEBAAHhTTjvg7vsofM8DMIEAgIAAICAACAgAAgKAgACAgABwk9y2oLv3YfieB4AJBAABAUBAABAQAAQEAAQEAAEBQEAAEBAABAQABAQAAQFAQAAQEAAEBAAEBAABAUBAABAQAAQEAAQEAAEBQEAAGC+3LaiqXFUAEwgAAgKAgACAgAAgIAAICAACAsBG4/aBRMTRF+z09QMmEAAEBAABAQABAUBAABAQAAQEgINF+YAGACYQAAQEAAEBQEAAQEAAEBAABAQAAQFAQABAQAAQEAAEBAABAUBAAEBAABAQAAQEAAEBQEAAQEAAEBAABAQAAQFAQABAQAAQEAAEBAABAUBAAEBAABAQAAQEAAEBQEAAQEAA+IYf8fZKNX0RrMQAAAAASUVORK5CYII="
|
||||
alt="Kod QR" title="Kod QR" height="400" width="400"/>
|
||||
<span class="blockElement">Token: 3S1A1B2C</span>
|
||||
<span class="blockElement">Symbol: Default</span>
|
||||
<span class="blockElement">PIN: 1234567</span>
|
||||
</article>
|
||||
</main>
|
||||
<footer>wersja: 18.01.0001.27311</footer>
|
||||
</body>
|
||||
</html>
|
@ -364,7 +364,20 @@
|
||||
<span></span>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div>
|
||||
<span class="">Tworzenie i administrowanie bazami danych [zaw2]</span>
|
||||
<span class=""></span>
|
||||
<span class=""></span>
|
||||
<span class=""></span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="x-treelabel-ppl x-treelabel-inv">Zajęcia z wychowawcą</span>
|
||||
<span class="x-treelabel-ppl x-treelabel-inv">Małgorzata Kowal</span>
|
||||
<span class="x-treelabel-ppl x-treelabel-inv">43</span>
|
||||
<span class="x-treelabel-rlz">(zmiana organizacji zajęć)</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
|
@ -41,8 +41,8 @@ android {
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 26
|
||||
versionCode 13
|
||||
versionName "0.4.5"
|
||||
versionCode 14
|
||||
versionName "0.5.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
playAccountConfig = playAccountConfigs.defaultAccountConfig
|
||||
@ -118,6 +118,9 @@ dependencies {
|
||||
implementation "com.jakewharton.threetenabp:threetenabp:$threeTenABP"
|
||||
implementation "com.google.android.gms:play-services-oss-licenses:$ossLicenses"
|
||||
|
||||
implementation "com.jakewharton.timber:timber:$timber"
|
||||
implementation "at.favre.lib:slf4j-timber:$slf4jTimber"
|
||||
|
||||
implementation("com.crashlytics.sdk.android:crashlytics:$crashlyticsSdk@aar") {
|
||||
transitive = true
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/WulkanowyTheme">
|
||||
<activity
|
||||
android:name=".ui.splash.SplashActivity"
|
||||
@ -31,20 +30,20 @@
|
||||
android:name=".ui.login.LoginActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/title_activity_login"
|
||||
android:theme="@style/WulkanowyTheme.LoginTheme"
|
||||
android:theme="@style/WulkanowyTheme.DarkActionBar"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name=".ui.main.MainActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/activity_dashboard_text"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/WulkanowyTheme" />
|
||||
/>
|
||||
<activity
|
||||
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
|
||||
android:theme="@style/WulkanowyTheme.LoginTheme" />
|
||||
android:theme="@style/WulkanowyTheme.DarkActionBar" />
|
||||
<activity
|
||||
android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
|
||||
android:theme="@style/WulkanowyTheme.LoginTheme" />
|
||||
android:theme="@style/WulkanowyTheme.DarkActionBar" />
|
||||
|
||||
<service
|
||||
android:name=".services.jobs.SyncJob"
|
||||
|
@ -12,11 +12,12 @@ import javax.inject.Inject;
|
||||
import dagger.android.AndroidInjector;
|
||||
import dagger.android.support.DaggerApplication;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.utils.Log;
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.di.DaggerAppComponent;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import io.github.wulkanowy.utils.FabricUtils;
|
||||
import io.github.wulkanowy.utils.LoggerUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class WulkanowyApp extends DaggerApplication {
|
||||
|
||||
@ -39,15 +40,18 @@ public class WulkanowyApp extends DaggerApplication {
|
||||
if (repository.getSharedRepo().isUserLoggedIn()) {
|
||||
try {
|
||||
repository.getSyncRepo().initLastUser();
|
||||
FabricUtils.logLogin("Open app", true);
|
||||
} catch (Exception e) {
|
||||
LogUtils.error("An error occurred when the application was started", e);
|
||||
FabricUtils.logLogin("Open app", false);
|
||||
Timber.e(e, "An error occurred when the application was started");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void enableDebugLog() {
|
||||
QueryBuilder.LOG_VALUES = true;
|
||||
FlexibleAdapter.enableLogs(Log.Level.DEBUG);
|
||||
FlexibleAdapter.enableLogs(eu.davidea.flexibleadapter.utils.Log.Level.DEBUG);
|
||||
Timber.plant(new LoggerUtils.DebugLogTree());
|
||||
}
|
||||
|
||||
private void initializeFabric() {
|
||||
@ -60,6 +64,7 @@ public class WulkanowyApp extends DaggerApplication {
|
||||
)
|
||||
.debuggable(BuildConfig.DEBUG)
|
||||
.build());
|
||||
Timber.plant(new LoggerUtils.CrashlyticsTree());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,4 +47,10 @@ public class Repository implements RepositoryContract {
|
||||
public SyncContract getSyncRepo() {
|
||||
return synchronization;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanAllData() {
|
||||
sharedPref.cleanSharedPref();
|
||||
database.recreateDatabase();
|
||||
}
|
||||
}
|
||||
|
@ -17,4 +17,6 @@ public interface RepositoryContract {
|
||||
DbContract getDbRepo();
|
||||
|
||||
SyncContract getSyncRepo();
|
||||
|
||||
void cleanAllData();
|
||||
}
|
||||
|
@ -30,4 +30,6 @@ public interface DbContract {
|
||||
long getCurrentSemesterId();
|
||||
|
||||
int getCurrentSemesterName();
|
||||
|
||||
void recreateDatabase();
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import io.github.wulkanowy.data.db.dao.migrations.Migration26;
|
||||
import io.github.wulkanowy.data.db.dao.migrations.Migration27;
|
||||
import io.github.wulkanowy.data.db.dao.migrations.Migration28;
|
||||
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
@Singleton
|
||||
public class DbHelper extends DaoMaster.OpenHelper {
|
||||
@ -41,7 +41,7 @@ public class DbHelper extends DaoMaster.OpenHelper {
|
||||
|
||||
@Override
|
||||
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
LogUtils.info("Cleaning user data oldVersion=" + oldVersion + " newVersion=" + newVersion);
|
||||
Timber.i("Cleaning user data oldVersion=%s newVersion=%s", oldVersion, newVersion);
|
||||
Database database = new StandardDatabase(db);
|
||||
recreateDatabase(database);
|
||||
}
|
||||
@ -54,11 +54,11 @@ public class DbHelper extends DaoMaster.OpenHelper {
|
||||
for (Migration migration : migrations) {
|
||||
if (oldVersion < migration.getVersion()) {
|
||||
try {
|
||||
LogUtils.info("Applying migration to db schema v" + migration.getVersion() + "...");
|
||||
Timber.i("Applying migration to db schema v%s...", migration.getVersion());
|
||||
migration.runMigration(db, sharedPref, vulcan);
|
||||
LogUtils.info("Migration " + migration.getVersion() + " complete");
|
||||
Timber.i("Migration %s complete", migration.getVersion());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Timber.e(e, "Failed to apply migration");
|
||||
recreateDatabase(db);
|
||||
break;
|
||||
}
|
||||
@ -67,7 +67,7 @@ public class DbHelper extends DaoMaster.OpenHelper {
|
||||
}
|
||||
|
||||
private void recreateDatabase(Database db) {
|
||||
LogUtils.info("Database is recreating...");
|
||||
Timber.i("Database is recreating...");
|
||||
sharedPref.setCurrentUserId(0);
|
||||
DaoMaster.dropAllTables(db, true);
|
||||
onCreate(db);
|
||||
|
@ -1,9 +1,12 @@
|
||||
package io.github.wulkanowy.data.db.dao;
|
||||
|
||||
import org.greenrobot.greendao.database.Database;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.data.db.dao.entities.DiaryDao;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
@ -109,4 +112,12 @@ public class DbRepository implements DbContract {
|
||||
SemesterDao.Properties.Current.eq(true)
|
||||
).unique();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recreateDatabase() {
|
||||
Database database = daoSession.getDatabase();
|
||||
|
||||
DaoMaster.dropAllTables(database, true);
|
||||
DaoMaster.createAllTables(database, true);
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.github.wulkanowy.api.Diary;
|
||||
import io.github.wulkanowy.api.Vulcan;
|
||||
import io.github.wulkanowy.api.generic.Diary;
|
||||
import io.github.wulkanowy.data.db.dao.DbHelper;
|
||||
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||
import io.github.wulkanowy.utils.security.Scrambler;
|
||||
|
@ -3,8 +3,6 @@ package io.github.wulkanowy.data.db.resources;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
@ -16,8 +14,8 @@ import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.api.NotLoggedInErrorException;
|
||||
import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson;
|
||||
import io.github.wulkanowy.utils.AppConstant;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import io.github.wulkanowy.utils.security.CryptoException;
|
||||
import timber.log.Timber;
|
||||
|
||||
@Singleton
|
||||
public class ResourcesRepository implements ResourcesContract {
|
||||
@ -41,8 +39,7 @@ public class ResourcesRepository implements ResourcesContract {
|
||||
|
||||
@Override
|
||||
public String getErrorLoginMessage(Exception exception) {
|
||||
LogUtils.error(AppConstant.APP_NAME + " encountered a error", exception);
|
||||
Crashlytics.logException(exception);
|
||||
Timber.e(exception,"%s encountered a error", AppConstant.APP_NAME);
|
||||
|
||||
if (exception instanceof CryptoException) {
|
||||
return resources.getString(R.string.encrypt_failed_text);
|
||||
|
@ -21,6 +21,8 @@ public interface SharedPrefContract {
|
||||
|
||||
boolean isShowAttendancePresent();
|
||||
|
||||
int getCurrentTheme();
|
||||
|
||||
int getServicesInterval();
|
||||
|
||||
boolean isMobileDisable();
|
||||
@ -28,4 +30,6 @@ public interface SharedPrefContract {
|
||||
boolean isServicesEnable();
|
||||
|
||||
boolean isNotifyEnable();
|
||||
|
||||
void cleanSharedPref();
|
||||
}
|
||||
|
@ -69,6 +69,11 @@ public class SharedPrefRepository implements SharedPrefContract {
|
||||
return settingsSharedPref.getBoolean(SettingsFragment.SHARED_KEY_ATTENDANCE_PRESENT, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentTheme() {
|
||||
return Integer.parseInt(settingsSharedPref.getString(SettingsFragment.SHARED_KEY_THEME, "1"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServicesInterval() {
|
||||
return Integer.parseInt(settingsSharedPref.getString(SettingsFragment.SHARED_KEY_SERVICES_INTERVAL, "60"));
|
||||
@ -88,4 +93,10 @@ public class SharedPrefRepository implements SharedPrefContract {
|
||||
public boolean isMobileDisable() {
|
||||
return settingsSharedPref.getBoolean(SettingsFragment.SHARED_KEY_SERVICES_MOBILE_DISABLED, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanSharedPref() {
|
||||
appSharedPref.edit().clear().apply();
|
||||
settingsSharedPref.edit().clear().apply();
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ import io.github.wulkanowy.data.db.dao.entities.Symbol;
|
||||
import io.github.wulkanowy.data.db.dao.entities.SymbolDao;
|
||||
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.security.CryptoException;
|
||||
import io.github.wulkanowy.utils.security.Scrambler;
|
||||
import timber.log.Timber;
|
||||
|
||||
@Singleton
|
||||
public class AccountSync {
|
||||
@ -73,7 +73,7 @@ public class AccountSync {
|
||||
}
|
||||
|
||||
private Account insertAccount(String email, String password) throws CryptoException {
|
||||
LogUtils.debug("Register account: " + email);
|
||||
Timber.d("Register account");
|
||||
Account account = new Account()
|
||||
.setEmail(email)
|
||||
.setPassword(Scrambler.encrypt(email, password, context));
|
||||
@ -82,10 +82,11 @@ public class AccountSync {
|
||||
}
|
||||
|
||||
private Symbol insertSymbol(Account account) throws VulcanException, IOException {
|
||||
LogUtils.debug("Register symbol: " + vulcan.getSymbol());
|
||||
String schoolId = vulcan.getStudentAndParent().getSchoolID();
|
||||
Timber.d("Register symbol %s", vulcan.getSymbol());
|
||||
Symbol symbol = new Symbol()
|
||||
.setUserId(account.getId())
|
||||
.setSchoolId(vulcan.getStudentAndParent().getSchoolID())
|
||||
.setSchoolId(schoolId)
|
||||
.setSymbol(vulcan.getSymbol());
|
||||
daoSession.getSymbolDao().insert(symbol);
|
||||
|
||||
@ -97,7 +98,7 @@ public class AccountSync {
|
||||
vulcan.getStudentAndParent().getStudents(),
|
||||
symbol.getId()
|
||||
);
|
||||
LogUtils.debug("Register students: " + studentList.size());
|
||||
Timber.d("Register students %s", studentList.size());
|
||||
daoSession.getStudentDao().insertInTx(studentList);
|
||||
}
|
||||
|
||||
@ -108,7 +109,7 @@ public class AccountSync {
|
||||
StudentDao.Properties.SymbolId.eq(symbolEntity.getId()),
|
||||
StudentDao.Properties.Current.eq(true)
|
||||
).unique().getId());
|
||||
LogUtils.debug("Register diaries: " + diaryList.size());
|
||||
Timber.d("Register diaries %s", diaryList.size());
|
||||
daoSession.getDiaryDao().insertInTx(diaryList);
|
||||
}
|
||||
|
||||
@ -118,7 +119,7 @@ public class AccountSync {
|
||||
daoSession.getDiaryDao().queryBuilder().where(
|
||||
DiaryDao.Properties.Current.eq(true)
|
||||
).unique().getId());
|
||||
LogUtils.debug("Register semesters: " + semesterList.size());
|
||||
Timber.d("Register semesters %s", semesterList.size());
|
||||
daoSession.getSemesterDao().insertInTx(semesterList);
|
||||
}
|
||||
|
||||
@ -130,7 +131,7 @@ public class AccountSync {
|
||||
throw new NotRegisteredUserException("Can't find user id in SharedPreferences");
|
||||
}
|
||||
|
||||
LogUtils.debug("Initialization current user id=" + userId);
|
||||
Timber.d("Init current user (%s)", userId);
|
||||
|
||||
Account account = daoSession.getAccountDao().load(userId);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package io.github.wulkanowy.data.sync;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -19,8 +18,7 @@ import io.github.wulkanowy.data.db.dao.entities.DayDao;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Week;
|
||||
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import io.github.wulkanowy.utils.TimeUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
@Singleton
|
||||
public class AttendanceSync {
|
||||
@ -37,10 +35,10 @@ public class AttendanceSync {
|
||||
this.vulcan = vulcan;
|
||||
}
|
||||
|
||||
public void syncAttendance(long diaryId, String date) throws IOException, ParseException, VulcanException {
|
||||
public void syncAttendance(long diaryId, String date) throws IOException, VulcanException {
|
||||
this.diaryId = diaryId;
|
||||
|
||||
io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.generic.Day> weekApi = getWeekFromApi(getNormalizedDate(date));
|
||||
io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.generic.Day> weekApi = getWeekFromApi(date);
|
||||
Week weekDb = getWeekFromDb(weekApi.getStartDayDate());
|
||||
|
||||
long weekId = updateWeekInDb(weekDb, weekApi);
|
||||
@ -49,15 +47,11 @@ public class AttendanceSync {
|
||||
|
||||
daoSession.getAttendanceLessonDao().saveInTx(lessonList);
|
||||
|
||||
LogUtils.debug("Synchronization attendance lessons (amount = " + lessonList.size() + ")");
|
||||
}
|
||||
|
||||
private String getNormalizedDate(String date) throws ParseException {
|
||||
return null != date ? String.valueOf(TimeUtils.getNetTicks(date)) : "";
|
||||
Timber.d("Attendance synchronization complete (%s)", lessonList.size());
|
||||
}
|
||||
|
||||
private io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.generic.Day> getWeekFromApi(String date)
|
||||
throws IOException, ParseException, VulcanException {
|
||||
throws IOException, VulcanException {
|
||||
return vulcan.getAttendanceTable().getWeekTable(date);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package io.github.wulkanowy.data.sync;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -18,8 +17,7 @@ import io.github.wulkanowy.data.db.dao.entities.ExamDao;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Week;
|
||||
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import io.github.wulkanowy.utils.TimeUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class ExamsSync {
|
||||
|
||||
@ -35,11 +33,10 @@ public class ExamsSync {
|
||||
this.vulcan = vulcan;
|
||||
}
|
||||
|
||||
public void syncExams(long diaryId, String date) throws IOException, VulcanException,
|
||||
ParseException {
|
||||
public void syncExams(long diaryId, String date) throws IOException, VulcanException {
|
||||
this.diaryId = diaryId;
|
||||
|
||||
io.github.wulkanowy.api.generic.Week<ExamDay> weekApi = getWeekFromApi(getNormalizedDate(date));
|
||||
io.github.wulkanowy.api.generic.Week<ExamDay> weekApi = getWeekFromApi(date);
|
||||
Week weekDb = getWeekFromDb(weekApi.getStartDayDate());
|
||||
|
||||
long weekId = updateWeekInDb(weekDb, weekApi);
|
||||
@ -48,7 +45,7 @@ public class ExamsSync {
|
||||
|
||||
daoSession.getExamDao().saveInTx(examList);
|
||||
|
||||
LogUtils.debug("Synchronization exams (amount = " + examList.size() + ")");
|
||||
Timber.d("Exams synchronization complete (%s)", examList.size());
|
||||
}
|
||||
|
||||
private Week getWeekFromDb(String date) {
|
||||
@ -59,7 +56,7 @@ public class ExamsSync {
|
||||
}
|
||||
|
||||
private io.github.wulkanowy.api.generic.Week<ExamDay> getWeekFromApi(String date)
|
||||
throws VulcanException, IOException, ParseException {
|
||||
throws VulcanException, IOException {
|
||||
return vulcan.getExamsList().getWeek(date, true);
|
||||
}
|
||||
|
||||
@ -77,10 +74,6 @@ public class ExamsSync {
|
||||
return daoSession.getWeekDao().insert(weekApiEntity);
|
||||
}
|
||||
|
||||
private String getNormalizedDate(String date) throws ParseException {
|
||||
return null != date ? String.valueOf(TimeUtils.getNetTicks(date)) : "";
|
||||
}
|
||||
|
||||
private Day getDayFromDb(String date, long weekId) {
|
||||
return daoSession.getDayDao().queryBuilder().where(
|
||||
DayDao.Properties.WeekId.eq(weekId),
|
||||
|
@ -1,7 +1,6 @@
|
||||
package io.github.wulkanowy.data.sync;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -16,7 +15,7 @@ import io.github.wulkanowy.data.db.dao.entities.Semester;
|
||||
import io.github.wulkanowy.data.db.dao.entities.SubjectDao;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.EntitiesCompare;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
@Singleton
|
||||
public class GradeSync {
|
||||
@ -33,7 +32,7 @@ public class GradeSync {
|
||||
this.vulcan = vulcan;
|
||||
}
|
||||
|
||||
public void sync(long semesterId) throws IOException, VulcanException, ParseException {
|
||||
public void sync(long semesterId) throws IOException, VulcanException {
|
||||
this.semesterId = semesterId;
|
||||
|
||||
Semester semester = daoSession.getSemesterDao().load(semesterId);
|
||||
@ -44,7 +43,7 @@ public class GradeSync {
|
||||
daoSession.getGradeDao().deleteInTx(semester.getGradeList());
|
||||
daoSession.getGradeDao().insertInTx(lastList);
|
||||
|
||||
LogUtils.debug("Synchronization grades (amount = " + lastList.size() + ")");
|
||||
Timber.d("Grades synchronization complete (%s)", lastList.size());
|
||||
}
|
||||
|
||||
private void resetSemesterRelations(Semester semester) {
|
||||
@ -64,7 +63,7 @@ public class GradeSync {
|
||||
return updatedList;
|
||||
}
|
||||
|
||||
private List<Grade> getComparedList(Semester semester) throws IOException, VulcanException, ParseException {
|
||||
private List<Grade> getComparedList(Semester semester) throws IOException, VulcanException {
|
||||
List<Grade> gradesFromNet = DataObjectConverter.gradesToGradeEntities(
|
||||
vulcan.getGradesList().getAll(semester.getValue()), semesterId);
|
||||
|
||||
|
@ -13,7 +13,7 @@ import io.github.wulkanowy.data.db.dao.entities.DaoSession;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Semester;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
@Singleton
|
||||
public class SubjectSync {
|
||||
@ -40,7 +40,7 @@ public class SubjectSync {
|
||||
daoSession.getSubjectDao().deleteInTx(getSubjectsFromDb());
|
||||
daoSession.getSubjectDao().insertInTx(lastList);
|
||||
|
||||
LogUtils.debug("Synchronization subjects (amount = " + lastList.size() + ")");
|
||||
Timber.d("Subjects synchronization complete (%s)", lastList.size());
|
||||
}
|
||||
|
||||
private List<Subject> getSubjectsFromNet(Semester semester) throws VulcanException, IOException {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package io.github.wulkanowy.data.sync;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -47,17 +46,17 @@ public class SyncRepository implements SyncContract {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initLastUser() throws IOException, CryptoException {
|
||||
public void initLastUser() throws CryptoException {
|
||||
accountSync.initLastUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncGrades(int semesterName) throws VulcanException, IOException, ParseException {
|
||||
public void syncGrades(int semesterName) throws VulcanException, IOException {
|
||||
gradeSync.sync(semesterName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncGrades() throws VulcanException, IOException, ParseException {
|
||||
public void syncGrades() throws VulcanException, IOException {
|
||||
gradeSync.sync(database.getCurrentSemesterId());
|
||||
}
|
||||
|
||||
@ -72,12 +71,12 @@ public class SyncRepository implements SyncContract {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncAttendance() throws ParseException, IOException, VulcanException {
|
||||
public void syncAttendance() throws IOException, VulcanException {
|
||||
attendanceSync.syncAttendance(database.getCurrentDiaryId(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncAttendance(long diaryId, String date) throws ParseException, IOException, VulcanException {
|
||||
public void syncAttendance(long diaryId, String date) throws IOException, VulcanException {
|
||||
if (diaryId != 0) {
|
||||
attendanceSync.syncAttendance(diaryId, date);
|
||||
} else {
|
||||
@ -86,12 +85,12 @@ public class SyncRepository implements SyncContract {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncTimetable() throws VulcanException, IOException, ParseException {
|
||||
public void syncTimetable() throws VulcanException, IOException {
|
||||
timetableSync.syncTimetable(database.getCurrentDiaryId(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncTimetable(long diaryId, String date) throws VulcanException, IOException, ParseException {
|
||||
public void syncTimetable(long diaryId, String date) throws VulcanException, IOException {
|
||||
if (diaryId != 0) {
|
||||
timetableSync.syncTimetable(diaryId, date);
|
||||
} else {
|
||||
@ -100,12 +99,12 @@ public class SyncRepository implements SyncContract {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncExams() throws VulcanException, IOException, ParseException {
|
||||
public void syncExams() throws VulcanException, IOException {
|
||||
examsSync.syncExams(database.getCurrentDiaryId(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncExams(long diaryId, String date) throws VulcanException, IOException, ParseException {
|
||||
public void syncExams(long diaryId, String date) throws VulcanException, IOException {
|
||||
if (diaryId != 0) {
|
||||
examsSync.syncExams(diaryId, date);
|
||||
} else {
|
||||
@ -114,7 +113,7 @@ public class SyncRepository implements SyncContract {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncAll() throws VulcanException, IOException, ParseException {
|
||||
public void syncAll() throws VulcanException, IOException {
|
||||
syncSubjects();
|
||||
syncGrades();
|
||||
syncAttendance();
|
||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.data.sync;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -21,8 +20,7 @@ import io.github.wulkanowy.data.db.dao.entities.TimetableLessonDao;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Week;
|
||||
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
|
||||
import io.github.wulkanowy.utils.DataObjectConverter;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import io.github.wulkanowy.utils.TimeUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
@Singleton
|
||||
public class TimetableSync {
|
||||
@ -39,10 +37,10 @@ public class TimetableSync {
|
||||
this.vulcan = vulcan;
|
||||
}
|
||||
|
||||
public void syncTimetable(long diaryId, String date) throws IOException, ParseException, VulcanException {
|
||||
public void syncTimetable(long diaryId, String date) throws IOException, VulcanException {
|
||||
this.diaryId = diaryId;
|
||||
|
||||
io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.timetable.TimetableDay> weekApi = getWeekFromApi(getNormalizedDate(date));
|
||||
io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.timetable.TimetableDay> weekApi = getWeekFromApi(date);
|
||||
Week weekDb = getWeekFromDb(weekApi.getStartDayDate());
|
||||
|
||||
long weekId = updateWeekInDb(weekDb, weekApi);
|
||||
@ -51,15 +49,11 @@ public class TimetableSync {
|
||||
|
||||
daoSession.getTimetableLessonDao().saveInTx(lessonList);
|
||||
|
||||
LogUtils.debug("Synchronization timetable lessons (amount = " + lessonList.size() + ")");
|
||||
}
|
||||
|
||||
private String getNormalizedDate(String date) throws ParseException {
|
||||
return null != date ? String.valueOf(TimeUtils.getNetTicks(date)) : "";
|
||||
Timber.d("Timetable synchronization complete (%s)", lessonList.size());
|
||||
}
|
||||
|
||||
private io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.timetable.TimetableDay> getWeekFromApi(String date)
|
||||
throws IOException, ParseException, VulcanException {
|
||||
throws IOException, VulcanException {
|
||||
return vulcan.getTimetable().getWeekTable(date);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.firebase.jobdispatcher.Constraint;
|
||||
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
|
||||
import com.firebase.jobdispatcher.GooglePlayDriver;
|
||||
@ -22,12 +21,14 @@ import javax.inject.Inject;
|
||||
|
||||
import dagger.android.AndroidInjection;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.api.login.BadCredentialsException;
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.data.sync.NotRegisteredUserException;
|
||||
import io.github.wulkanowy.services.notifies.GradeNotify;
|
||||
import io.github.wulkanowy.ui.main.MainActivity;
|
||||
import io.github.wulkanowy.utils.LogUtils;
|
||||
import io.github.wulkanowy.utils.FabricUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class SyncJob extends SimpleJobService {
|
||||
|
||||
@ -74,13 +75,24 @@ public class SyncJob extends SimpleJobService {
|
||||
if (!gradeList.isEmpty() && repository.getSharedRepo().isNotifyEnable()) {
|
||||
showNotification();
|
||||
}
|
||||
|
||||
FabricUtils.logLogin("Background", true);
|
||||
|
||||
return JobService.RESULT_SUCCESS;
|
||||
} catch (NotRegisteredUserException e) {
|
||||
logError(e);
|
||||
stop(getApplicationContext());
|
||||
|
||||
return JobService.RESULT_FAIL_NORETRY;
|
||||
} catch (BadCredentialsException e) {
|
||||
logError(e);
|
||||
repository.cleanAllData();
|
||||
stop(getApplicationContext());
|
||||
|
||||
return JobService.RESULT_FAIL_NORETRY;
|
||||
} catch (Exception e) {
|
||||
logError(e);
|
||||
|
||||
return JobService.RESULT_FAIL_RETRY;
|
||||
}
|
||||
}
|
||||
@ -122,7 +134,7 @@ public class SyncJob extends SimpleJobService {
|
||||
}
|
||||
|
||||
private void logError(Exception e) {
|
||||
Crashlytics.logException(e);
|
||||
LogUtils.error("During background synchronization an error occurred", e);
|
||||
FabricUtils.logLogin("Background", false);
|
||||
Timber.e(e, "During background synchronization an error occurred");
|
||||
}
|
||||
}
|
||||
|
@ -54,5 +54,6 @@ public abstract class BaseActivity extends DaggerAppCompatActivity implements Ba
|
||||
if (unbinder != null) {
|
||||
unbinder.unbind();
|
||||
}
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ -217,6 +218,12 @@ public class LoginActivity extends BaseActivity implements LoginContract.View {
|
||||
return findViewById(R.id.login_activity_container);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onSyncFailed() {
|
||||
Toast.makeText(getApplicationContext(), R.string.login_sync_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void onLoginProgressUpdate(String step, String message) {
|
||||
loginProgressText.setText(String.format("%1$s/2 - %2$s...", step, message));
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ public interface LoginContract {
|
||||
|
||||
void showActionBar(boolean show);
|
||||
|
||||
void onSyncFailed();
|
||||
|
||||
}
|
||||
|
||||
interface Presenter extends BaseContract.Presenter<View> {
|
||||
@ -45,7 +47,7 @@ public interface LoginContract {
|
||||
|
||||
void onLoginProgress(int step);
|
||||
|
||||
void onEndAsync(boolean success, Exception exception);
|
||||
void onEndAsync(int success, Exception exception);
|
||||
|
||||
void onCanceledAsync();
|
||||
}
|
||||
|
@ -83,22 +83,30 @@ public class LoginPresenter extends BasePresenter<LoginContract.View>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEndAsync(boolean success, Exception exception) {
|
||||
if (success) {
|
||||
FabricUtils.logRegister(true, getRepository().getDbRepo().getCurrentSymbol().getSymbol());
|
||||
getView().openMainActivity();
|
||||
return;
|
||||
} else if (exception instanceof BadCredentialsException) {
|
||||
getView().setErrorPassIncorrect();
|
||||
getView().showSoftInput();
|
||||
} else if (exception instanceof AccountPermissionException) {
|
||||
getView().setErrorSymbolRequired();
|
||||
getView().showSoftInput();
|
||||
} else {
|
||||
FabricUtils.logRegister(false, symbol);
|
||||
getView().showMessage(getRepository().getResRepo().getErrorLoginMessage(exception));
|
||||
public void onEndAsync(int success, Exception exception) {
|
||||
switch (success) {
|
||||
case LoginTask.LOGIN_AND_SYNC_SUCCESS:
|
||||
FabricUtils.logRegister(true, getRepository().getDbRepo().getCurrentSymbol().getSymbol(), "Success");
|
||||
getView().openMainActivity();
|
||||
return;
|
||||
case LoginTask.SYNC_FAILED:
|
||||
FabricUtils.logRegister(true, symbol, exception.getMessage());
|
||||
getView().onSyncFailed();
|
||||
getView().openMainActivity();
|
||||
return;
|
||||
case LoginTask.LOGIN_FAILED:
|
||||
if (exception instanceof BadCredentialsException) {
|
||||
getView().setErrorPassIncorrect();
|
||||
getView().showSoftInput();
|
||||
} else if (exception instanceof AccountPermissionException) {
|
||||
getView().setErrorSymbolRequired();
|
||||
getView().showSoftInput();
|
||||
} else {
|
||||
FabricUtils.logRegister(false, symbol, exception.getMessage());
|
||||
getView().showMessage(getRepository().getResRepo().getErrorLoginMessage(exception));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
getView().showActionBar(true);
|
||||
getView().showLoginProgress(false);
|
||||
}
|
||||
|
@ -2,7 +2,13 @@ package io.github.wulkanowy.ui.login;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
public class LoginTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
public class LoginTask extends AsyncTask<Void, Integer, Integer> {
|
||||
|
||||
public final static int LOGIN_AND_SYNC_SUCCESS = 1;
|
||||
|
||||
public final static int LOGIN_FAILED = -1;
|
||||
|
||||
public final static int SYNC_FAILED = 2;
|
||||
|
||||
private LoginContract.Presenter presenter;
|
||||
|
||||
@ -18,18 +24,23 @@ public class LoginTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
protected Integer doInBackground(Void... params) {
|
||||
try {
|
||||
publishProgress(1);
|
||||
presenter.onDoInBackground(1);
|
||||
} catch (Exception e) {
|
||||
exception = e;
|
||||
return LOGIN_FAILED;
|
||||
}
|
||||
|
||||
try {
|
||||
publishProgress(2);
|
||||
presenter.onDoInBackground(2);
|
||||
} catch (Exception e) {
|
||||
exception = e;
|
||||
return false;
|
||||
return SYNC_FAILED;
|
||||
}
|
||||
return true;
|
||||
return LOGIN_AND_SYNC_SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -38,7 +49,7 @@ public class LoginTask extends AsyncTask<Void, Integer, Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success) {
|
||||
protected void onPostExecute(Integer success) {
|
||||
presenter.onEndAsync(success, exception);
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,9 @@ 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.annotation.NonNull;
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
@ -18,6 +18,7 @@ import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.RepositoryContract;
|
||||
import io.github.wulkanowy.services.jobs.SyncJob;
|
||||
import io.github.wulkanowy.ui.base.BaseActivity;
|
||||
import io.github.wulkanowy.ui.base.BasePagerAdapter;
|
||||
@ -26,6 +27,7 @@ import io.github.wulkanowy.ui.main.exams.ExamsFragment;
|
||||
import io.github.wulkanowy.ui.main.grades.GradesFragment;
|
||||
import io.github.wulkanowy.ui.main.settings.SettingsFragment;
|
||||
import io.github.wulkanowy.ui.main.timetable.TimetableFragment;
|
||||
import io.github.wulkanowy.utils.CommonUtils;
|
||||
|
||||
public class MainActivity extends BaseActivity implements MainContract.View,
|
||||
AHBottomNavigation.OnTabSelectedListener, OnFragmentIsReadyListener {
|
||||
@ -41,6 +43,9 @@ public class MainActivity extends BaseActivity implements MainContract.View,
|
||||
@BindView(R.id.main_activity_progress_bar)
|
||||
View progressBar;
|
||||
|
||||
@BindView(R.id.main_activity_appbar)
|
||||
AppBarLayout appBar;
|
||||
|
||||
@Named("Main")
|
||||
@Inject
|
||||
BasePagerAdapter pagerAdapter;
|
||||
@ -48,6 +53,9 @@ public class MainActivity extends BaseActivity implements MainContract.View,
|
||||
@Inject
|
||||
MainContract.Presenter presenter;
|
||||
|
||||
@Inject
|
||||
RepositoryContract repository;
|
||||
|
||||
public static Intent getStartIntent(Context context) {
|
||||
return new Intent(context, MainActivity.class);
|
||||
}
|
||||
@ -56,7 +64,7 @@ public class MainActivity extends BaseActivity implements MainContract.View,
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
|
||||
setSupportActionBar((Toolbar) findViewById(R.id.main_activity_toolbar));
|
||||
injectViews();
|
||||
|
||||
presenter.attachView(this, getIntent().getIntExtra(EXTRA_CARD_ID_KEY, -1));
|
||||
@ -88,6 +96,8 @@ public class MainActivity extends BaseActivity implements MainContract.View,
|
||||
@Override
|
||||
public boolean onTabSelected(int position, boolean wasSelected) {
|
||||
presenter.onTabSelected(position, wasSelected);
|
||||
appBar.setExpanded(true, true);
|
||||
invalidateOptionsMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -119,8 +129,8 @@ public class MainActivity extends BaseActivity implements MainContract.View,
|
||||
R.drawable.ic_menu_other_24dp));
|
||||
|
||||
bottomNavigation.setAccentColor(getResources().getColor(R.color.colorPrimary));
|
||||
bottomNavigation.setInactiveColor(Color.BLACK);
|
||||
bottomNavigation.setBackgroundColor(getResources().getColor(R.color.colorBackgroundBottomNav));
|
||||
bottomNavigation.setInactiveColor(CommonUtils.getThemeAttrColor(this, android.R.attr.textColorTertiary));
|
||||
bottomNavigation.setDefaultBackgroundColor(CommonUtils.getThemeAttrColor(this, R.attr.bottomNavBackground));
|
||||
bottomNavigation.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW);
|
||||
bottomNavigation.setOnTabSelectedListener(this);
|
||||
bottomNavigation.setCurrentItem(tabPosition);
|
||||
|
@ -78,7 +78,7 @@ public class AttendanceDialogFragment extends DialogFragment {
|
||||
description.setText(lesson.getDescription());
|
||||
|
||||
if (lesson.getAbsenceUnexcused()) {
|
||||
description.setTextColor(getResources().getColor(R.color.colorPrimaryDark));
|
||||
description.setTextColor(getResources().getColor(R.color.colorPrimary));
|
||||
}
|
||||
|
||||
return view;
|
||||
|
@ -14,7 +14,6 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindColor;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
@ -23,13 +22,14 @@ import eu.davidea.flexibleadapter.items.IFlexible;
|
||||
import eu.davidea.viewholders.ExpandableViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Day;
|
||||
import io.github.wulkanowy.utils.CommonUtils;
|
||||
|
||||
public class AttendanceHeaderItem
|
||||
extends AbstractExpandableHeaderItem<AttendanceHeaderItem.HeaderViewHolder, AttendanceSubItem> {
|
||||
public class AttendanceHeader
|
||||
extends AbstractExpandableHeaderItem<AttendanceHeader.HeaderViewHolder, AttendanceSubItem> {
|
||||
|
||||
private Day day;
|
||||
|
||||
AttendanceHeaderItem(Day day) {
|
||||
AttendanceHeader(Day day) {
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ public class AttendanceHeaderItem
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AttendanceHeaderItem that = (AttendanceHeaderItem) o;
|
||||
AttendanceHeader that = (AttendanceHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(day, that.day)
|
||||
@ -86,15 +86,6 @@ public class AttendanceHeaderItem
|
||||
@BindView(R.id.attendance_header_free_name)
|
||||
TextView freeName;
|
||||
|
||||
@BindColor(R.color.secondary_text)
|
||||
int secondaryColor;
|
||||
|
||||
@BindColor(R.color.free_day)
|
||||
int backgroundFreeDay;
|
||||
|
||||
@BindColor(android.R.color.black)
|
||||
int black;
|
||||
|
||||
private Context context;
|
||||
|
||||
HeaderViewHolder(View view, FlexibleAdapter adapter) {
|
||||
@ -117,16 +108,15 @@ public class AttendanceHeaderItem
|
||||
setInactiveHeader(item.getAttendanceLessons().isEmpty());
|
||||
}
|
||||
|
||||
|
||||
private void setInactiveHeader(boolean inactive) {
|
||||
((FrameLayout) getContentView()).setForeground(inactive ? null : getSelectableDrawable());
|
||||
dayName.setTextColor(inactive ? secondaryColor : black);
|
||||
dayName.setTextColor(CommonUtils.getThemeAttrColor(context,
|
||||
inactive ? android.R.attr.textColorSecondary : android.R.attr.textColorPrimary));
|
||||
|
||||
if (inactive) {
|
||||
getContentView().setBackgroundColor(backgroundFreeDay);
|
||||
getContentView().setBackgroundColor(CommonUtils.getThemeAttrColor(context, R.attr.colorControlHighlight));
|
||||
} else {
|
||||
getContentView().setBackgroundDrawable(context.getResources()
|
||||
.getDrawable(R.drawable.ic_border));
|
||||
getContentView().setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_border));
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson;
|
||||
import io.github.wulkanowy.ui.main.attendance.AttendanceDialogFragment;
|
||||
|
||||
class AttendanceSubItem
|
||||
extends AbstractSectionableItem<AttendanceSubItem.SubItemViewHolder, AttendanceHeaderItem> {
|
||||
extends AbstractSectionableItem<AttendanceSubItem.SubItemViewHolder, AttendanceHeader> {
|
||||
|
||||
private AttendanceLesson lesson;
|
||||
|
||||
AttendanceSubItem(AttendanceHeaderItem header, AttendanceLesson lesson) {
|
||||
AttendanceSubItem(AttendanceHeader header, AttendanceLesson lesson) {
|
||||
super(header);
|
||||
this.lesson = lesson;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public interface AttendanceTabContract {
|
||||
|
||||
interface View extends BaseContract.View {
|
||||
|
||||
void updateAdapterList(List<AttendanceHeaderItem> headerItems);
|
||||
void updateAdapterList(List<AttendanceHeader> headerItems);
|
||||
|
||||
void onRefreshSuccess();
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class AttendanceTabFragment extends BaseFragment implements AttendanceTab
|
||||
AttendanceTabContract.Presenter presenter;
|
||||
|
||||
@Inject
|
||||
FlexibleAdapter<AttendanceHeaderItem> adapter;
|
||||
FlexibleAdapter<AttendanceHeader> adapter;
|
||||
|
||||
private boolean isFragmentVisible = false;
|
||||
|
||||
@ -83,7 +83,7 @@ public class AttendanceTabFragment extends BaseFragment implements AttendanceTab
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAdapterList(List<AttendanceHeaderItem> headerItems) {
|
||||
public void updateAdapterList(List<AttendanceHeader> headerItems) {
|
||||
adapter.updateDataSet(headerItems);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ public abstract class AttendanceTabModule {
|
||||
|
||||
@PerChildFragment
|
||||
@Provides
|
||||
static FlexibleAdapter<AttendanceHeaderItem> provideAdapter() {
|
||||
static FlexibleAdapter<AttendanceHeader> provideAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class AttendanceTabPresenter extends BasePresenter<AttendanceTabContract.
|
||||
|
||||
private AbstractTask loadingTask;
|
||||
|
||||
private List<AttendanceHeaderItem> headerItems = new ArrayList<>();
|
||||
private List<AttendanceHeader> headerItems = new ArrayList<>();
|
||||
|
||||
private String date;
|
||||
|
||||
@ -115,7 +115,7 @@ public class AttendanceTabPresenter extends BasePresenter<AttendanceTabContract.
|
||||
|
||||
for (Day day : dayList) {
|
||||
day.resetAttendanceLessons();
|
||||
AttendanceHeaderItem headerItem = new AttendanceHeaderItem(day);
|
||||
AttendanceHeader headerItem = new AttendanceHeader(day);
|
||||
|
||||
if (isEmptyWeek) {
|
||||
isEmptyWeek = day.getAttendanceLessons().isEmpty();
|
||||
|
@ -2,7 +2,6 @@ package io.github.wulkanowy.ui.main.exams;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
@ -13,7 +12,6 @@ import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.ui.base.BaseFragment;
|
||||
import io.github.wulkanowy.ui.base.BasePagerAdapter;
|
||||
|
@ -18,11 +18,11 @@ import eu.davidea.viewholders.FlexibleViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Day;
|
||||
|
||||
public class ExamsHeaderItem extends AbstractHeaderItem<ExamsHeaderItem.HeaderVieHolder> {
|
||||
public class ExamsHeader extends AbstractHeaderItem<ExamsHeader.HeaderVieHolder> {
|
||||
|
||||
private Day day;
|
||||
|
||||
ExamsHeaderItem(Day day) {
|
||||
ExamsHeader(Day day) {
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ public class ExamsHeaderItem extends AbstractHeaderItem<ExamsHeaderItem.HeaderVi
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ExamsHeaderItem that = (ExamsHeaderItem) o;
|
||||
ExamsHeader that = (ExamsHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(day, that.day)
|
@ -21,11 +21,11 @@ import io.github.wulkanowy.data.db.dao.entities.Exam;
|
||||
import io.github.wulkanowy.ui.main.exams.ExamsDialogFragment;
|
||||
|
||||
public class ExamsSubItem
|
||||
extends AbstractSectionableItem<ExamsSubItem.SubItemViewHolder, ExamsHeaderItem> {
|
||||
extends AbstractSectionableItem<ExamsSubItem.SubItemViewHolder, ExamsHeader> {
|
||||
|
||||
private Exam exam;
|
||||
|
||||
ExamsSubItem(ExamsHeaderItem header, Exam exam) {
|
||||
ExamsSubItem(ExamsHeader header, Exam exam) {
|
||||
super(header);
|
||||
this.exam = exam;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ public class ExamsTabPresenter extends BasePresenter<ExamsTabContract.View>
|
||||
|
||||
for (Day day : dayList) {
|
||||
day.resetExams();
|
||||
ExamsHeaderItem headerItem = new ExamsHeaderItem(day);
|
||||
ExamsHeader headerItem = new ExamsHeader(day);
|
||||
|
||||
List<Exam> examList = day.getExams();
|
||||
|
||||
|
@ -12,7 +12,9 @@ public interface GradesContract {
|
||||
|
||||
interface View extends BaseContract.View, SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
void updateAdapterList(List<GradeHeaderItem> headerItems);
|
||||
void updateAdapterList(List<GradesHeader> headerItems);
|
||||
|
||||
void updateSummaryAdapterList(List<GradesSummarySubItem> summarySubItems);
|
||||
|
||||
void showNoItem(boolean show);
|
||||
|
||||
@ -28,6 +30,8 @@ public interface GradesContract {
|
||||
|
||||
boolean isMenuVisible();
|
||||
|
||||
void setSummaryAverages(String calculatedValue, String predictedValue, String finalValue );
|
||||
|
||||
}
|
||||
|
||||
interface Presenter extends BaseContract.Presenter<View> {
|
||||
|
@ -71,7 +71,7 @@ public class GradesDialogFragment extends DialogFragment {
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.grade_dialog, container, false);
|
||||
View view = inflater.inflate(R.layout.grades_dialog, container, false);
|
||||
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
|
@ -13,6 +13,7 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -27,17 +28,38 @@ import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
|
||||
public class GradesFragment extends BaseFragment implements GradesContract.View {
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_container)
|
||||
View summary;
|
||||
|
||||
@BindView(R.id.grade_fragment_details_container)
|
||||
View details;
|
||||
|
||||
@BindView(R.id.grade_fragment_recycler)
|
||||
RecyclerView recyclerView;
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_recycler)
|
||||
RecyclerView summaryRecyclerView;
|
||||
|
||||
@BindView(R.id.grade_fragment_no_item_container)
|
||||
View noItemView;
|
||||
|
||||
@BindView(R.id.grade_fragment_swipe_refresh)
|
||||
SwipeRefreshLayout refreshLayout;
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_predicted_average)
|
||||
TextView predictedAverage;
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_calculated_average)
|
||||
TextView calculatedAverage;
|
||||
|
||||
@BindView(R.id.grade_fragment_summary_final_average)
|
||||
TextView finalAverage;
|
||||
|
||||
@Inject
|
||||
FlexibleAdapter<GradeHeaderItem> adapter;
|
||||
FlexibleAdapter<GradesHeader> adapter;
|
||||
|
||||
@Inject
|
||||
FlexibleAdapter<GradesSummarySubItem> summaryAdapter;
|
||||
|
||||
@Inject
|
||||
GradesContract.Presenter presenter;
|
||||
@ -66,43 +88,59 @@ public class GradesFragment extends BaseFragment implements GradesContract.View
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.semester_switch, menu);
|
||||
menu.clear();
|
||||
inflater.inflate(R.menu.grades_action_menu, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_filter) {
|
||||
presenter.onSemesterSwitchActive();
|
||||
CharSequence[] items = new CharSequence[]{
|
||||
getResources().getString(R.string.semester_text, 1),
|
||||
getResources().getString(R.string.semester_text, 2),
|
||||
};
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.switch_semester)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setSingleChoiceItems(items, this.currentSemester, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
presenter.onSemesterChange(which);
|
||||
dialog.cancel();
|
||||
}
|
||||
}).show();
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_semester_switch:
|
||||
presenter.onSemesterSwitchActive();
|
||||
CharSequence[] items = new CharSequence[]{
|
||||
getResources().getString(R.string.semester_text, 1),
|
||||
getResources().getString(R.string.semester_text, 2),
|
||||
};
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.switch_semester)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setSingleChoiceItems(items, this.currentSemester, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
presenter.onSemesterChange(which);
|
||||
dialog.cancel();
|
||||
}
|
||||
}).show();
|
||||
return true;
|
||||
case R.id.action_summary_switch:
|
||||
boolean isDetailsVisible = details.getVisibility() == View.VISIBLE;
|
||||
|
||||
item.setTitle(isDetailsVisible ? R.string.action_title_details : R.string.action_title_summary);
|
||||
details.setVisibility(isDetailsVisible ? View.INVISIBLE : View.VISIBLE);
|
||||
summary.setVisibility(isDetailsVisible ? View.VISIBLE : View.INVISIBLE);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
noItemView.setVisibility(View.GONE);
|
||||
summary.setVisibility(View.INVISIBLE);
|
||||
details.setVisibility(View.VISIBLE);
|
||||
|
||||
adapter.setAutoCollapseOnExpand(true);
|
||||
adapter.setAutoScrollOnExpand(true);
|
||||
adapter.expandItemsAtStartUp();
|
||||
summaryAdapter.setDisplayHeadersAtStartUp(true);
|
||||
|
||||
recyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(view.getContext()));
|
||||
recyclerView.setAdapter(adapter);
|
||||
summaryRecyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(view.getContext()));
|
||||
summaryRecyclerView.setAdapter(summaryAdapter);
|
||||
summaryRecyclerView.setNestedScrollingEnabled(false);
|
||||
|
||||
refreshLayout.setColorSchemeResources(android.R.color.black);
|
||||
refreshLayout.setOnRefreshListener(this);
|
||||
@ -116,6 +154,13 @@ public class GradesFragment extends BaseFragment implements GradesContract.View
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSummaryAverages(String calculatedValue, String predictedValue, String finalValue) {
|
||||
calculatedAverage.setText(calculatedValue);
|
||||
predictedAverage.setText(predictedValue);
|
||||
finalAverage.setText(finalValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActivityTitle() {
|
||||
setTitle(getString(R.string.grades_text));
|
||||
@ -141,10 +186,15 @@ public class GradesFragment extends BaseFragment implements GradesContract.View
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAdapterList(List<GradeHeaderItem> headerItems) {
|
||||
public void updateAdapterList(List<GradesHeader> headerItems) {
|
||||
adapter.updateDataSet(headerItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSummaryAdapterList(List<GradesSummarySubItem> summarySubItems) {
|
||||
summaryAdapter.updateDataSet(summarySubItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSuccessNoGrade() {
|
||||
showMessage(R.string.snackbar_no_grades);
|
||||
|
@ -20,14 +20,14 @@ import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.utils.AnimationUtils;
|
||||
import io.github.wulkanowy.utils.GradeUtils;
|
||||
|
||||
public class GradeHeaderItem
|
||||
extends AbstractExpandableHeaderItem<GradeHeaderItem.HeaderViewHolder, GradesSubItem> {
|
||||
public class GradesHeader
|
||||
extends AbstractExpandableHeaderItem<GradesHeader.HeaderViewHolder, GradesSubItem> {
|
||||
|
||||
private Subject subject;
|
||||
|
||||
private final boolean isShowSummary;
|
||||
|
||||
GradeHeaderItem(Subject subject, boolean isShowSummary) {
|
||||
GradesHeader(Subject subject, boolean isShowSummary) {
|
||||
this.subject = subject;
|
||||
this.isShowSummary = isShowSummary;
|
||||
}
|
||||
@ -38,7 +38,7 @@ public class GradeHeaderItem
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GradeHeaderItem that = (GradeHeaderItem) o;
|
||||
GradesHeader that = (GradesHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(subject, that.subject)
|
||||
@ -54,7 +54,7 @@ public class GradeHeaderItem
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.grade_header;
|
||||
return R.layout.grades_header;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -118,29 +118,41 @@ public class GradeHeaderItem
|
||||
item.getFinalRating()));
|
||||
|
||||
resetViews();
|
||||
toggleSummaryText();
|
||||
toggleSubjectText();
|
||||
toggleSummary();
|
||||
|
||||
alertImage.setVisibility(isSubItemsReadAndSaveAlertView(subItems)
|
||||
? View.INVISIBLE : View.VISIBLE);
|
||||
}
|
||||
|
||||
private String getGradesAverageString() {
|
||||
float average = GradeUtils.calculateWeightedAverage(item.getGradeList());
|
||||
|
||||
if (average < 0) {
|
||||
return resources.getString(R.string.info_no_average);
|
||||
}
|
||||
|
||||
return resources.getString(R.string.info_average_grades, average);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
super.onClick(view);
|
||||
toggleSubjectText();
|
||||
toggleSummaryText();
|
||||
toggleSummary();
|
||||
}
|
||||
|
||||
private void toggleSummaryText() {
|
||||
if (isSummaryToggleable()) {
|
||||
if (isExpand()) {
|
||||
AnimationUtils.slideDown(predictedText);
|
||||
AnimationUtils.slideDown(finalText);
|
||||
} else {
|
||||
AnimationUtils.slideUp(predictedText);
|
||||
AnimationUtils.slideUp(finalText);
|
||||
}
|
||||
private void resetViews() {
|
||||
subjectName.setMaxLines(1);
|
||||
setDefaultSummaryVisibility(predictedText, item.getPredictedRating());
|
||||
setDefaultSummaryVisibility(finalText, item.getFinalRating());
|
||||
}
|
||||
|
||||
private void setDefaultSummaryVisibility(View view, String value) {
|
||||
if (!"-".equals(value) && isShowSummary) {
|
||||
view.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
view.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,10 +164,25 @@ public class GradeHeaderItem
|
||||
}
|
||||
}
|
||||
|
||||
private void resetViews() {
|
||||
subjectName.setMaxLines(1);
|
||||
predictedText.setVisibility(View.GONE);
|
||||
finalText.setVisibility(View.GONE);
|
||||
private void toggleSummary() {
|
||||
toggleSummaryView(predictedText, item.getPredictedRating(), isExpand());
|
||||
toggleSummaryView(finalText, item.getFinalRating(), isExpand());
|
||||
}
|
||||
|
||||
private boolean isExpand() {
|
||||
return adapter.isExpanded(getFlexibleAdapterPosition());
|
||||
}
|
||||
|
||||
private void toggleSummaryView(View view, String value, boolean expand) {
|
||||
if ("-".equals(value) || isShowSummary) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (expand) {
|
||||
AnimationUtils.slideDown(view);
|
||||
} else {
|
||||
AnimationUtils.slideUp(view);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSubItemsReadAndSaveAlertView(List<GradesSubItem> subItems) {
|
||||
@ -168,37 +195,5 @@ public class GradeHeaderItem
|
||||
|
||||
return isRead;
|
||||
}
|
||||
|
||||
private String getGradesAverageString() {
|
||||
float average = GradeUtils.calculate(item.getGradeList());
|
||||
|
||||
if (average < 0) {
|
||||
return resources.getString(R.string.info_no_average);
|
||||
}
|
||||
|
||||
return resources.getString(R.string.info_average_grades, average);
|
||||
}
|
||||
|
||||
private boolean isExpand() {
|
||||
return adapter.isExpanded(getFlexibleAdapterPosition());
|
||||
}
|
||||
|
||||
private boolean isSummaryToggleable() {
|
||||
boolean isSummaryEmpty = true;
|
||||
|
||||
if (!"-".equals(item.getPredictedRating()) || !"-".equals(item.getFinalRating())) {
|
||||
isSummaryEmpty = false;
|
||||
}
|
||||
|
||||
if (isSummaryEmpty) {
|
||||
return false;
|
||||
} else if (isShowSummary) {
|
||||
predictedText.setVisibility(View.VISIBLE);
|
||||
finalText.setVisibility(View.VISIBLE);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,12 @@ public abstract class GradesModule {
|
||||
abstract GradesContract.Presenter provideGradesPresenter(GradesPresenter gradesPresenter);
|
||||
|
||||
@Provides
|
||||
static FlexibleAdapter<GradeHeaderItem> provideGradesAdapter() {
|
||||
static FlexibleAdapter<GradesHeader> provideGradesAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
|
||||
@Provides
|
||||
static FlexibleAdapter<GradesSummarySubItem> provideGradesSummaryAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import org.threeten.bp.LocalDate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ -18,6 +19,7 @@ import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
import io.github.wulkanowy.ui.base.BasePresenter;
|
||||
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
|
||||
import io.github.wulkanowy.utils.FabricUtils;
|
||||
import io.github.wulkanowy.utils.GradeUtils;
|
||||
import io.github.wulkanowy.utils.async.AbstractTask;
|
||||
import io.github.wulkanowy.utils.async.AsyncListeners;
|
||||
|
||||
@ -31,12 +33,20 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
|
||||
private OnFragmentIsReadyListener listener;
|
||||
|
||||
private List<GradeHeaderItem> headerItems = new ArrayList<>();
|
||||
private List<GradesHeader> headerItems = new ArrayList<>();
|
||||
|
||||
private List<GradesSummarySubItem> summarySubItems = new ArrayList<>();
|
||||
|
||||
private boolean isFirstSight = false;
|
||||
|
||||
private int semesterName;
|
||||
|
||||
private float finalAverage;
|
||||
|
||||
private float predictedAverage;
|
||||
|
||||
private float calculatedAverage;
|
||||
|
||||
@Inject
|
||||
GradesPresenter(RepositoryContract repository) {
|
||||
super(repository);
|
||||
@ -56,7 +66,6 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
|
||||
if (!isFirstSight) {
|
||||
isFirstSight = true;
|
||||
|
||||
reloadGrades();
|
||||
}
|
||||
}
|
||||
@ -76,12 +85,6 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
.putCustomAttribute("Name", semesterName));
|
||||
}
|
||||
|
||||
private void reloadGrades() {
|
||||
loadingTask = new AbstractTask();
|
||||
loadingTask.setOnFirstLoadingListener(this);
|
||||
loadingTask.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentVisible(boolean isVisible) {
|
||||
if (isVisible) {
|
||||
@ -140,13 +143,17 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
boolean isShowSummary = getRepository().getSharedRepo().isShowGradesSummary();
|
||||
|
||||
headerItems = new ArrayList<>();
|
||||
summarySubItems = new ArrayList<>();
|
||||
|
||||
for (Subject subject : subjectList) {
|
||||
subject.resetGradeList();
|
||||
List<Grade> gradeList = subject.getGradeList();
|
||||
|
||||
GradesSummaryHeader summaryHeader = new GradesSummaryHeader(subject, GradeUtils.calculateWeightedAverage(gradeList));
|
||||
summarySubItems.add(new GradesSummarySubItem(summaryHeader, subject));
|
||||
|
||||
if (!gradeList.isEmpty()) {
|
||||
GradeHeaderItem headerItem = new GradeHeaderItem(subject, isShowSummary);
|
||||
GradesHeader headerItem = new GradesHeader(subject, isShowSummary);
|
||||
|
||||
List<GradesSubItem> subItems = new ArrayList<>();
|
||||
|
||||
@ -159,6 +166,10 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
headerItems.add(headerItem);
|
||||
}
|
||||
}
|
||||
|
||||
finalAverage = GradeUtils.calculateSubjectsAverage(subjectList, false);
|
||||
predictedAverage = GradeUtils.calculateSubjectsAverage(subjectList, true);
|
||||
calculatedAverage = GradeUtils.calculateDetailedSubjectsAverage(subjectList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -170,9 +181,35 @@ public class GradesPresenter extends BasePresenter<GradesContract.View>
|
||||
public void onEndLoadingAsync(boolean result, Exception exception) {
|
||||
getView().showNoItem(headerItems.isEmpty());
|
||||
getView().updateAdapterList(headerItems);
|
||||
|
||||
setSummaryAverages();
|
||||
getView().updateSummaryAdapterList(summarySubItems);
|
||||
|
||||
listener.onFragmentIsReady();
|
||||
}
|
||||
|
||||
private void setSummaryAverages() {
|
||||
getView().setSummaryAverages(
|
||||
getFormattedAverage(calculatedAverage),
|
||||
getFormattedAverage(predictedAverage),
|
||||
getFormattedAverage(finalAverage)
|
||||
);
|
||||
}
|
||||
|
||||
private String getFormattedAverage(float average) {
|
||||
if (-1.0f == average) {
|
||||
return "-- --";
|
||||
}
|
||||
|
||||
return String.format(Locale.FRANCE, "%.2f", average);
|
||||
}
|
||||
|
||||
private void reloadGrades() {
|
||||
loadingTask = new AbstractTask();
|
||||
loadingTask.setOnFirstLoadingListener(this);
|
||||
loadingTask.execute();
|
||||
}
|
||||
|
||||
private void cancelAsyncTasks() {
|
||||
if (refreshTask != null) {
|
||||
refreshTask.cancel(true);
|
||||
|
@ -21,7 +21,7 @@ import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.utils.GradeUtils;
|
||||
|
||||
public class GradesSubItem
|
||||
extends AbstractSectionableItem<GradesSubItem.SubItemViewHolder, GradeHeaderItem> {
|
||||
extends AbstractSectionableItem<GradesSubItem.SubItemViewHolder, GradesHeader> {
|
||||
|
||||
private Grade grade;
|
||||
|
||||
@ -29,7 +29,7 @@ public class GradesSubItem
|
||||
|
||||
private View subjectAlertImage;
|
||||
|
||||
GradesSubItem(GradeHeaderItem header, Grade grade) {
|
||||
GradesSubItem(GradesHeader header, Grade grade) {
|
||||
super(header);
|
||||
this.grade = grade;
|
||||
}
|
||||
@ -64,7 +64,7 @@ public class GradesSubItem
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.grade_subitem;
|
||||
return R.layout.grades_subitem;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,87 @@
|
||||
package io.github.wulkanowy.ui.main.grades;
|
||||
|
||||
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 java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.items.AbstractHeaderItem;
|
||||
import eu.davidea.flexibleadapter.items.IFlexible;
|
||||
import eu.davidea.viewholders.FlexibleViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
|
||||
class GradesSummaryHeader extends AbstractHeaderItem<GradesSummaryHeader.HeaderViewHolder> {
|
||||
|
||||
private Subject subject;
|
||||
|
||||
private String average;
|
||||
|
||||
GradesSummaryHeader(Subject subject, float average) {
|
||||
this.subject = subject;
|
||||
this.average = String.format(Locale.FRANCE, "%.2f", average);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GradesSummaryHeader that = (GradesSummaryHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(subject, that.subject)
|
||||
.append(average, that.average)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(subject)
|
||||
.append(average)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.grades_summary_header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
|
||||
return new HeaderViewHolder(view, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, HeaderViewHolder holder, int position, List<Object> payloads) {
|
||||
holder.onBind(subject, average);
|
||||
}
|
||||
|
||||
static class HeaderViewHolder extends FlexibleViewHolder {
|
||||
|
||||
@BindView(R.id.grades_summary_header_name)
|
||||
TextView name;
|
||||
|
||||
@BindView(R.id.grades_summary_header_average)
|
||||
TextView average;
|
||||
|
||||
HeaderViewHolder(View view, FlexibleAdapter adapter) {
|
||||
super(view, adapter);
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
|
||||
void onBind(Subject item, String value) {
|
||||
name.setText(item.getName());
|
||||
average.setText("-1,00".equals(value) ? "" : value);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package io.github.wulkanowy.ui.main.grades;
|
||||
|
||||
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.AbstractSectionableItem;
|
||||
import eu.davidea.flexibleadapter.items.IFlexible;
|
||||
import eu.davidea.viewholders.FlexibleViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
|
||||
public class GradesSummarySubItem
|
||||
extends AbstractSectionableItem<GradesSummarySubItem.SubItemViewHolder, GradesSummaryHeader> {
|
||||
|
||||
private Subject subject;
|
||||
|
||||
public GradesSummarySubItem(GradesSummaryHeader header, Subject subject) {
|
||||
super(header);
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GradesSummarySubItem that = (GradesSummarySubItem) 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.grades_summary_subitem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubItemViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
|
||||
return new SubItemViewHolder(view, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, SubItemViewHolder holder, int position, List<Object> payloads) {
|
||||
holder.onBind(subject);
|
||||
}
|
||||
|
||||
static class SubItemViewHolder extends FlexibleViewHolder {
|
||||
|
||||
@BindView(R.id.grades_summary_subitem_final_grade)
|
||||
TextView finalGrade;
|
||||
|
||||
@BindView(R.id.grades_summary_subitem_predicted_grade)
|
||||
TextView predictedGrade;
|
||||
|
||||
SubItemViewHolder(View view, FlexibleAdapter adapter) {
|
||||
super(view, adapter);
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
|
||||
void onBind(Subject item) {
|
||||
predictedGrade.setText(item.getPredictedRating());
|
||||
finalGrade.setText(item.getFinalRating());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package io.github.wulkanowy.ui.main.settings;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity;
|
||||
|
||||
import io.github.wulkanowy.BuildConfig;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.utils.AppConstant;
|
||||
|
||||
public class AboutScreen extends SettingsFragment {
|
||||
|
||||
public static final String SHARED_KEY_ABOUT_VERSION = "about_version";
|
||||
|
||||
public static final String SHARED_KEY_ABOUT_LICENSES = "about_osl";
|
||||
|
||||
public static final String SHARED_KEY_ABOUT_REPO = "about_repo";
|
||||
|
||||
private Preference.OnPreferenceClickListener onProgrammerListener = new Preference.OnPreferenceClickListener() {
|
||||
private int clicks = 0;
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Toast.makeText(getActivity(), getVersionToast(clicks++), Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getVersionToast(int click) {
|
||||
if (0 == click) {
|
||||
return R.string.about_programmer_step1;
|
||||
}
|
||||
|
||||
if (1 == click) {
|
||||
return R.string.about_programmer_step2;
|
||||
}
|
||||
|
||||
if (9 > click) {
|
||||
return R.string.about_programmer_step3;
|
||||
}
|
||||
|
||||
return R.string.about_programmer;
|
||||
}
|
||||
};
|
||||
|
||||
public AboutScreen() {
|
||||
// silence is golden
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
findPreference(SHARED_KEY_ABOUT_VERSION).setSummary(BuildConfig.VERSION_NAME);
|
||||
findPreference(SHARED_KEY_ABOUT_VERSION).setOnPreferenceClickListener(onProgrammerListener);
|
||||
findPreference(SHARED_KEY_ABOUT_REPO).setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(AppConstant.REPO_URL)));
|
||||
findPreference(SHARED_KEY_ABOUT_LICENSES).setIntent(new Intent(getActivity(), OssLicensesMenuActivity.class)
|
||||
.putExtra("title", getString(R.string.pref_about_osl)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle bundle, String rootKey) {
|
||||
setPreferencesFromResource(R.xml.preferences, rootKey);
|
||||
}
|
||||
}
|
@ -1,18 +1,25 @@
|
||||
package io.github.wulkanowy.ui.main.settings;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.AppCompatDelegate;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceFragmentCompat;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity;
|
||||
|
||||
import io.github.wulkanowy.BuildConfig;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.services.jobs.SyncJob;
|
||||
import io.github.wulkanowy.ui.main.MainActivity;
|
||||
import io.github.wulkanowy.utils.AppConstant;
|
||||
|
||||
public class SettingsFragment extends PreferenceFragmentCompat
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener,
|
||||
PreferenceFragmentCompat.OnPreferenceStartScreenCallback{
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
public static final String SHARED_KEY_START_TAB = "startup_tab";
|
||||
|
||||
@ -20,6 +27,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
|
||||
public static final String SHARED_KEY_ATTENDANCE_PRESENT = "attendance_present";
|
||||
|
||||
public static final String SHARED_KEY_THEME = "theme";
|
||||
|
||||
public static final String SHARED_KEY_SERVICES_ENABLE = "services_enable";
|
||||
|
||||
public static final String SHARED_KEY_NOTIFY_ENABLE = "notify_enable";
|
||||
@ -28,6 +37,42 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
|
||||
public static final String SHARED_KEY_SERVICES_MOBILE_DISABLED = "services_disable_mobile";
|
||||
|
||||
public static final String SHARED_KEY_ABOUT_VERSION = "about_version";
|
||||
|
||||
public static final String SHARED_KEY_ABOUT_LICENSES = "about_osl";
|
||||
|
||||
public static final String SHARED_KEY_ABOUT_REPO = "about_repo";
|
||||
|
||||
private boolean isStarted;
|
||||
|
||||
private boolean isVisible;
|
||||
|
||||
private Preference.OnPreferenceClickListener onProgrammerListener = new Preference.OnPreferenceClickListener() {
|
||||
private int clicks = 0;
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Toast.makeText(getActivity(), getVersionToast(clicks++), Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getVersionToast(int click) {
|
||||
if (0 == click) {
|
||||
return R.string.about_programmer_step1;
|
||||
}
|
||||
|
||||
if (1 == click) {
|
||||
return R.string.about_programmer_step2;
|
||||
}
|
||||
|
||||
if (9 > click) {
|
||||
return R.string.about_programmer_step3;
|
||||
}
|
||||
|
||||
return R.string.about_programmer;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
@ -36,6 +81,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
findPreference(SHARED_KEY_ABOUT_VERSION).setSummary(BuildConfig.VERSION_NAME);
|
||||
findPreference(SHARED_KEY_ABOUT_VERSION).setOnPreferenceClickListener(onProgrammerListener);
|
||||
findPreference(SHARED_KEY_ABOUT_REPO).setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(AppConstant.REPO_URL)));
|
||||
findPreference(SHARED_KEY_ABOUT_LICENSES).setIntent(new Intent(getActivity(), OssLicensesMenuActivity.class)
|
||||
.putExtra("title", getString(R.string.pref_about_osl)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -43,21 +94,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
|
||||
PreferenceScreen preferenceScreen) {
|
||||
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
|
||||
AboutScreen fragment = new AboutScreen();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey());
|
||||
fragment.setArguments(args);
|
||||
ft.add(R.id.main_activity_container, fragment, preferenceScreen.getKey());
|
||||
ft.addToBackStack(preferenceScreen.getKey());
|
||||
ft.commit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (key.equals(SHARED_KEY_SERVICES_ENABLE) || key.equals(SHARED_KEY_SERVICES_INTERVAL)
|
||||
@ -65,6 +101,20 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
launchServices(sharedPreferences.getBoolean(SHARED_KEY_SERVICES_ENABLE, true),
|
||||
sharedPreferences);
|
||||
}
|
||||
|
||||
if (key.equals(SHARED_KEY_THEME)) {
|
||||
setCurrentTheme(sharedPreferences);
|
||||
}
|
||||
}
|
||||
|
||||
private void setCurrentTheme(SharedPreferences sharedPreferences) {
|
||||
AppCompatDelegate.setDefaultNightMode(Integer.parseInt(sharedPreferences.getString(SHARED_KEY_THEME, "1")));
|
||||
getActivity().finish();
|
||||
startActivity(MainActivity
|
||||
.getStartIntent(getContext())
|
||||
.putExtra(MainActivity.EXTRA_CARD_ID_KEY, 4)
|
||||
);
|
||||
getActivity().overridePendingTransition(0, 0);
|
||||
}
|
||||
|
||||
private void launchServices(boolean start, SharedPreferences sharedPref) {
|
||||
@ -79,11 +129,25 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
}
|
||||
}
|
||||
|
||||
private void setTitle() {
|
||||
getActivity().setTitle(R.string.settings_text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMenuVisibility(boolean menuVisible) {
|
||||
super.setMenuVisibility(menuVisible);
|
||||
if (menuVisible) {
|
||||
getActivity().setTitle(R.string.settings_text);
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
isVisible = isVisibleToUser;
|
||||
if (isVisible && isStarted) {
|
||||
setTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
isStarted = true;
|
||||
if (isVisible) {
|
||||
setTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,4 +164,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
getPreferenceScreen().getSharedPreferences()
|
||||
.unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
isStarted = false;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.main.timetable;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -14,7 +14,6 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindColor;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
@ -23,13 +22,14 @@ import eu.davidea.flexibleadapter.items.IFlexible;
|
||||
import eu.davidea.viewholders.ExpandableViewHolder;
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Day;
|
||||
import io.github.wulkanowy.utils.CommonUtils;
|
||||
|
||||
public class TimetableHeaderItem
|
||||
extends AbstractExpandableHeaderItem<TimetableHeaderItem.HeaderViewHolder, TimetableSubItem> {
|
||||
public class TimetableHeader
|
||||
extends AbstractExpandableHeaderItem<TimetableHeader.HeaderViewHolder, TimetableSubItem> {
|
||||
|
||||
private Day day;
|
||||
|
||||
TimetableHeaderItem(Day day) {
|
||||
TimetableHeader(Day day) {
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ public class TimetableHeaderItem
|
||||
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
TimetableHeaderItem that = (TimetableHeaderItem) o;
|
||||
TimetableHeader that = (TimetableHeader) o;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(day, that.day)
|
||||
@ -83,15 +83,6 @@ public class TimetableHeaderItem
|
||||
@BindView(R.id.timetable_header_free_name)
|
||||
TextView freeName;
|
||||
|
||||
@BindColor(R.color.secondary_text)
|
||||
int secondaryColor;
|
||||
|
||||
@BindColor(R.color.free_day)
|
||||
int backgroundFreeDay;
|
||||
|
||||
@BindColor(android.R.color.black)
|
||||
int black;
|
||||
|
||||
private Context context;
|
||||
|
||||
HeaderViewHolder(View view, FlexibleAdapter adapter) {
|
||||
@ -112,13 +103,13 @@ public class TimetableHeaderItem
|
||||
|
||||
private void setInactiveHeader(boolean inactive) {
|
||||
((FrameLayout) getContentView()).setForeground(inactive ? null : getSelectableDrawable());
|
||||
dayName.setTextColor(inactive ? secondaryColor : black);
|
||||
dayName.setTextColor(CommonUtils.getThemeAttrColor(context,
|
||||
inactive ? android.R.attr.textColorSecondary : android.R.attr.textColorPrimary));
|
||||
|
||||
if (inactive) {
|
||||
getContentView().setBackgroundColor(backgroundFreeDay);
|
||||
getContentView().setBackgroundColor(CommonUtils.getThemeAttrColor(context, R.attr.colorControlHighlight));
|
||||
} else {
|
||||
getContentView().setBackgroundDrawable(context.getResources()
|
||||
.getDrawable(R.drawable.ic_border));
|
||||
getContentView().setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_border));
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,11 @@ import io.github.wulkanowy.ui.main.timetable.TimetableDialogFragment;
|
||||
|
||||
|
||||
public class TimetableSubItem
|
||||
extends AbstractSectionableItem<TimetableSubItem.SubItemViewHolder, TimetableHeaderItem> {
|
||||
extends AbstractSectionableItem<TimetableSubItem.SubItemViewHolder, TimetableHeader> {
|
||||
|
||||
private TimetableLesson lesson;
|
||||
|
||||
TimetableSubItem(TimetableHeaderItem header, TimetableLesson lesson) {
|
||||
TimetableSubItem(TimetableHeader header, TimetableLesson lesson) {
|
||||
super(header);
|
||||
this.lesson = lesson;
|
||||
}
|
||||
|
@ -8,7 +8,9 @@ public interface TimetableTabContract {
|
||||
|
||||
interface View extends BaseContract.View {
|
||||
|
||||
void updateAdapterList(List<TimetableHeaderItem> headerItems);
|
||||
void updateAdapterList(List<TimetableHeader> headerItems);
|
||||
|
||||
void expandItem(int item);
|
||||
|
||||
void onRefreshSuccess();
|
||||
|
||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.main.timetable.tab;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
@ -45,7 +44,7 @@ public class TimetableTabFragment extends BaseFragment implements TimetableTabCo
|
||||
TimetableTabContract.Presenter presenter;
|
||||
|
||||
@Inject
|
||||
FlexibleAdapter<TimetableHeaderItem> adapter;
|
||||
FlexibleAdapter<TimetableHeader> adapter;
|
||||
|
||||
private boolean isFragmentVisible = false;
|
||||
|
||||
@ -87,10 +86,16 @@ public class TimetableTabFragment extends BaseFragment implements TimetableTabCo
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAdapterList(List<TimetableHeaderItem> headerItems) {
|
||||
public void updateAdapterList(List<TimetableHeader> headerItems) {
|
||||
adapter.updateDataSet(headerItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expandItem(int position) {
|
||||
adapter.expand(adapter.getItem(position), true);
|
||||
recyclerView.scrollToPosition(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMenuVisibility(boolean menuVisible) {
|
||||
super.setMenuVisibility(menuVisible);
|
||||
|
@ -15,7 +15,7 @@ public abstract class TimetableTabModule {
|
||||
|
||||
@PerChildFragment
|
||||
@Provides
|
||||
static FlexibleAdapter<TimetableHeaderItem> provideTimetableAdapter() {
|
||||
static FlexibleAdapter<TimetableHeader> provideTimetableAdapter() {
|
||||
return new FlexibleAdapter<>(null);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package io.github.wulkanowy.ui.main.timetable.tab;
|
||||
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.threeten.bp.LocalDate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -13,7 +14,9 @@ import io.github.wulkanowy.data.db.dao.entities.Day;
|
||||
import io.github.wulkanowy.data.db.dao.entities.TimetableLesson;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Week;
|
||||
import io.github.wulkanowy.ui.base.BasePresenter;
|
||||
import io.github.wulkanowy.utils.AppConstant;
|
||||
import io.github.wulkanowy.utils.FabricUtils;
|
||||
import io.github.wulkanowy.utils.TimeUtils;
|
||||
import io.github.wulkanowy.utils.async.AbstractTask;
|
||||
import io.github.wulkanowy.utils.async.AsyncListeners;
|
||||
|
||||
@ -25,7 +28,7 @@ public class TimetableTabPresenter extends BasePresenter<TimetableTabContract.Vi
|
||||
|
||||
private AbstractTask loadingTask;
|
||||
|
||||
private List<TimetableHeaderItem> headerItems = new ArrayList<>();
|
||||
private List<TimetableHeader> headerItems = new ArrayList<>();
|
||||
|
||||
private String date;
|
||||
|
||||
@ -48,8 +51,6 @@ public class TimetableTabPresenter extends BasePresenter<TimetableTabContract.Vi
|
||||
@Override
|
||||
public void onFragmentActivated(boolean isSelected) {
|
||||
if (!isFirstSight && isSelected && isViewAttached()) {
|
||||
isFirstSight = true;
|
||||
|
||||
loadingTask = new AbstractTask();
|
||||
loadingTask.setOnFirstLoadingListener(this);
|
||||
loadingTask.execute();
|
||||
@ -116,7 +117,7 @@ public class TimetableTabPresenter extends BasePresenter<TimetableTabContract.Vi
|
||||
|
||||
for (Day day : dayList) {
|
||||
day.resetTimetableLessons();
|
||||
TimetableHeaderItem headerItem = new TimetableHeaderItem(day);
|
||||
TimetableHeader headerItem = new TimetableHeader(day);
|
||||
|
||||
if (isFreeWeek) {
|
||||
isFreeWeek = day.getFreeDay();
|
||||
@ -148,15 +149,24 @@ public class TimetableTabPresenter extends BasePresenter<TimetableTabContract.Vi
|
||||
|
||||
@Override
|
||||
public void onEndLoadingAsync(boolean result, Exception exception) {
|
||||
getView().showNoItem(headerItems.isEmpty());
|
||||
getView().updateAdapterList(headerItems);
|
||||
|
||||
if (headerItems.isEmpty()) {
|
||||
getView().showNoItem(true);
|
||||
getView().setFreeWeekName(freeWeekName);
|
||||
getView().updateAdapterList(null);
|
||||
} else {
|
||||
getView().updateAdapterList(headerItems);
|
||||
getView().showNoItem(false);
|
||||
expandCurrentDayHeader();
|
||||
}
|
||||
getView().showProgressBar(false);
|
||||
isFirstSight = true;
|
||||
}
|
||||
|
||||
private void expandCurrentDayHeader() {
|
||||
LocalDate monday = TimeUtils.getParsedDate(date, AppConstant.DATE_PATTERN);
|
||||
|
||||
if (TimeUtils.isDateInWeek(monday, LocalDate.now()) && !isFirstSight) {
|
||||
getView().expandItem(LocalDate.now().getDayOfWeek().getValue() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,10 +1,10 @@
|
||||
package io.github.wulkanowy.ui.splash;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatDelegate;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.github.wulkanowy.services.jobs.SyncJob;
|
||||
import io.github.wulkanowy.services.notifies.NotificationService;
|
||||
import io.github.wulkanowy.ui.base.BaseActivity;
|
||||
import io.github.wulkanowy.ui.login.LoginActivity;
|
||||
@ -39,6 +39,10 @@ public class SplashActivity extends BaseActivity implements SplashContract.View
|
||||
finish();
|
||||
}
|
||||
|
||||
public void setCurrentThemeMode(int mode) {
|
||||
AppCompatDelegate.setDefaultNightMode(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelNotifications() {
|
||||
new NotificationService(getApplicationContext()).cancelAll();
|
||||
|
@ -11,6 +11,8 @@ public interface SplashContract {
|
||||
void openMainActivity();
|
||||
|
||||
void cancelNotifications();
|
||||
|
||||
void setCurrentThemeMode(int mode);
|
||||
}
|
||||
|
||||
interface Presenter extends BaseContract.Presenter<View> {
|
||||
|
@ -18,6 +18,7 @@ public class SplashPresenter extends BasePresenter<SplashContract.View>
|
||||
@Override
|
||||
public void attachView(@NonNull SplashContract.View view) {
|
||||
super.attachView(view);
|
||||
getView().setCurrentThemeMode(getRepository().getSharedRepo().getCurrentTheme());
|
||||
getView().cancelNotifications();
|
||||
|
||||
if (getRepository().getSharedRepo().isUserLoggedIn()) {
|
||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.widgets;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Paint;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.RemoteViews;
|
||||
@ -75,13 +76,21 @@ public class TimetableWidgetFactory implements RemoteViewsService.RemoteViewsFac
|
||||
views.setTextViewText(R.id.timetable_widget_item_room, getRoomText(position));
|
||||
|
||||
if (!getDescriptionText(position).isEmpty()) {
|
||||
views.setViewVisibility(R.id.timetable_widget_item_description, View.VISIBLE);
|
||||
views.setTextViewText(R.id.timetable_widget_item_description, getDescriptionText(position));
|
||||
} else {
|
||||
views.setViewVisibility(R.id.timetable_widget_item_description, View.GONE);
|
||||
}
|
||||
|
||||
views.setOnClickFillInIntent(R.id.timetable_widget_item_container, new Intent());
|
||||
if (lessonList.get(position).getMovedOrCanceled()) {
|
||||
views.setInt(R.id.timetable_widget_item_subject, "setPaintFlags",
|
||||
Paint.STRIKE_THRU_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
|
||||
} else {
|
||||
views.setInt(R.id.timetable_widget_item_subject, "setPaintFlags",
|
||||
Paint.ANTI_ALIAS_FLAG);
|
||||
}
|
||||
|
||||
views.setOnClickFillInIntent(R.id.timetable_widget_item_container, new Intent());
|
||||
return views;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
package io.github.wulkanowy.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.AttrRes;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
@ -37,4 +41,14 @@ public final class CommonUtils {
|
||||
return R.string.noColor_text;
|
||||
}
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
public static int getThemeAttrColor(Context context, @AttrRes int colorAttr) {
|
||||
final TypedArray array = context.obtainStyledAttributes(null, new int[]{colorAttr});
|
||||
try {
|
||||
return array.getColor(0, 0);
|
||||
} finally {
|
||||
array.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ public final class DataObjectConverter {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static List<Student> studentsToStudentEntities(List<io.github.wulkanowy.api.Student> students, Long symbolId) {
|
||||
public static List<Student> studentsToStudentEntities(List<io.github.wulkanowy.api.generic.Student> students, Long symbolId) {
|
||||
List<Student> studentList = new ArrayList<>();
|
||||
|
||||
for (io.github.wulkanowy.api.Student student : students) {
|
||||
for (io.github.wulkanowy.api.generic.Student student : students) {
|
||||
studentList.add(new Student()
|
||||
.setName(student.getName())
|
||||
.setCurrent(student.isCurrent())
|
||||
@ -36,10 +36,10 @@ public final class DataObjectConverter {
|
||||
return studentList;
|
||||
}
|
||||
|
||||
public static List<Diary> diariesToDiaryEntities(List<io.github.wulkanowy.api.Diary> diaryList, Long studentId) {
|
||||
public static List<Diary> diariesToDiaryEntities(List<io.github.wulkanowy.api.generic.Diary> diaryList, Long studentId) {
|
||||
List<Diary> diaryEntityList = new ArrayList<>();
|
||||
|
||||
for (io.github.wulkanowy.api.Diary diary : diaryList) {
|
||||
for (io.github.wulkanowy.api.generic.Diary diary : diaryList) {
|
||||
diaryEntityList.add(new Diary()
|
||||
.setStudentId(studentId)
|
||||
.setValue(diary.getId())
|
||||
@ -50,10 +50,10 @@ public final class DataObjectConverter {
|
||||
return diaryEntityList;
|
||||
}
|
||||
|
||||
public static List<Semester> semestersToSemesterEntities(List<io.github.wulkanowy.api.Semester> semesters, long diaryId) {
|
||||
public static List<Semester> semestersToSemesterEntities(List<io.github.wulkanowy.api.generic.Semester> semesters, long diaryId) {
|
||||
List<Semester> semesterList = new ArrayList<>();
|
||||
|
||||
for (io.github.wulkanowy.api.Semester semester : semesters) {
|
||||
for (io.github.wulkanowy.api.generic.Semester semester : semesters) {
|
||||
semesterList.add(new Semester()
|
||||
.setDiaryId(diaryId)
|
||||
.setName(semester.getName())
|
||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.utils;
|
||||
|
||||
import com.crashlytics.android.answers.Answers;
|
||||
import com.crashlytics.android.answers.CustomEvent;
|
||||
import com.crashlytics.android.answers.LoginEvent;
|
||||
import com.crashlytics.android.answers.SignUpEvent;
|
||||
|
||||
public final class FabricUtils {
|
||||
@ -10,17 +11,26 @@ public final class FabricUtils {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static void logRegister(boolean result, String symbol) {
|
||||
public static void logLogin(String method, boolean result) {
|
||||
Answers.getInstance().logLogin(new LoginEvent()
|
||||
.putMethod(method)
|
||||
.putSuccess(result)
|
||||
);
|
||||
}
|
||||
|
||||
public static void logRegister(boolean result, String symbol, String message) {
|
||||
Answers.getInstance().logSignUp(new SignUpEvent()
|
||||
.putMethod("Login activity")
|
||||
.putSuccess(result)
|
||||
.putCustomAttribute("symbol", symbol));
|
||||
.putCustomAttribute("symbol", symbol)
|
||||
.putCustomAttribute("message", message)
|
||||
);
|
||||
}
|
||||
|
||||
public static void logRefresh(String name, boolean result, String date) {
|
||||
Answers.getInstance().logCustom(
|
||||
new CustomEvent(name + " refresh")
|
||||
.putCustomAttribute("Success", result ? 1 : 0)
|
||||
.putCustomAttribute("Success", result ? "true" : "false")
|
||||
.putCustomAttribute("Date", date)
|
||||
);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
import io.github.wulkanowy.R;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||
import io.github.wulkanowy.data.db.dao.entities.Subject;
|
||||
|
||||
public final class GradeUtils {
|
||||
|
||||
@ -16,53 +17,33 @@ public final class GradeUtils {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static float calculate(List<Grade> gradeList) {
|
||||
public static float calculateWeightedAverage(List<Grade> gradeList) {
|
||||
|
||||
float counter = 0f;
|
||||
float denominator = 0f;
|
||||
|
||||
for (Grade grade : gradeList) {
|
||||
int integerWeight = getIntegerForWeightOfGrade(grade.getWeight());
|
||||
float floatValue = getMathematicalValueOfGrade(grade.getValue());
|
||||
int weight = getWeightValue(grade.getWeight());
|
||||
float value = getWeightedGradeValue(grade.getValue());
|
||||
|
||||
if (floatValue != -1f) {
|
||||
counter += floatValue * integerWeight;
|
||||
denominator += integerWeight;
|
||||
if (value != -1.0f) {
|
||||
counter += value * weight;
|
||||
denominator += weight;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter == 0f) {
|
||||
return -1f;
|
||||
} else {
|
||||
return counter / denominator;
|
||||
return -1.0f;
|
||||
}
|
||||
return counter / denominator;
|
||||
}
|
||||
|
||||
private static float getMathematicalValueOfGrade(String valueOfGrade) {
|
||||
if (valueOfGrade.matches("[-|+|=]{0,2}[0-6]")
|
||||
|| valueOfGrade.matches("[0-6][-|+|=]{0,2}")) {
|
||||
if (valueOfGrade.matches("[-][0-6]")
|
||||
|| valueOfGrade.matches("[0-6][-]")) {
|
||||
String replacedValue = valueOfGrade.replaceAll("[-]", "");
|
||||
return Float.valueOf(replacedValue) - 0.33f;
|
||||
} else if (valueOfGrade.matches("[+][0-6]")
|
||||
|| valueOfGrade.matches("[0-6][+]")) {
|
||||
String replacedValue = valueOfGrade.replaceAll("[+]", "");
|
||||
return Float.valueOf((replacedValue)) + 0.33f;
|
||||
} else if (valueOfGrade.matches("[-|=]{1,2}[0-6]")
|
||||
|| valueOfGrade.matches("[0-6][-|=]{1,2}")) {
|
||||
String replacedValue = valueOfGrade.replaceAll("[-|=]{1,2}", "");
|
||||
return Float.valueOf((replacedValue)) - 0.5f;
|
||||
} else {
|
||||
return Float.valueOf(valueOfGrade);
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
public static float calculateSubjectsAverage(List<Subject> subjectList, boolean usePredicted) {
|
||||
return calculateSubjectsAverage(subjectList, usePredicted, false);
|
||||
}
|
||||
|
||||
private static int getIntegerForWeightOfGrade(String weightOfGrade) {
|
||||
return Integer.valueOf(weightOfGrade.substring(0, weightOfGrade.length() - 3));
|
||||
public static float calculateDetailedSubjectsAverage(List<Subject> subjectList) {
|
||||
return calculateSubjectsAverage(subjectList, false, true);
|
||||
}
|
||||
|
||||
public static int getValueColor(String value) {
|
||||
@ -93,4 +74,80 @@ public final class GradeUtils {
|
||||
return R.color.default_grade;
|
||||
}
|
||||
}
|
||||
|
||||
private static float calculateSubjectsAverage(List<Subject> subjectList, boolean usePredicted, boolean useSubjectsAverages) {
|
||||
float counter = 0f;
|
||||
float denominator = 0f;
|
||||
|
||||
for (Subject subject : subjectList) {
|
||||
float value;
|
||||
|
||||
if (useSubjectsAverages) {
|
||||
value = calculateWeightedAverage(subject.getGradeList());
|
||||
} else {
|
||||
value = getGradeValue(usePredicted ? subject.getPredictedRating() : subject.getFinalRating());
|
||||
}
|
||||
|
||||
if (value != -1.0f) {
|
||||
counter += Math.round(value);
|
||||
denominator++;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter == 0) {
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
return counter / denominator;
|
||||
}
|
||||
|
||||
private static float getGradeValue(String grade) {
|
||||
if (validGradePattern.matcher(grade).matches()) {
|
||||
return getWeightedGradeValue(grade);
|
||||
}
|
||||
|
||||
return getVerbalGradeValue(grade);
|
||||
}
|
||||
|
||||
private static float getVerbalGradeValue(String grade) {
|
||||
switch (grade) {
|
||||
case "celujący":
|
||||
return 6f;
|
||||
case "bardzo dobry":
|
||||
return 5f;
|
||||
case "dobry":
|
||||
return 4f;
|
||||
case "dostateczny":
|
||||
return 3f;
|
||||
case "dopuszczający":
|
||||
return 2f;
|
||||
case "niedostateczny":
|
||||
return 1f;
|
||||
default:
|
||||
return -1f;
|
||||
}
|
||||
}
|
||||
|
||||
private static float getWeightedGradeValue(String value) {
|
||||
if (validGradePattern.matcher(value).matches()) {
|
||||
if (value.matches("[-][0-6]") || value.matches("[0-6][-]")) {
|
||||
String replacedValue = value.replaceAll("[-]", "");
|
||||
return Float.valueOf(replacedValue) - 0.33f;
|
||||
} else if (value.matches("[+][0-6]") || value.matches("[0-6][+]")) {
|
||||
String replacedValue = value.replaceAll("[+]", "");
|
||||
return Float.valueOf((replacedValue)) + 0.33f;
|
||||
} else if (value.matches("[-|=]{1,2}[0-6]") || value.matches("[0-6][-|=]{1,2}")) {
|
||||
String replacedValue = value.replaceAll("[-|=]{1,2}", "");
|
||||
return Float.valueOf((replacedValue)) - 0.5f;
|
||||
} else {
|
||||
return Float.valueOf(value);
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getWeightValue(String weightOfGrade) {
|
||||
return Integer.valueOf(weightOfGrade.substring(0, weightOfGrade.length() - 3));
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
package io.github.wulkanowy.utils;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public final class LogUtils {
|
||||
|
||||
private LogUtils() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static void debug(String message) {
|
||||
Log.d(AppConstant.APP_NAME, message);
|
||||
}
|
||||
|
||||
public static void error(String message, Throwable throwable) {
|
||||
Log.e(AppConstant.APP_NAME, message, throwable);
|
||||
}
|
||||
|
||||
public static void error(String message) {
|
||||
Log.e(AppConstant.APP_NAME, message);
|
||||
}
|
||||
|
||||
public static void info(String message) {
|
||||
Log.i(AppConstant.APP_NAME, message);
|
||||
}
|
||||
}
|
47
app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.java
Normal file
47
app/src/main/java/io/github/wulkanowy/utils/LoggerUtils.java
Normal file
@ -0,0 +1,47 @@
|
||||
package io.github.wulkanowy.utils;
|
||||
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
public final class LoggerUtils {
|
||||
|
||||
public static class CrashlyticsTree extends Timber.Tree {
|
||||
|
||||
@Override
|
||||
protected void log(int priority, @Nullable String tag, @Nullable String message, @Nullable Throwable t) {
|
||||
Crashlytics.setInt("priority", priority);
|
||||
Crashlytics.setString("tag", tag);
|
||||
|
||||
if (t == null) {
|
||||
Crashlytics.log(message);
|
||||
} else {
|
||||
Crashlytics.setString("message", message);
|
||||
Crashlytics.logException(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class DebugLogTree extends Timber.DebugTree {
|
||||
|
||||
@Override
|
||||
protected void log(int priority, String tag, @NonNull String message, Throwable t) {
|
||||
if ("HUAWEI".equals(Build.MANUFACTURER) || "samsung".equals(Build.MANUFACTURER)) {
|
||||
if (priority == Log.VERBOSE || priority == Log.DEBUG || priority == Log.INFO) {
|
||||
priority = Log.ERROR;
|
||||
}
|
||||
}
|
||||
super.log(priority, AppConstant.APP_NAME, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String createStackElementTag(@NonNull StackTraceElement element) {
|
||||
return super.createStackElementTag(element) + " - " + element.getLineNumber();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,48 +4,19 @@ import org.threeten.bp.DayOfWeek;
|
||||
import org.threeten.bp.LocalDate;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public final class TimeUtils {
|
||||
|
||||
private static final long TICKS_AT_EPOCH = 621355968000000000L;
|
||||
|
||||
private static final long TICKS_PER_MILLISECOND = 10000;
|
||||
|
||||
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(AppConstant.DATE_PATTERN);
|
||||
|
||||
private TimeUtils() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static long getNetTicks(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
|
||||
return (calendar.getTimeInMillis() * TICKS_PER_MILLISECOND) + TICKS_AT_EPOCH;
|
||||
}
|
||||
|
||||
public static long getNetTicks(String dateString) throws ParseException {
|
||||
return getNetTicks(dateString, AppConstant.DATE_PATTERN);
|
||||
}
|
||||
|
||||
public static long getNetTicks(String dateString, String dateFormat) throws ParseException {
|
||||
SimpleDateFormat format = new SimpleDateFormat(dateFormat, Locale.ROOT);
|
||||
format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
Date dateObject = format.parse(dateString);
|
||||
|
||||
return getNetTicks(dateObject);
|
||||
}
|
||||
|
||||
public static Date getDate(long netTicks) {
|
||||
return new Date((netTicks - TICKS_AT_EPOCH) / TICKS_PER_MILLISECOND);
|
||||
public static LocalDate getParsedDate(String dateString, String dateFormat) {
|
||||
return LocalDate.parse(dateString, DateTimeFormatter.ofPattern(dateFormat));
|
||||
}
|
||||
|
||||
public static List<String> getMondaysFromCurrentSchoolYear() {
|
||||
@ -102,4 +73,9 @@ public final class TimeUtils {
|
||||
LocalDate current = LocalDate.now();
|
||||
return nextDay ? current.plusDays(1).format(formatter) : current.format(formatter);
|
||||
}
|
||||
|
||||
public static boolean isDateInWeek(LocalDate firstWeekDay, LocalDate date) {
|
||||
return date.isAfter(firstWeekDay.minusDays(1)) && date.isBefore(firstWeekDay.plusDays(5));
|
||||
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user