diff --git a/api/src/main/java/io/github/wulkanowy/api/exams/ExamsWeek.java b/api/src/main/java/io/github/wulkanowy/api/exams/ExamsWeek.java index 3dd056d9..50aa48e7 100644 --- a/api/src/main/java/io/github/wulkanowy/api/exams/ExamsWeek.java +++ b/api/src/main/java/io/github/wulkanowy/api/exams/ExamsWeek.java @@ -1,12 +1,17 @@ package io.github.wulkanowy.api.exams; +import org.apache.commons.lang3.StringUtils; import org.jsoup.nodes.Document; 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; @@ -22,11 +27,11 @@ public class ExamsWeek { this.snp = snp; } - public Week getCurrent() throws IOException, VulcanException { + public Week getCurrent() throws IOException, VulcanException, ParseException { return getWeek("", true); } - public Week getWeek(String tick, final boolean onlyNotEmpty) throws IOException, VulcanException { + public Week getWeek(String tick, final boolean onlyNotEmpty) throws IOException, VulcanException, ParseException { Document examsPage = snp.getSnPPageDocument(EXAMS_PAGE_URL + tick); Elements examsDays = examsPage.select(".mainContainer > div:not(.navigation)"); @@ -41,7 +46,9 @@ public class ExamsWeek { } if (null != dayHeading) { - day.setDate(dayHeading.text().split(", ")[1]); + String[] dateHeader = dayHeading.text().split(", "); + day.setDayName(StringUtils.capitalize(dateHeader[0])); + day.setDate(getFormattedDate(dateHeader[1])); } Elements exams = item.select("article"); @@ -58,8 +65,17 @@ public class ExamsWeek { days.add(day); } + return new Week() - .setStartDayDate(examsDays.select("h2").first().text().split(" ")[1]) + .setStartDayDate(getFormattedDate(examsPage.select(".mainContainer > h2") + .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); + } } diff --git a/api/src/main/java/io/github/wulkanowy/api/generic/Day.java b/api/src/main/java/io/github/wulkanowy/api/generic/Day.java index 6bf26c04..5b9086a3 100644 --- a/api/src/main/java/io/github/wulkanowy/api/generic/Day.java +++ b/api/src/main/java/io/github/wulkanowy/api/generic/Day.java @@ -11,10 +11,6 @@ public class Day { private String dayName = ""; - private boolean isFreeDay = false; - - private String freeDayName = ""; - public Lesson getLesson(int index) { return lessons.get(index); } @@ -44,20 +40,4 @@ public class Day { public void setDayName(String dayName) { this.dayName = dayName; } - - public boolean isFreeDay() { - return isFreeDay; - } - - public void setFreeDay(boolean freeDay) { - isFreeDay = freeDay; - } - - public String getFreeDayName() { - return freeDayName; - } - - public void setFreeDayName(String freeDayName) { - this.freeDayName = freeDayName; - } } diff --git a/api/src/main/java/io/github/wulkanowy/api/timetable/Timetable.java b/api/src/main/java/io/github/wulkanowy/api/timetable/Timetable.java index 5cb623b4..b5c7efc2 100644 --- a/api/src/main/java/io/github/wulkanowy/api/timetable/Timetable.java +++ b/api/src/main/java/io/github/wulkanowy/api/timetable/Timetable.java @@ -14,7 +14,6 @@ import java.util.Locale; import io.github.wulkanowy.api.SnP; import io.github.wulkanowy.api.VulcanException; -import io.github.wulkanowy.api.generic.Day; import io.github.wulkanowy.api.generic.Lesson; import io.github.wulkanowy.api.generic.Week; @@ -28,25 +27,25 @@ public class Timetable { this.snp = snp; } - public Week getWeekTable() throws IOException, ParseException, VulcanException { + public Week getWeekTable() throws IOException, ParseException, VulcanException { return getWeekTable(""); } - public Week getWeekTable(final String tick) throws IOException, ParseException, VulcanException { + public Week getWeekTable(final String tick) throws IOException, ParseException, VulcanException { Element table = snp.getSnPPageDocument(TIMETABLE_PAGE_URL + tick) .select(".mainContainer .presentData").first(); - List days = getDays(table.select("thead th")); + List days = getDays(table.select("thead th")); setLessonToDays(table, days); - return new Week() + return new Week() .setStartDayDate(days.get(0).getDate()) .setDays(days); } - private List getDays(Elements tableHeaderCells) throws ParseException { - List days = new ArrayList<>(); + private List getDays(Elements tableHeaderCells) throws ParseException { + List days = new ArrayList<>(); for (int i = 2; i < 7; i++) { String[] dayHeaderCell = tableHeaderCells.get(i).html().split("
"); @@ -55,7 +54,7 @@ public class Timetable { Date d = sdf.parse(dayHeaderCell[1].trim()); sdf.applyPattern("yyyy-MM-dd"); - Day day = new Day(); + TimetableDay day = new TimetableDay(); day.setDayName(dayHeaderCell[0]); day.setDate(sdf.format(d)); @@ -70,7 +69,7 @@ public class Timetable { return days; } - private void setLessonToDays(Element table, List days) { + private void setLessonToDays(Element table, List days) { for (Element row : table.select("tbody tr")) { Elements hours = row.select("td"); diff --git a/api/src/main/java/io/github/wulkanowy/api/timetable/TimetableDay.java b/api/src/main/java/io/github/wulkanowy/api/timetable/TimetableDay.java new file mode 100644 index 00000000..1aa29de2 --- /dev/null +++ b/api/src/main/java/io/github/wulkanowy/api/timetable/TimetableDay.java @@ -0,0 +1,26 @@ +package io.github.wulkanowy.api.timetable; + +import io.github.wulkanowy.api.generic.Day; + +public class TimetableDay extends Day { + + private boolean isFreeDay = false; + + private String freeDayName = ""; + + public boolean isFreeDay() { + return isFreeDay; + } + + public void setFreeDay(boolean freeDay) { + isFreeDay = freeDay; + } + + public String getFreeDayName() { + return freeDayName; + } + + public void setFreeDayName(String freeDayName) { + this.freeDayName = freeDayName; + } +} diff --git a/api/src/test/java/io/github/wulkanowy/api/exams/ExamsWeekTest.java b/api/src/test/java/io/github/wulkanowy/api/exams/ExamsWeekTest.java index 9b57ddd6..14b55e8d 100644 --- a/api/src/test/java/io/github/wulkanowy/api/exams/ExamsWeekTest.java +++ b/api/src/test/java/io/github/wulkanowy/api/exams/ExamsWeekTest.java @@ -12,20 +12,25 @@ public class ExamsWeekTest extends StudentAndParentTestCase { private ExamsWeek onePerDay; + private ExamsWeek empty; + @Before public void getCurrent() throws Exception { onePerDay = new ExamsWeek(getSnp("Sprawdziany-one-per-day.html")); + empty = new ExamsWeek(getSnp("Sprawdziany-empty.html")); } @Test public void getWeekTest() throws Exception { - Assert.assertEquals("23.10.2017", onePerDay.getCurrent().getStartDayDate()); + Assert.assertEquals("2017-10-23", onePerDay.getCurrent().getStartDayDate()); + Assert.assertEquals("2018-04-30", empty.getCurrent().getStartDayDate()); } @Test public void getDaysListTest() throws Exception { Assert.assertEquals(3, onePerDay.getCurrent().getDays().size()); Assert.assertEquals(7, onePerDay.getWeek("", false).getDays().size()); + Assert.assertEquals(0, empty.getCurrent().getDays().size()); } @Test @@ -45,9 +50,18 @@ public class ExamsWeekTest extends StudentAndParentTestCase { public void getDayDateTest() throws Exception { List dayList = onePerDay.getCurrent().getDays(); - Assert.assertEquals("23.10.2017", dayList.get(0).getDate()); - Assert.assertEquals("24.10.2017", dayList.get(1).getDate()); - Assert.assertEquals("27.10.2017", dayList.get(2).getDate()); + Assert.assertEquals("2017-10-23", dayList.get(0).getDate()); + Assert.assertEquals("2017-10-24", dayList.get(1).getDate()); + Assert.assertEquals("2017-10-27", dayList.get(2).getDate()); + } + + @Test + public void getDayNameTest() throws Exception { + List dayList = onePerDay.getCurrent().getDays(); + + Assert.assertEquals("Poniedziałek", dayList.get(0).getDayName()); + Assert.assertEquals("Wtorek", dayList.get(1).getDayName()); + Assert.assertEquals("Piątek", dayList.get(2).getDayName()); } @Test diff --git a/api/src/test/resources/io/github/wulkanowy/api/exams/Sprawdziany-empty.html b/api/src/test/resources/io/github/wulkanowy/api/exams/Sprawdziany-empty.html new file mode 100644 index 00000000..bf1032b4 --- /dev/null +++ b/api/src/test/resources/io/github/wulkanowy/api/exams/Sprawdziany-empty.html @@ -0,0 +1,19 @@ + + + + + Witryna ucznia i rodzica – Terminarz sprawdzianów + + +
+

Sprawdziany

+

Tydzień 30.04.2018 - 06.05.2018

+

Nie zaplanowano żadnych sprawdzianów na wybrany tydzień

+ +
+
wersja: 17.09.0009.26859
+ + diff --git a/app/build.gradle b/app/build.gradle index d66f6a9c..3850e793 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,7 +62,7 @@ android { } greendao { - schemaVersion 24 + schemaVersion 25 generateTests = true } diff --git a/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/ExamTest.java b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/ExamTest.java new file mode 100644 index 00000000..271e811f --- /dev/null +++ b/app/src/androidTest/java/io/github/wulkanowy/data/db/dao/entities/ExamTest.java @@ -0,0 +1,18 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.test.AbstractDaoTestLongPk; + +public class ExamTest extends AbstractDaoTestLongPk { + + public ExamTest() { + super(ExamDao.class); + } + + @Override + protected Exam createEntity(Long key) { + Exam entity = new Exam(); + entity.setId(key); + return entity; + } + +} diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbContract.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbContract.java index f4ce6fb7..38115cc4 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbContract.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbContract.java @@ -10,6 +10,8 @@ public interface DbContract { Week getWeek(String date); + Week getWeek(long diaryId, String date); + List getSubjectList(int semesterName); List getNewGrades(int semesterName); diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java index e3dc8b77..b1f92f2a 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbHelper.java @@ -17,7 +17,7 @@ import javax.inject.Singleton; import io.github.wulkanowy.api.Vulcan; import io.github.wulkanowy.data.db.dao.entities.DaoMaster; import io.github.wulkanowy.data.db.dao.migrations.Migration23; -import io.github.wulkanowy.data.db.dao.migrations.Migration24; +import io.github.wulkanowy.data.db.dao.migrations.Migration25; import io.github.wulkanowy.data.db.shared.SharedPrefContract; import io.github.wulkanowy.di.annotations.ApplicationContext; import io.github.wulkanowy.di.annotations.DatabaseInfo; @@ -66,6 +66,7 @@ public class DbHelper extends DaoMaster.OpenHelper { } private void recreateDatabase(Database db) { + LogUtils.info("Database is recreating..."); sharedPref.setCurrentUserId(0); DaoMaster.dropAllTables(db, true); onCreate(db); @@ -74,7 +75,7 @@ public class DbHelper extends DaoMaster.OpenHelper { private List getMigrations() { List migrations = new ArrayList<>(); migrations.add(new Migration23()); - migrations.add(new Migration24()); + migrations.add(new Migration25()); // Sorting just to be safe, in case other people add migrations in the wrong order. Comparator migrationComparator = new Comparator() { diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbRepository.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbRepository.java index 6b64b8d8..6757c48e 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/DbRepository.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/DbRepository.java @@ -32,13 +32,18 @@ public class DbRepository implements DbContract { @Override public Week getWeek(String date) { + return getWeek(getCurrentDiaryId(), date); + } + + @Override + public Week getWeek(long diaryId, String date) { return daoSession.getWeekDao().queryBuilder().where( WeekDao.Properties.StartDayDate.eq(date), - WeekDao.Properties.DiaryId.eq(getCurrentDiaryId()) + WeekDao.Properties.DiaryId.eq(diaryId) ).unique(); } - + @Override public List getSubjectList(int semesterName) { return daoSession.getSemesterDao().load(getSemesterId(semesterName)).getSubjectList(); } diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Day.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Day.java index 8b0e6689..434affb0 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Day.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Day.java @@ -41,6 +41,9 @@ public class Day { @ToMany(referencedJoinProperty = "dayId") private List attendanceLessons; + @ToMany(referencedJoinProperty = "dayId") + private List exams; + /** * Used to resolve relations */ @@ -218,6 +221,36 @@ public class Day { myDao.update(this); } + /** + * To-many relationship, resolved on first access (and after reset). + * Changes to to-many relations are not persisted, make changes to the target entity. + */ + @Generated(hash = 1231531946) + public List getExams() { + if (exams == null) { + final DaoSession daoSession = this.daoSession; + if (daoSession == null) { + throw new DaoException("Entity is detached from DAO context"); + } + ExamDao targetDao = daoSession.getExamDao(); + List examsNew = targetDao._queryDay_Exams(id); + synchronized (this) { + if (exams == null) { + exams = examsNew; + } + } + } + return exams; + } + + /** + * Resets a to-many relationship, making the next get call to query for a fresh result. + */ + @Generated(hash = 841969952) + public synchronized void resetExams() { + exams = null; + } + /** called by internal mechanisms, do not call yourself. */ @Generated(hash = 1409317752) public void __setDaoSession(DaoSession daoSession) { diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Exam.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Exam.java new file mode 100644 index 00000000..c492ae3d --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Exam.java @@ -0,0 +1,177 @@ +package io.github.wulkanowy.data.db.dao.entities; + +import org.greenrobot.greendao.DaoException; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Property; + +import java.io.Serializable; + +@Entity( + nameInDb = "Exams", + active = true +) + +public class Exam implements Serializable { + + @Id(autoincrement = true) + private Long id; + + @Property(nameInDb = "day_id") + private Long dayId; + + @Property(nameInDb = "subject_and_group") + private String subjectAndGroup = ""; + + @Property(nameInDb = "type") + private String type = ""; + + @Property(nameInDb = "description") + private String description = ""; + + @Property(nameInDb = "teacher") + private String teacher = ""; + + @Property(nameInDb = "date") + private String date = ""; + + private static final long serialVersionUID = 42L; + + /** + * Used to resolve relations + */ + @Generated(hash = 2040040024) + private transient DaoSession daoSession; + + /** + * Used for active entity operations. + */ + @Generated(hash = 973692038) + private transient ExamDao myDao; + + @Generated(hash = 1455345431) + public Exam(Long id, Long dayId, String subjectAndGroup, String type, + String description, String teacher, String date) { + this.id = id; + this.dayId = dayId; + this.subjectAndGroup = subjectAndGroup; + this.type = type; + this.description = description; + this.teacher = teacher; + this.date = date; + } + + @Generated(hash = 945526930) + public Exam() { + } + + public Long getId() { + return id; + } + + public Exam setId(Long id) { + this.id = id; + return this; + } + + public Long getDayId() { + return this.dayId; + } + + public Exam setDayId(Long dayId) { + this.dayId = dayId; + return this; + } + + public String getSubjectAndGroup() { + return subjectAndGroup; + } + + public Exam setSubjectAndGroup(String subjectAndGroup) { + this.subjectAndGroup = subjectAndGroup; + return this; + } + + public String getType() { + return type; + } + + public Exam setType(String type) { + this.type = type; + return this; + } + + public String getDescription() { + return description; + } + + public Exam setDescription(String description) { + this.description = description; + return this; + } + + public String getTeacher() { + return teacher; + } + + public Exam setTeacher(String teacher) { + this.teacher = teacher; + return this; + } + + public String getDate() { + return date; + } + + public Exam setDate(String date) { + this.date = date; + return this; + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 128553479) + public void delete() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.delete(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 1942392019) + public void refresh() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.refresh(this); + } + + /** + * Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}. + * Entity must attached to an entity context. + */ + @Generated(hash = 713229351) + public void update() { + if (myDao == null) { + throw new DaoException("Entity is detached from DAO context"); + } + myDao.update(this); + } + + /** + * called by internal mechanisms, do not call yourself. + */ + @Generated(hash = 1730563422) + public void __setDaoSession(DaoSession daoSession) { + this.daoSession = daoSession; + myDao = daoSession != null ? daoSession.getExamDao() : null; + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Week.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Week.java index 90b09e0e..1edfa245 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Week.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/entities/Week.java @@ -32,6 +32,9 @@ public class Week { @Property(nameInDb = "timetable_synced") private boolean timetableSynced = false; + @Property(nameInDb = "exams_synced") + private boolean examsSynced = false; + @ToMany(referencedJoinProperty = "weekId") private List dayList; @@ -47,14 +50,15 @@ public class Week { @Generated(hash = 1019310398) private transient WeekDao myDao; - @Generated(hash = 1608180902) - public Week(Long id, Long diaryId, String startDayDate, - boolean attendanceSynced, boolean timetableSynced) { + @Generated(hash = 23357599) + public Week(Long id, Long diaryId, String startDayDate, boolean attendanceSynced, + boolean timetableSynced, boolean examsSynced) { this.id = id; this.diaryId = diaryId; this.startDayDate = startDayDate; this.attendanceSynced = attendanceSynced; this.timetableSynced = timetableSynced; + this.examsSynced = examsSynced; } @Generated(hash = 2135529658) @@ -88,8 +92,8 @@ public class Week { return this; } - public boolean isAttendanceSynced() { - return attendanceSynced; + public boolean getAttendanceSynced() { + return this.attendanceSynced; } public Week setAttendanceSynced(boolean attendanceSynced) { @@ -97,8 +101,8 @@ public class Week { return this; } - public boolean isTimetableSynced() { - return timetableSynced; + public boolean getTimetableSynced() { + return this.timetableSynced; } public Week setTimetableSynced(boolean timetableSynced) { @@ -106,6 +110,15 @@ public class Week { return this; } + public Week setExamsSynced(boolean examsSynced) { + this.examsSynced = examsSynced; + return this; + } + + public boolean getExamsSynced() { + return examsSynced; + } + /** * To-many relationship, resolved on first access (and after reset). * Changes to to-many relations are not persisted, make changes to the target entity. @@ -172,14 +185,6 @@ public class Week { myDao.update(this); } - public boolean getAttendanceSynced() { - return this.attendanceSynced; - } - - public boolean getTimetableSynced() { - return this.timetableSynced; - } - /** called by internal mechanisms, do not call yourself. */ @Generated(hash = 665278367) public void __setDaoSession(DaoSession daoSession) { diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration24.java b/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration25.java similarity index 86% rename from app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration24.java rename to app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration25.java index 102384cb..a5359b35 100644 --- a/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration24.java +++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/migrations/Migration25.java @@ -6,11 +6,11 @@ import io.github.wulkanowy.api.Vulcan; import io.github.wulkanowy.data.db.dao.DbHelper; import io.github.wulkanowy.data.db.shared.SharedPrefContract; -public class Migration24 implements DbHelper.Migration { +public class Migration25 implements DbHelper.Migration { @Override public Integer getVersion() { - return 24; + return 25; } @Override diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/ExamsSync.java b/app/src/main/java/io/github/wulkanowy/data/sync/ExamsSync.java new file mode 100644 index 00000000..2fd18866 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/data/sync/ExamsSync.java @@ -0,0 +1,147 @@ +package io.github.wulkanowy.data.sync; + +import org.threeten.bp.LocalDate; +import org.threeten.bp.format.DateTimeFormatter; +import org.threeten.bp.format.TextStyle; + +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import javax.inject.Inject; + +import io.github.wulkanowy.api.Vulcan; +import io.github.wulkanowy.api.VulcanException; +import io.github.wulkanowy.api.exams.ExamDay; +import io.github.wulkanowy.data.db.dao.entities.DaoSession; +import io.github.wulkanowy.data.db.dao.entities.Day; +import io.github.wulkanowy.data.db.dao.entities.DayDao; +import io.github.wulkanowy.data.db.dao.entities.Exam; +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.AppConstant; +import io.github.wulkanowy.utils.DataObjectConverter; +import io.github.wulkanowy.utils.LogUtils; +import io.github.wulkanowy.utils.TimeUtils; + +public class ExamsSync { + + private final DaoSession daoSession; + + private final Vulcan vulcan; + + private long diaryId; + + @Inject + ExamsSync(DaoSession daoSession, Vulcan vulcan) { + this.daoSession = daoSession; + this.vulcan = vulcan; + } + + public void syncExams(long diaryId, String date) throws IOException, VulcanException, + ParseException { + this.diaryId = diaryId; + + io.github.wulkanowy.api.generic.Week weekApi = getWeekFromApi(getNormalizedDate(date)); + Week weekDb = getWeekFromDb(weekApi.getStartDayDate()); + + long weekId = updateWeekInDb(weekDb, weekApi); + + List examList = getPreparedExams(weekApi.getDays(), weekId); + + daoSession.getExamDao().saveInTx(examList); + + LogUtils.debug("Synchronization exams (amount = " + examList.size() + ")"); + } + + private Week getWeekFromDb(String date) { + return daoSession.getWeekDao().queryBuilder().where( + WeekDao.Properties.DiaryId.eq(diaryId), + WeekDao.Properties.StartDayDate.eq(date) + ).unique(); + } + + private io.github.wulkanowy.api.generic.Week getWeekFromApi(String date) + throws VulcanException, IOException, ParseException { + return vulcan.getExamsList().getWeek(date, true); + } + + private Long updateWeekInDb(Week weekDb, io.github.wulkanowy.api.generic.Week weekApi) { + if (weekDb != null) { + weekDb.setExamsSynced(true); + weekDb.update(); + + return weekDb.getId(); + } + + Week weekApiEntity = DataObjectConverter.weekToWeekEntity(weekApi).setDiaryId(diaryId); + weekApiEntity.setExamsSynced(true); + + 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), + DayDao.Properties.Date.eq(date) + ).unique(); + } + + private List getPreparedExams(List dayListFromApi, + long weekId) { + List preparedExamList = new ArrayList<>(); + + for (ExamDay dayFromApi : dayListFromApi) { + + Day dayDb = getDayFromDb(dayFromApi.getDate(), weekId); + + Day dayApiEntity = DataObjectConverter.dayToDayEntity(dayFromApi); + + long dayId = updateDayInDb(dayDb, dayApiEntity, weekId); + + prepareExam(dayFromApi.getExamList(), preparedExamList, dayId); + } + return preparedExamList; + } + + private long updateDayInDb(Day dayDb, Day dayApi, long weekId) { + dayApi.setWeekId(weekId); + + if (null != dayDb) { + return dayDb.getId(); + } + return daoSession.getDayDao().insert(dayApi); + } + + private void prepareExam(List examList, + List preparedExams, long dayId) { + List examsApiEntity = DataObjectConverter.examsToExamsEntitiy(examList); + + for (Exam examApi : examsApiEntity) { + Exam examDb = getExamFromDb(examApi, dayId); + + examApi.setDayId(dayId); + + if (examDb != null) { + examApi.setId(examDb.getId()); + } + preparedExams.add(examApi); + } + } + + private Exam getExamFromDb(Exam examApi, long dayId) { + return daoSession.getExamDao().queryBuilder() + .where(ExamDao.Properties.DayId.eq(dayId), + ExamDao.Properties.Date.eq(examApi.getDate()), + ExamDao.Properties.SubjectAndGroup.eq(examApi.getSubjectAndGroup()), + ExamDao.Properties.Teacher.eq(examApi.getTeacher())) + .unique(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/SyncContract.java b/app/src/main/java/io/github/wulkanowy/data/sync/SyncContract.java index 3a2e0a4c..67797ad1 100644 --- a/app/src/main/java/io/github/wulkanowy/data/sync/SyncContract.java +++ b/app/src/main/java/io/github/wulkanowy/data/sync/SyncContract.java @@ -32,5 +32,9 @@ public interface SyncContract { void syncTimetable(long diaryId, String date) throws VulcanException, IOException, ParseException; + void syncExams() throws VulcanException, IOException, ParseException; + + void syncExams(long diaryId, String date) throws VulcanException, IOException, ParseException; + void syncAll() throws VulcanException, IOException, ParseException; } diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/SyncRepository.java b/app/src/main/java/io/github/wulkanowy/data/sync/SyncRepository.java index 91e8b421..6a1e4dc1 100644 --- a/app/src/main/java/io/github/wulkanowy/data/sync/SyncRepository.java +++ b/app/src/main/java/io/github/wulkanowy/data/sync/SyncRepository.java @@ -23,16 +23,20 @@ public class SyncRepository implements SyncContract { private final AccountSync accountSync; + private final ExamsSync examsSync; + private final DbContract database; @Inject SyncRepository(GradeSync gradeSync, SubjectSync subjectSync, AttendanceSync attendanceSync, - TimetableSync timetableSync, AccountSync accountSync, DbContract database) { + TimetableSync timetableSync, AccountSync accountSync, ExamsSync examsSync, + DbContract database) { this.gradeSync = gradeSync; this.subjectSync = subjectSync; this.attendanceSync = attendanceSync; this.timetableSync = timetableSync; this.accountSync = accountSync; + this.examsSync = examsSync; this.database = database; } @@ -95,11 +99,26 @@ public class SyncRepository implements SyncContract { } } + @Override + public void syncExams() throws VulcanException, IOException, ParseException { + examsSync.syncExams(database.getCurrentDiaryId(), null); + } + + @Override + public void syncExams(long diaryId, String date) throws VulcanException, IOException, ParseException { + if (diaryId != 0) { + examsSync.syncExams(diaryId, date); + } else { + examsSync.syncExams(database.getCurrentDiaryId(), date); + } + } + @Override public void syncAll() throws VulcanException, IOException, ParseException { syncSubjects(); syncGrades(); syncAttendance(); syncTimetable(); + syncExams(); } } diff --git a/app/src/main/java/io/github/wulkanowy/data/sync/TimetableSync.java b/app/src/main/java/io/github/wulkanowy/data/sync/TimetableSync.java index 40b7eb56..69ebafcf 100644 --- a/app/src/main/java/io/github/wulkanowy/data/sync/TimetableSync.java +++ b/app/src/main/java/io/github/wulkanowy/data/sync/TimetableSync.java @@ -40,7 +40,7 @@ public class TimetableSync { public void syncTimetable(long diaryId, String date) throws IOException, ParseException, VulcanException { this.diaryId = diaryId; - io.github.wulkanowy.api.generic.Week weekApi = getWeekFromApi(getNormalizedDate(date)); + io.github.wulkanowy.api.generic.Week weekApi = getWeekFromApi(getNormalizedDate(date)); Week weekDb = getWeekFromDb(weekApi.getStartDayDate()); long weekId = updateWeekInDb(weekDb, weekApi); @@ -56,7 +56,7 @@ public class TimetableSync { return null != date ? String.valueOf(TimeUtils.getNetTicks(date)) : ""; } - private io.github.wulkanowy.api.generic.Week getWeekFromApi(String date) + private io.github.wulkanowy.api.generic.Week getWeekFromApi(String date) throws IOException, ParseException, VulcanException { return vulcan.getTimetable().getWeekTable(date); } @@ -82,14 +82,14 @@ public class TimetableSync { return daoSession.getWeekDao().insert(apiEntity); } - private List updateDays(List dayListFromApi, long weekId) { + private List updateDays(List dayListFromApi, long weekId) { List updatedLessonList = new ArrayList<>(); - for (io.github.wulkanowy.api.generic.Day dayFromApi : dayListFromApi) { + for (io.github.wulkanowy.api.timetable.TimetableDay dayFromApi : dayListFromApi) { Day dbDayEntity = getDayFromDb(dayFromApi.getDate(), weekId); - Day apiDayEntity = DataObjectConverter.dayToDayEntity(dayFromApi); + Day apiDayEntity = DataObjectConverter.timetableDayToDayEntity(dayFromApi); long dayId = updateDay(dbDayEntity, apiDayEntity, weekId); diff --git a/app/src/main/java/io/github/wulkanowy/di/component/FragmentComponent.java b/app/src/main/java/io/github/wulkanowy/di/component/FragmentComponent.java index b26abaaf..9f56364c 100644 --- a/app/src/main/java/io/github/wulkanowy/di/component/FragmentComponent.java +++ b/app/src/main/java/io/github/wulkanowy/di/component/FragmentComponent.java @@ -5,7 +5,8 @@ import io.github.wulkanowy.di.annotations.PerFragment; import io.github.wulkanowy.di.modules.FragmentModule; import io.github.wulkanowy.ui.main.attendance.AttendanceFragment; import io.github.wulkanowy.ui.main.attendance.AttendanceTabFragment; -import io.github.wulkanowy.ui.main.dashboard.DashboardFragment; +import io.github.wulkanowy.ui.main.exams.ExamsFragment; +import io.github.wulkanowy.ui.main.exams.ExamsTabFragment; import io.github.wulkanowy.ui.main.grades.GradesFragment; import io.github.wulkanowy.ui.main.timetable.TimetableFragment; import io.github.wulkanowy.ui.main.timetable.TimetableTabFragment; @@ -20,7 +21,9 @@ public interface FragmentComponent { void inject(AttendanceTabFragment attendanceTabFragment); - void inject(DashboardFragment dashboardFragment); + void inject(ExamsFragment examsFragment); + + void inject(ExamsTabFragment examsTabFragment); void inject(TimetableFragment timetableFragment); diff --git a/app/src/main/java/io/github/wulkanowy/di/modules/ActivityModule.java b/app/src/main/java/io/github/wulkanowy/di/modules/ActivityModule.java index 53dc1086..cdffe73a 100644 --- a/app/src/main/java/io/github/wulkanowy/di/modules/ActivityModule.java +++ b/app/src/main/java/io/github/wulkanowy/di/modules/ActivityModule.java @@ -8,10 +8,10 @@ import dagger.Module; import dagger.Provides; import io.github.wulkanowy.di.annotations.ActivityContext; import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.ui.base.BasePagerAdapter; import io.github.wulkanowy.ui.login.LoginContract; import io.github.wulkanowy.ui.login.LoginPresenter; import io.github.wulkanowy.ui.main.MainContract; -import io.github.wulkanowy.ui.main.MainPagerAdapter; import io.github.wulkanowy.ui.main.MainPresenter; import io.github.wulkanowy.ui.splash.SplashContract; import io.github.wulkanowy.ui.splash.SplashPresenter; @@ -58,7 +58,7 @@ public class ActivityModule { } @Provides - MainPagerAdapter provideMainPagerAdapter() { - return new MainPagerAdapter(activity.getSupportFragmentManager()); + BasePagerAdapter provideMainPagerAdapter() { + return new BasePagerAdapter(activity.getSupportFragmentManager()); } } diff --git a/app/src/main/java/io/github/wulkanowy/di/modules/FragmentModule.java b/app/src/main/java/io/github/wulkanowy/di/modules/FragmentModule.java index 3479a8c4..005b7aa1 100644 --- a/app/src/main/java/io/github/wulkanowy/di/modules/FragmentModule.java +++ b/app/src/main/java/io/github/wulkanowy/di/modules/FragmentModule.java @@ -6,20 +6,22 @@ import dagger.Module; import dagger.Provides; import eu.davidea.flexibleadapter.FlexibleAdapter; import io.github.wulkanowy.di.annotations.PerFragment; +import io.github.wulkanowy.ui.base.BasePagerAdapter; import io.github.wulkanowy.ui.main.attendance.AttendanceContract; import io.github.wulkanowy.ui.main.attendance.AttendanceHeaderItem; -import io.github.wulkanowy.ui.main.attendance.AttendancePagerAdapter; import io.github.wulkanowy.ui.main.attendance.AttendancePresenter; import io.github.wulkanowy.ui.main.attendance.AttendanceTabContract; import io.github.wulkanowy.ui.main.attendance.AttendanceTabPresenter; -import io.github.wulkanowy.ui.main.dashboard.DashboardContract; -import io.github.wulkanowy.ui.main.dashboard.DashboardPresenter; +import io.github.wulkanowy.ui.main.exams.ExamsContract; +import io.github.wulkanowy.ui.main.exams.ExamsPresenter; +import io.github.wulkanowy.ui.main.exams.ExamsSubItem; +import io.github.wulkanowy.ui.main.exams.ExamsTabContract; +import io.github.wulkanowy.ui.main.exams.ExamsTabPresenter; import io.github.wulkanowy.ui.main.grades.GradeHeaderItem; import io.github.wulkanowy.ui.main.grades.GradesContract; import io.github.wulkanowy.ui.main.grades.GradesPresenter; import io.github.wulkanowy.ui.main.timetable.TimetableContract; import io.github.wulkanowy.ui.main.timetable.TimetableHeaderItem; -import io.github.wulkanowy.ui.main.timetable.TimetablePagerAdapter; import io.github.wulkanowy.ui.main.timetable.TimetablePresenter; import io.github.wulkanowy.ui.main.timetable.TimetableTabContract; import io.github.wulkanowy.ui.main.timetable.TimetableTabPresenter; @@ -47,8 +49,8 @@ public class FragmentModule { @PerFragment @Provides - DashboardContract.Presenter provideDashboardPresenter(DashboardPresenter dashboardPresenter) { - return dashboardPresenter; + ExamsContract.Presenter provideDashboardPresenter(ExamsPresenter examsPresenter) { + return examsPresenter; } @PerFragment @@ -58,8 +60,8 @@ public class FragmentModule { } @Provides - AttendancePagerAdapter provideAttendancePagerAdapter() { - return new AttendancePagerAdapter(fragment.getChildFragmentManager()); + BasePagerAdapter provideBasePagerAdapter() { + return new BasePagerAdapter(fragment.getChildFragmentManager()); } @Provides @@ -67,6 +69,21 @@ public class FragmentModule { return new FlexibleAdapter<>(null); } + @Provides + FlexibleAdapter provideTimetableTabAdapter() { + return new FlexibleAdapter<>(null); + } + + @Provides + FlexibleAdapter provideGradesAdapter() { + return new FlexibleAdapter<>(null); + } + + @Provides + FlexibleAdapter provideExamAdapter() { + return new FlexibleAdapter<>(null); + } + @PerFragment @Provides TimetableContract.Presenter provideTimetablePresenter(TimetablePresenter timetablePresenter) { @@ -80,17 +97,7 @@ public class FragmentModule { } @Provides - TimetablePagerAdapter provideTimetablePagerAdapter() { - return new TimetablePagerAdapter(fragment.getChildFragmentManager()); - } - - @Provides - FlexibleAdapter provideTimetableTabAdapter() { - return new FlexibleAdapter<>(null); - } - - @Provides - FlexibleAdapter provideGradesAdapter() { - return new FlexibleAdapter<>(null); + ExamsTabContract.Presenter provideExamsTabPresenter(ExamsTabPresenter examsTabPresenter) { + return examsTabPresenter; } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/base/BasePagerAdapter.java b/app/src/main/java/io/github/wulkanowy/ui/base/BasePagerAdapter.java new file mode 100644 index 00000000..178f0110 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/base/BasePagerAdapter.java @@ -0,0 +1,47 @@ +package io.github.wulkanowy.ui.base; + +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; + +import java.util.ArrayList; +import java.util.List; + +public class BasePagerAdapter extends FragmentStatePagerAdapter { + + private List fragmentList = new ArrayList<>(); + + private List titleList = new ArrayList<>(); + + public BasePagerAdapter(FragmentManager fragmentManager) { + super(fragmentManager); + } + + public void addFragment(@NonNull Fragment fragment, @NonNull String title) { + fragmentList.add(fragment); + titleList.add(title); + } + + public void addFragment(@NonNull Fragment fragment) { + fragmentList.add(fragment); + } + + @Override + public Fragment getItem(int position) { + return fragmentList.get(position); + } + + @Override + public int getCount() { + return fragmentList.size(); + } + + @Override + public CharSequence getPageTitle(int position) { + if (!titleList.isEmpty()) { + return titleList.get(position); + } + return null; + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.java b/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.java index 07951b3f..11acc562 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/MainActivity.java @@ -18,8 +18,9 @@ import butterknife.BindView; import butterknife.ButterKnife; import io.github.wulkanowy.R; import io.github.wulkanowy.ui.base.BaseActivity; +import io.github.wulkanowy.ui.base.BasePagerAdapter; import io.github.wulkanowy.ui.main.attendance.AttendanceFragment; -import io.github.wulkanowy.ui.main.dashboard.DashboardFragment; +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; @@ -39,7 +40,7 @@ public class MainActivity extends BaseActivity implements MainContract.View, View progressBar; @Inject - MainPagerAdapter pagerAdapter; + BasePagerAdapter pagerAdapter; @Inject MainContract.Presenter presenter; @@ -107,8 +108,8 @@ public class MainActivity extends BaseActivity implements MainContract.View, bottomNavigation.addItem(new AHBottomNavigationItem(getString(R.string.attendance_text), R.drawable.ic_menu_attendance_24dp)); - bottomNavigation.addItem(new AHBottomNavigationItem(getString(R.string.dashboard_text), - R.drawable.ic_menu_dashboard_24dp)); + bottomNavigation.addItem(new AHBottomNavigationItem(getString(R.string.exams_text), + R.drawable.ic_menu_exams_24dp)); bottomNavigation.addItem(new AHBottomNavigationItem(getString(R.string.timetable_text), R.drawable.ic_menu_timetable_24dp)); @@ -129,7 +130,7 @@ public class MainActivity extends BaseActivity implements MainContract.View, public void initiationViewPager(int tabPosition) { pagerAdapter.addFragment(new GradesFragment()); pagerAdapter.addFragment(new AttendanceFragment()); - pagerAdapter.addFragment(new DashboardFragment()); + pagerAdapter.addFragment(new ExamsFragment()); pagerAdapter.addFragment(new TimetableFragment()); pagerAdapter.addFragment(new SettingsFragment()); diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/MainPagerAdapter.java b/app/src/main/java/io/github/wulkanowy/ui/main/MainPagerAdapter.java deleted file mode 100644 index fcc51fb5..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/main/MainPagerAdapter.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.wulkanowy.ui.main; - -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentStatePagerAdapter; - -import java.util.ArrayList; -import java.util.List; - -public class MainPagerAdapter extends FragmentStatePagerAdapter { - - private List fragmentList = new ArrayList<>(); - - public MainPagerAdapter(FragmentManager fragmentManager) { - super(fragmentManager); - } - - void addFragment(Fragment fragment) { - fragmentList.add(fragment); - } - - @Override - public Fragment getItem(int position) { - return fragmentList.get(position); - } - - @Override - public int getCount() { - return fragmentList.size(); - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/TabsData.java b/app/src/main/java/io/github/wulkanowy/ui/main/TabsData.java deleted file mode 100644 index 3af29534..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/main/TabsData.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.github.wulkanowy.ui.main; - -import android.support.v4.app.Fragment; - -import java.util.ArrayList; -import java.util.List; - -public class TabsData { - - private List fragments = new ArrayList<>(); - - private List titles = new ArrayList<>(); - - public Fragment getFragment(int index) { - return fragments.get(index); - } - - public void addFragment(Fragment fragment) { - if (fragment != null) { - fragments.add(fragment); - } - } - - public int getFragmentsCount() { - return fragments.size(); - } - - public String getTitle(int index) { - return titles.get(index); - } - - public void addTitle(String title) { - if (title != null) { - titles.add(title); - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceContract.java index 545e300e..29db9a57 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceContract.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceContract.java @@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.main.attendance; import io.github.wulkanowy.di.annotations.PerActivity; import io.github.wulkanowy.ui.base.BaseContract; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -import io.github.wulkanowy.ui.main.TabsData; public interface AttendanceContract { @@ -13,7 +12,7 @@ public interface AttendanceContract { void scrollViewPagerToPosition(int position); - void setTabDataToAdapter(TabsData tabsData); + void setTabDataToAdapter(String date); void setAdapterWithTabLayout(); diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.java index 4dd179b1..852eba20 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceFragment.java @@ -17,8 +17,8 @@ import butterknife.ButterKnife; import io.github.wulkanowy.R; import io.github.wulkanowy.di.component.FragmentComponent; import io.github.wulkanowy.ui.base.BaseFragment; +import io.github.wulkanowy.ui.base.BasePagerAdapter; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -import io.github.wulkanowy.ui.main.TabsData; public class AttendanceFragment extends BaseFragment implements AttendanceContract.View { @@ -31,7 +31,7 @@ public class AttendanceFragment extends BaseFragment implements AttendanceContra TabLayout tabLayout; @Inject - AttendancePagerAdapter pagerAdapter; + BasePagerAdapter pagerAdapter; @Inject AttendanceContract.Presenter presenter; @@ -65,8 +65,8 @@ public class AttendanceFragment extends BaseFragment implements AttendanceContra } @Override - public void setTabDataToAdapter(TabsData tabsData) { - pagerAdapter.setTabsData(tabsData); + public void setTabDataToAdapter(String date) { + pagerAdapter.addFragment(AttendanceTabFragment.newInstance(date), date); } @Override diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePagerAdapter.java b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePagerAdapter.java deleted file mode 100644 index 3cabff71..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePagerAdapter.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.wulkanowy.ui.main.attendance; - -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentStatePagerAdapter; - -import io.github.wulkanowy.ui.main.TabsData; - -public class AttendancePagerAdapter extends FragmentStatePagerAdapter { - - private TabsData tabsData; - - public AttendancePagerAdapter(FragmentManager fragmentManager) { - super(fragmentManager); - } - - void setTabsData(TabsData tabsData) { - this.tabsData = tabsData; - } - - @Override - public Fragment getItem(int position) { - return tabsData.getFragment(position); - } - - - @Override - public int getCount() { - return tabsData.getFragmentsCount(); - } - - @Nullable - @Override - public CharSequence getPageTitle(int position) { - return tabsData.getTitle(position); - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java index bad68e16..f32aba35 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendancePresenter.java @@ -8,7 +8,6 @@ import javax.inject.Inject; import io.github.wulkanowy.data.RepositoryContract; import io.github.wulkanowy.ui.base.BasePresenter; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -import io.github.wulkanowy.ui.main.TabsData; import io.github.wulkanowy.utils.TimeUtils; import io.github.wulkanowy.utils.async.AbstractTask; import io.github.wulkanowy.utils.async.AsyncListeners; @@ -20,8 +19,6 @@ public class AttendancePresenter extends BasePresenter private List dates = new ArrayList<>(); - private TabsData tabsData = new TabsData(); - private OnFragmentIsReadyListener listener; private int positionToScroll = 0; @@ -69,8 +66,7 @@ public class AttendancePresenter extends BasePresenter @Override public void onDoInBackgroundLoading() throws Exception { for (String date : dates) { - tabsData.addTitle(date); - tabsData.addFragment(AttendanceTabFragment.newInstance(date)); + getView().setTabDataToAdapter(date); } } @@ -83,7 +79,6 @@ public class AttendancePresenter extends BasePresenter @Override public void onEndLoadingAsync(boolean result, Exception exception) { if (result) { - getView().setTabDataToAdapter(tabsData); getView().setAdapterWithTabLayout(); getView().scrollViewPagerToPosition(positionToScroll); listener.onFragmentIsReady(); diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceTabPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceTabPresenter.java index 5731cbb3..47927feb 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceTabPresenter.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/attendance/AttendanceTabPresenter.java @@ -100,6 +100,7 @@ public class AttendanceTabPresenter extends BasePresenter dayList = week.getDayList(); headerItems = new ArrayList<>(); diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardFragment.java deleted file mode 100644 index 0832b5fb..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardFragment.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.github.wulkanowy.ui.main.dashboard; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import javax.inject.Inject; - -import butterknife.ButterKnife; -import io.github.wulkanowy.R; -import io.github.wulkanowy.di.component.FragmentComponent; -import io.github.wulkanowy.ui.base.BaseFragment; -import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; - -public class DashboardFragment extends BaseFragment implements DashboardContract.View { - - @Inject - DashboardContract.Presenter presenter; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_board, container, false); - - FragmentComponent component = getFragmentComponent(); - if (component != null) { - component.inject(this); - setButterKnife(ButterKnife.bind(this, view)); - presenter.onStart(this, (OnFragmentIsReadyListener) getActivity()); - } - return view; - } - - @Override - public void setMenuVisibility(boolean menuVisible) { - super.setMenuVisibility(menuVisible); - if (presenter != null) { - presenter.onFragmentVisible(menuVisible); - } - } - - @Override - public void setActivityTitle() { - setTitle(getString(R.string.dashboard_text)); - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardPresenter.java deleted file mode 100644 index 58d89b39..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardPresenter.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.github.wulkanowy.ui.main.dashboard; - -import javax.inject.Inject; - -import io.github.wulkanowy.data.RepositoryContract; -import io.github.wulkanowy.ui.base.BasePresenter; -import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; - -public class DashboardPresenter extends BasePresenter - implements DashboardContract.Presenter { - - private OnFragmentIsReadyListener listener; - - @Inject - DashboardPresenter(RepositoryContract repository) { - super(repository); - } - - @Override - public void onStart(DashboardContract.View view, OnFragmentIsReadyListener listener) { - super.onStart(view); - this.listener = listener; - - if (getView().isMenuVisible()) { - getView().setActivityTitle(); - } - - this.listener.onFragmentIsReady(); - } - - @Override - public void onFragmentVisible(boolean isVisible) { - if (isVisible) { - getView().setActivityTitle(); - } - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsContract.java similarity index 58% rename from app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardContract.java rename to app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsContract.java index 2488eb95..d4692c03 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/dashboard/DashboardContract.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsContract.java @@ -1,16 +1,22 @@ -package io.github.wulkanowy.ui.main.dashboard; +package io.github.wulkanowy.ui.main.exams; import io.github.wulkanowy.di.annotations.PerActivity; import io.github.wulkanowy.ui.base.BaseContract; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -public interface DashboardContract { +public interface ExamsContract { interface View extends BaseContract.View { void setActivityTitle(); boolean isMenuVisible(); + + void scrollViewPagerToPosition(int position); + + void setTabDataToAdapter(String date); + + void setAdapterWithTabLayout(); } @PerActivity @@ -18,6 +24,8 @@ public interface DashboardContract { void onStart(View view, OnFragmentIsReadyListener listener); - void onFragmentVisible(boolean isVisible); + void onFragmentActivated(boolean isVisible); + + void setRestoredPosition(int position); } } diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsDialogFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsDialogFragment.java new file mode 100644 index 00000000..6128cf6d --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsDialogFragment.java @@ -0,0 +1,81 @@ +package io.github.wulkanowy.ui.main.exams; + + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import io.github.wulkanowy.R; +import io.github.wulkanowy.data.db.dao.entities.Exam; + +public class ExamsDialogFragment extends DialogFragment { + + private static final String ARGUMENT_KEY = "Item"; + + private Exam exam; + + @BindView(R.id.exams_dialog_subject_value) + TextView subject; + + @BindView(R.id.exams_dialog_type_value) + TextView type; + + @BindView(R.id.exams_dialog_teacher_value) + TextView teacher; + + @BindView(R.id.exams_dialog_date_value) + TextView date; + + @BindView(R.id.exams_dialog_description_value) + TextView description; + + public static ExamsDialogFragment newInstance(Exam exam) { + ExamsDialogFragment dialogFragment = new ExamsDialogFragment(); + + Bundle bundle = new Bundle(); + bundle.putSerializable(ARGUMENT_KEY, exam); + + dialogFragment.setArguments(bundle); + + return dialogFragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + exam = (Exam) getArguments().getSerializable(ARGUMENT_KEY); + } + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.exams_dialog, container, false); + + ButterKnife.bind(this, view); + + subject.setText(exam.getSubjectAndGroup()); + teacher.setText(exam.getTeacher()); + type.setText(exam.getType()); + date.setText(exam.getDate()); + + if (!exam.getDescription().isEmpty()) { + description.setText(exam.getDescription()); + } + + return view; + } + + @OnClick(R.id.exams_dialog_close) + void onClickCloseButton() { + dismiss(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsFragment.java new file mode 100644 index 00000000..064e435c --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsFragment.java @@ -0,0 +1,92 @@ +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; +import android.view.View; +import android.view.ViewGroup; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.github.wulkanowy.R; +import io.github.wulkanowy.di.component.FragmentComponent; +import io.github.wulkanowy.ui.base.BaseFragment; +import io.github.wulkanowy.ui.base.BasePagerAdapter; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; + +public class ExamsFragment extends BaseFragment implements ExamsContract.View { + + @BindView(R.id.exams_fragment_viewpager) + ViewPager viewPager; + + @BindView(R.id.exams_fragment_tab_layout) + TabLayout tabLayout; + + @Inject + BasePagerAdapter pagerAdapter; + + @Inject + ExamsContract.Presenter presenter; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_exams, container, false); + + FragmentComponent component = getFragmentComponent(); + if (component != null) { + component.inject(this); + setButterKnife(ButterKnife.bind(this, view)); + presenter.onStart(this, (OnFragmentIsReadyListener) getActivity()); + } + return view; + } + + @Override + public void setMenuVisibility(boolean menuVisible) { + super.setMenuVisibility(menuVisible); + if (presenter != null) { + presenter.onFragmentActivated(menuVisible); + } + } + + @Override + public void onError(String message) { + if (getActivity() != null) { + Snackbar.make(getActivity().findViewById(R.id.main_activity_view_pager), + message, Snackbar.LENGTH_LONG).show(); + } + } + + @Override + public void setActivityTitle() { + setTitle(getString(R.string.exams_text)); + } + + @Override + public void scrollViewPagerToPosition(int position) { + viewPager.setCurrentItem(position, false); + } + + @Override + public void setTabDataToAdapter(String date) { + pagerAdapter.addFragment(ExamsTabFragment.newInstance(date), date); + } + + @Override + public void setAdapterWithTabLayout() { + viewPager.setAdapter(pagerAdapter); + tabLayout.setupWithViewPager(viewPager); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + presenter.onDestroy(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsHeaderItem.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsHeaderItem.java new file mode 100644 index 00000000..86070515 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsHeaderItem.java @@ -0,0 +1,82 @@ +package io.github.wulkanowy.ui.main.exams; + +import android.view.View; +import android.widget.TextView; + +import org.apache.commons.lang3.StringUtils; +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.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.Day; + +public class ExamsHeaderItem extends AbstractHeaderItem { + + private Day day; + + public ExamsHeaderItem(Day day) { + this.day = day; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + ExamsHeaderItem that = (ExamsHeaderItem) o; + + return new EqualsBuilder() + .append(day, that.day) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(day) + .toHashCode(); + } + + @Override + public int getLayoutRes() { + return R.layout.exams_header; + } + + @Override + public HeaderVieHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new HeaderVieHolder(view, adapter); + } + + @Override + public void bindViewHolder(FlexibleAdapter adapter, HeaderVieHolder holder, int position, List payloads) { + holder.onBind(day); + } + + static class HeaderVieHolder extends FlexibleViewHolder { + + @BindView(R.id.exams_header_name) + TextView name; + + @BindView(R.id.exams_header_date) + TextView date; + + HeaderVieHolder(View view, FlexibleAdapter adapter) { + super(view, adapter); + ButterKnife.bind(this, view); + } + + void onBind(Day item) { + name.setText(StringUtils.capitalize(item.getDayName())); + date.setText(item.getDate()); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsPresenter.java new file mode 100644 index 00000000..2740e9a7 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsPresenter.java @@ -0,0 +1,102 @@ +package io.github.wulkanowy.ui.main.exams; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.ui.base.BasePresenter; +import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; +import io.github.wulkanowy.utils.TimeUtils; +import io.github.wulkanowy.utils.async.AbstractTask; +import io.github.wulkanowy.utils.async.AsyncListeners; + +public class ExamsPresenter extends BasePresenter + implements ExamsContract.Presenter, AsyncListeners.OnFirstLoadingListener { + + private AbstractTask loadingTask; + + private List dates = new ArrayList<>(); + + private OnFragmentIsReadyListener listener; + + private int positionToScroll = 0; + + private boolean isFirstSight = false; + + @Inject + ExamsPresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onStart(ExamsContract.View view, OnFragmentIsReadyListener listener) { + super.onStart(view); + this.listener = listener; + + if (getView().isMenuVisible()) { + getView().setActivityTitle(); + } + + if (dates.isEmpty()) { + dates = TimeUtils.getMondaysFromCurrentSchoolYear(); + } + + if (positionToScroll == 0) { + positionToScroll = dates.indexOf(TimeUtils.getDateOfCurrentMonday(true)); + } + + if (!isFirstSight) { + isFirstSight = true; + + loadingTask = new AbstractTask(); + loadingTask.setOnFirstLoadingListener(this); + loadingTask.execute(); + } + } + + @Override + public void onFragmentActivated(boolean isVisible) { + if (isVisible) { + getView().setActivityTitle(); + } + } + + @Override + public void setRestoredPosition(int position) { + this.positionToScroll = position; + } + + @Override + public void onDoInBackgroundLoading() throws Exception { + for (String date : dates) { + getView().setTabDataToAdapter(date); + } + } + + @Override + public void onCanceledLoadingAsync() { + // do nothing + } + + @Override + public void onEndLoadingAsync(boolean result, Exception exception) { + if (result) { + getView().setAdapterWithTabLayout(); + getView().scrollViewPagerToPosition(positionToScroll); + listener.onFragmentIsReady(); + } + } + + @Override + public void onDestroy() { + isFirstSight = false; + + if (loadingTask != null) { + loadingTask.cancel(true); + loadingTask = null; + } + super.onDestroy(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsSubItem.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsSubItem.java new file mode 100644 index 00000000..aca20d6b --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsSubItem.java @@ -0,0 +1,108 @@ +package io.github.wulkanowy.ui.main.exams; + +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +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.Exam; + +public class ExamsSubItem + extends AbstractSectionableItem { + + private Exam exam; + + ExamsSubItem(ExamsHeaderItem header, Exam exam) { + super(header); + this.exam = exam; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + ExamsSubItem that = (ExamsSubItem) o; + + return new EqualsBuilder() + .append(exam, that.exam) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(exam) + .toHashCode(); + } + + @Override + public int getLayoutRes() { + return R.layout.exams_subitem; + } + + @Override + public SubItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new SubItemViewHolder(view, adapter); + } + + @Override + public void bindViewHolder(FlexibleAdapter adapter, SubItemViewHolder holder, int position, List payloads) { + holder.onBind(exam); + } + + static class SubItemViewHolder extends FlexibleViewHolder { + + @BindView(R.id.exams_subitem_subject) + TextView subject; + + @BindView(R.id.exams_subitems_teacher) + TextView teacher; + + @BindView(R.id.exams_subitems_type) + TextView type; + + private Exam item; + + SubItemViewHolder(View view, FlexibleAdapter adapter) { + super(view, adapter); + ButterKnife.bind(this, view); + view.setOnClickListener(this); + } + + void onBind(Exam exam) { + item = exam; + + subject.setText(item.getSubjectAndGroup()); + teacher.setText(item.getTeacher()); + type.setText(item.getType()); + } + + @Override + public void onClick(View view) { + super.onClick(view); + showDialog(); + + } + + private void showDialog() { + ExamsDialogFragment dialogFragment = ExamsDialogFragment.newInstance(item); + dialogFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0); + dialogFragment.show(((FragmentActivity) getContentView().getContext()).getSupportFragmentManager(), + item.toString()); + } + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsTabContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsTabContract.java new file mode 100644 index 00000000..ec59628a --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsTabContract.java @@ -0,0 +1,32 @@ +package io.github.wulkanowy.ui.main.exams; + +import java.util.List; + +import io.github.wulkanowy.di.annotations.PerFragment; +import io.github.wulkanowy.ui.base.BaseContract; + +public interface ExamsTabContract { + + interface View extends BaseContract.View { + + void onRefreshSuccess(); + + void hideRefreshingBar(); + + void showNoItem(boolean show); + + void showProgressBar(boolean show); + + void updateAdapterList(List headerItems); + } + + @PerFragment + interface Presenter extends BaseContract.Presenter { + + void onFragmentActivated(boolean isSelected); + + void setArgumentDate(String date); + + void onRefresh(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsTabFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsTabFragment.java new file mode 100644 index 00000000..ccc3da17 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsTabFragment.java @@ -0,0 +1,141 @@ +package io.github.wulkanowy.ui.main.exams; + +import android.os.Bundle; +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; +import android.view.View; +import android.view.ViewGroup; + +import java.util.List; + +import javax.inject.Inject; + +import butterknife.BindView; +import butterknife.ButterKnife; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager; +import io.github.wulkanowy.R; +import io.github.wulkanowy.di.component.FragmentComponent; +import io.github.wulkanowy.ui.base.BaseFragment; + +public class ExamsTabFragment extends BaseFragment implements ExamsTabContract.View, + SwipeRefreshLayout.OnRefreshListener { + + private static final String ARGUMENT_KEY = "date"; + + @BindView(R.id.exams_tab_fragment_recycler) + RecyclerView recyclerView; + + @BindView(R.id.exams_tab_fragment_swipe_refresh) + SwipeRefreshLayout refreshLayout; + + @BindView(R.id.exams_tab_fragment_progress_bar) + View progressBar; + + @BindView(R.id.exams_tab_fragment_no_item_container) + View noItemView; + + @Inject + ExamsTabContract.Presenter presenter; + + @Inject + FlexibleAdapter adapter; + + private boolean isFragmentVisible = false; + + public static ExamsTabFragment newInstance(String date) { + ExamsTabFragment tabFragment = new ExamsTabFragment(); + + Bundle bundle = new Bundle(); + bundle.putString(ARGUMENT_KEY, date); + tabFragment.setArguments(bundle); + + return tabFragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_exams_tab, container, false); + + FragmentComponent component = getFragmentComponent(); + if (component != null) { + component.inject(this); + setButterKnife(ButterKnife.bind(this, view)); + + if (getArguments() != null) { + presenter.setArgumentDate(getArguments().getString(ARGUMENT_KEY)); + } + presenter.onStart(this); + presenter.onFragmentActivated(isFragmentVisible); + } + return view; + } + + @Override + protected void setUpOnViewCreated(View fragmentView) { + adapter.setDisplayHeadersAtStartUp(true); + + recyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(fragmentView.getContext())); + recyclerView.setAdapter(adapter); + + refreshLayout.setColorSchemeResources(android.R.color.black); + refreshLayout.setOnRefreshListener(this); + } + + @Override + public void setMenuVisibility(boolean menuVisible) { + super.setMenuVisibility(menuVisible); + isFragmentVisible = menuVisible; + if (presenter != null) { + presenter.onFragmentActivated(menuVisible); + } + } + + @Override + public void updateAdapterList(List headerItems) { + adapter.updateDataSet(headerItems); + } + + @Override + public void onRefresh() { + presenter.onRefresh(); + } + + @Override + public void onRefreshSuccess() { + onError(R.string.sync_completed); + } + + @Override + public void hideRefreshingBar() { + refreshLayout.setRefreshing(false); + } + + @Override + public void showNoItem(boolean show) { + noItemView.setVisibility(show ? View.VISIBLE : View.INVISIBLE); + } + + @Override + public void showProgressBar(boolean show) { + progressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE); + } + + @Override + public void onError(String message) { + if (getActivity() != null) { + Snackbar.make(getActivity().findViewById(R.id.main_activity_view_pager), + message, Snackbar.LENGTH_LONG).show(); + } + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + presenter.onDestroy(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsTabPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsTabPresenter.java new file mode 100644 index 00000000..8c8914a0 --- /dev/null +++ b/app/src/main/java/io/github/wulkanowy/ui/main/exams/ExamsTabPresenter.java @@ -0,0 +1,162 @@ +package io.github.wulkanowy.ui.main.exams; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import io.github.wulkanowy.data.RepositoryContract; +import io.github.wulkanowy.data.db.dao.entities.Day; +import io.github.wulkanowy.data.db.dao.entities.Exam; +import io.github.wulkanowy.data.db.dao.entities.Week; +import io.github.wulkanowy.ui.base.BasePresenter; +import io.github.wulkanowy.utils.async.AbstractTask; +import io.github.wulkanowy.utils.async.AsyncListeners; + +public class ExamsTabPresenter extends BasePresenter + implements ExamsTabContract.Presenter, AsyncListeners.OnFirstLoadingListener, + AsyncListeners.OnRefreshListener { + + private AbstractTask refreshTask; + + private AbstractTask loadingTask; + + private List subItems = new ArrayList<>(); + + private String date; + + private boolean isFirstSight = false; + + @Inject + public ExamsTabPresenter(RepositoryContract repository) { + super(repository); + } + + @Override + public void onStart(ExamsTabContract.View view) { + super.onStart(view); + getView().showProgressBar(true); + getView().showNoItem(false); + } + + @Override + public void onFragmentActivated(boolean isSelected) { + if (!isFirstSight && isSelected && isViewAttached()) { + isFirstSight = true; + + loadingTask = new AbstractTask(); + loadingTask.setOnFirstLoadingListener(this); + loadingTask.execute(); + } else if (!isSelected) { + cancelAsyncTasks(); + } + } + + @Override + public void setArgumentDate(String date) { + this.date = date; + } + + @Override + public void onRefresh() { + if (getView().isNetworkConnected()) { + refreshTask = new AbstractTask(); + refreshTask.setOnRefreshListener(this); + refreshTask.execute(); + } else { + getView().onNoNetworkError(); + getView().hideRefreshingBar(); + } + } + + @Override + public void onDoInBackgroundRefresh() throws Exception { + syncData(); + } + + @Override + public void onCanceledRefreshAsync() { + if (isViewAttached()) { + getView().hideRefreshingBar(); + } + } + + @Override + public void onEndRefreshAsync(boolean result, Exception exception) { + if (result) { + loadingTask = new AbstractTask(); + loadingTask.setOnFirstLoadingListener(this); + loadingTask.execute(); + + getView().onRefreshSuccess(); + } else { + getView().onError(getRepository().getResRepo().getErrorLoginMessage(exception)); + } + getView().hideRefreshingBar(); + } + + @Override + public void onDoInBackgroundLoading() throws Exception { + Week week = getRepository().getDbRepo().getWeek(date); + + if (week == null || !week.getExamsSynced()) { + syncData(); + week = getRepository().getDbRepo().getWeek(date); + } + + week.resetDayList(); + List dayList = week.getDayList(); + + subItems = new ArrayList<>(); + + for (Day day : dayList) { + day.resetExams(); + ExamsHeaderItem headerItem = new ExamsHeaderItem(day); + + List examList = day.getExams(); + + for (Exam exam : examList) { + subItems.add(new ExamsSubItem(headerItem, exam)); + } + } + } + + @Override + public void onCanceledLoadingAsync() { + // do nothing + } + + @Override + public void onEndLoadingAsync(boolean result, Exception exception) { + if (subItems.isEmpty()) { + getView().showNoItem(true); + getView().updateAdapterList(null); + } else { + getView().updateAdapterList(subItems); + getView().showNoItem(false); + } + getView().showProgressBar(false); + } + + private void syncData() throws Exception { + getRepository().getSyncRepo().syncExams(0, date); + } + + private void cancelAsyncTasks() { + if (refreshTask != null) { + refreshTask.cancel(true); + refreshTask = null; + } + if (loadingTask != null) { + loadingTask.cancel(true); + loadingTask = null; + } + } + + @Override + public void onDestroy() { + isFirstSight = false; + cancelAsyncTasks(); + super.onDestroy(); + } +} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableContract.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableContract.java index aa4576bf..ad11c152 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableContract.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableContract.java @@ -1,9 +1,8 @@ package io.github.wulkanowy.ui.main.timetable; -import io.github.wulkanowy.di.annotations.PerActivity; +import io.github.wulkanowy.di.annotations.PerFragment; import io.github.wulkanowy.ui.base.BaseContract; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -import io.github.wulkanowy.ui.main.TabsData; public interface TimetableContract { @@ -13,14 +12,14 @@ public interface TimetableContract { void scrollViewPagerToPosition(int position); - void setTabDataToAdapter(TabsData tabsData); + void setTabDataToAdapter(String date); void setAdapterWithTabLayout(); boolean isMenuVisible(); } - @PerActivity + @PerFragment interface Presenter extends BaseContract.Presenter { void onFragmentActivated(boolean isVisible); diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.java index 5d9d96bf..99acb646 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableFragment.java @@ -17,8 +17,8 @@ import butterknife.ButterKnife; import io.github.wulkanowy.R; import io.github.wulkanowy.di.component.FragmentComponent; import io.github.wulkanowy.ui.base.BaseFragment; +import io.github.wulkanowy.ui.base.BasePagerAdapter; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -import io.github.wulkanowy.ui.main.TabsData; public class TimetableFragment extends BaseFragment implements TimetableContract.View { @@ -31,7 +31,7 @@ public class TimetableFragment extends BaseFragment implements TimetableContract TabLayout tabLayout; @Inject - TimetablePagerAdapter pagerAdapter; + BasePagerAdapter pagerAdapter; @Inject TimetableContract.Presenter presenter; @@ -63,8 +63,8 @@ public class TimetableFragment extends BaseFragment implements TimetableContract } @Override - public void setTabDataToAdapter(TabsData tabsData) { - pagerAdapter.setTabsData(tabsData); + public void setTabDataToAdapter(String date) { + pagerAdapter.addFragment(TimetableTabFragment.newInstance(date), date); } @Override diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePagerAdapter.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePagerAdapter.java deleted file mode 100644 index 0b852342..00000000 --- a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePagerAdapter.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.wulkanowy.ui.main.timetable; - -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentStatePagerAdapter; - -import io.github.wulkanowy.ui.main.TabsData; - -public class TimetablePagerAdapter extends FragmentStatePagerAdapter { - - private TabsData tabsData; - - public TimetablePagerAdapter(FragmentManager fragmentManager) { - super(fragmentManager); - } - - void setTabsData(TabsData tabsData) { - this.tabsData = tabsData; - } - - @Override - public Fragment getItem(int position) { - return tabsData.getFragment(position); - } - - - @Override - public int getCount() { - return tabsData.getFragmentsCount(); - } - - @Nullable - @Override - public CharSequence getPageTitle(int position) { - return tabsData.getTitle(position); - } -} diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java index 080ec90b..5c180236 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetablePresenter.java @@ -8,7 +8,6 @@ import javax.inject.Inject; import io.github.wulkanowy.data.RepositoryContract; import io.github.wulkanowy.ui.base.BasePresenter; import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener; -import io.github.wulkanowy.ui.main.TabsData; import io.github.wulkanowy.utils.TimeUtils; import io.github.wulkanowy.utils.async.AbstractTask; import io.github.wulkanowy.utils.async.AsyncListeners; @@ -20,8 +19,6 @@ public class TimetablePresenter extends BasePresenter private List dates = new ArrayList<>(); - private TabsData tabsData = new TabsData(); - private OnFragmentIsReadyListener listener; private int positionToScroll = 0; @@ -69,8 +66,7 @@ public class TimetablePresenter extends BasePresenter @Override public void onDoInBackgroundLoading() throws Exception { for (String date : dates) { - tabsData.addTitle(date); - tabsData.addFragment(TimetableTabFragment.newInstance(date)); + getView().setTabDataToAdapter(date); } } @@ -82,7 +78,6 @@ public class TimetablePresenter extends BasePresenter @Override public void onEndLoadingAsync(boolean result, Exception exception) { if (result) { - getView().setTabDataToAdapter(tabsData); getView().setAdapterWithTabLayout(); getView().scrollViewPagerToPosition(positionToScroll); listener.onFragmentIsReady(); diff --git a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabPresenter.java b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabPresenter.java index 1b4dd83f..ca582726 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabPresenter.java +++ b/app/src/main/java/io/github/wulkanowy/ui/main/timetable/TimetableTabPresenter.java @@ -102,6 +102,7 @@ public class TimetableTabPresenter extends BasePresenter dayList = week.getDayList(); headerItems = new ArrayList<>(); diff --git a/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java b/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java index de867816..11c1aeaf 100644 --- a/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java +++ b/app/src/main/java/io/github/wulkanowy/utils/DataObjectConverter.java @@ -7,6 +7,7 @@ import java.util.List; import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson; import io.github.wulkanowy.data.db.dao.entities.Day; import io.github.wulkanowy.data.db.dao.entities.Diary; +import io.github.wulkanowy.data.db.dao.entities.Exam; import io.github.wulkanowy.data.db.dao.entities.Grade; import io.github.wulkanowy.data.db.dao.entities.Semester; import io.github.wulkanowy.data.db.dao.entities.Student; @@ -103,6 +104,12 @@ public final class DataObjectConverter { } public static Day dayToDayEntity(io.github.wulkanowy.api.generic.Day day) { + return new Day() + .setDate(day.getDate()) + .setDayName(day.getDayName()); + } + + public static Day timetableDayToDayEntity(io.github.wulkanowy.api.timetable.TimetableDay day) { return new Day() .setDate(day.getDate()) .setDayName(day.getDayName()) @@ -123,52 +130,57 @@ public final class DataObjectConverter { List lessonEntityList = new ArrayList<>(); for (io.github.wulkanowy.api.generic.Lesson lesson : lessonList) { - lessonEntityList.add(lessonToTimetableLessonEntity(lesson)); + lessonEntityList.add(new TimetableLesson() + .setNumber(lesson.getNumber()) + .setSubject(lesson.getSubject()) + .setTeacher(lesson.getTeacher()) + .setRoom(lesson.getRoom()) + .setDescription(lesson.getDescription()) + .setGroup(lesson.getGroupName()) + .setStartTime(lesson.getStartTime()) + .setEndTime(lesson.getEndTime()) + .setDate(lesson.getDate()) + .setEmpty(lesson.isEmpty()) + .setDivisionIntoGroups(lesson.isDivisionIntoGroups()) + .setPlanning(lesson.isPlanning()) + .setRealized(lesson.isRealized()) + .setMovedOrCanceled(lesson.isMovedOrCanceled()) + .setNewMovedInOrChanged(lesson.isNewMovedInOrChanged())); } return lessonEntityList; } - private static TimetableLesson lessonToTimetableLessonEntity(io.github.wulkanowy.api.generic.Lesson lesson) { - return new TimetableLesson() - .setNumber(lesson.getNumber()) - .setSubject(lesson.getSubject()) - .setTeacher(lesson.getTeacher()) - .setRoom(lesson.getRoom()) - .setDescription(lesson.getDescription()) - .setGroup(lesson.getGroupName()) - .setStartTime(lesson.getStartTime()) - .setEndTime(lesson.getEndTime()) - .setDate(lesson.getDate()) - .setEmpty(lesson.isEmpty()) - .setDivisionIntoGroups(lesson.isDivisionIntoGroups()) - .setPlanning(lesson.isPlanning()) - .setRealized(lesson.isRealized()) - .setMovedOrCanceled(lesson.isMovedOrCanceled()) - .setNewMovedInOrChanged(lesson.isNewMovedInOrChanged()); - } - public static List lessonsToAttendanceLessonsEntities(List lessonList) { List lessonEntityList = new ArrayList<>(); for (io.github.wulkanowy.api.generic.Lesson lesson : lessonList) { - lessonEntityList.add(lessonToAttendanceLessonEntity(lesson)); + lessonEntityList.add(new AttendanceLesson() + .setNumber(Integer.valueOf(lesson.getNumber())) + .setSubject(lesson.getSubject()) + .setDate(lesson.getDate()) + .setPresence(lesson.isPresence()) + .setAbsenceUnexcused(lesson.isAbsenceUnexcused()) + .setAbsenceExcused(lesson.isAbsenceExcused()) + .setUnexcusedLateness(lesson.isUnexcusedLateness()) + .setAbsenceForSchoolReasons(lesson.isAbsenceForSchoolReasons()) + .setExcusedLateness(lesson.isExcusedLateness()) + .setExemption(lesson.isExemption())); } - return lessonEntityList; } - private static AttendanceLesson lessonToAttendanceLessonEntity(io.github.wulkanowy.api.generic.Lesson lesson) { - return new AttendanceLesson() - .setNumber(Integer.valueOf(lesson.getNumber())) - .setSubject(lesson.getSubject()) - .setDate(lesson.getDate()) - .setPresence(lesson.isPresence()) - .setAbsenceUnexcused(lesson.isAbsenceUnexcused()) - .setAbsenceExcused(lesson.isAbsenceExcused()) - .setUnexcusedLateness(lesson.isUnexcusedLateness()) - .setAbsenceForSchoolReasons(lesson.isAbsenceForSchoolReasons()) - .setExcusedLateness(lesson.isExcusedLateness()) - .setExemption(lesson.isExemption()); + public static List examsToExamsEntitiy(List examList) { + List examEntityList = new ArrayList<>(); + + for (io.github.wulkanowy.api.exams.Exam exam : examList) { + examEntityList.add(new Exam() + .setDescription(exam.getDescription()) + .setDate(exam.getEntryDate()) + .setSubjectAndGroup(exam.getSubjectAndGroup()) + .setTeacher(exam.getTeacher()) + .setType(exam.getType())); + } + return examEntityList; } } diff --git a/app/src/main/res/drawable/ic_menu_dashboard_24dp.xml b/app/src/main/res/drawable/ic_menu_dashboard_24dp.xml deleted file mode 100644 index 50726abd..00000000 --- a/app/src/main/res/drawable/ic_menu_dashboard_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_menu_exams_24dp.xml b/app/src/main/res/drawable/ic_menu_exams_24dp.xml new file mode 100644 index 00000000..66294598 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_exams_24dp.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/exams_dialog.xml b/app/src/main/res/layout/exams_dialog.xml new file mode 100644 index 00000000..5da1baac --- /dev/null +++ b/app/src/main/res/layout/exams_dialog.xml @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +