diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/ConfigUI.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/ConfigUI.kt index bd876c4c..7b39383e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/config/ConfigUI.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/ConfigUI.kt @@ -7,7 +7,6 @@ package pl.szczodrzynski.edziennik.config import pl.szczodrzynski.edziennik.config.utils.get import pl.szczodrzynski.edziennik.config.utils.getIntList import pl.szczodrzynski.edziennik.config.utils.set -import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel class ConfigUI(private val config: Config) { private var mTheme: Int? = null @@ -45,11 +44,6 @@ class ConfigUI(private val config: Config) { get() { mOpenDrawerOnBackPressed = mOpenDrawerOnBackPressed ?: config.values.get("openDrawerOnBackPressed", false); return mOpenDrawerOnBackPressed ?: false } set(value) { config.set("openDrawerOnBackPressed", value); mOpenDrawerOnBackPressed = value } - private var mHomeCards: List? = null - var homeCards: List - get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() } - set(value) { config.set("homeCards", value); mHomeCards = value } - private var mSnowfall: Boolean? = null var snowfall: Boolean get() { mSnowfall = mSnowfall ?: config.values.get("snowfall", false); return mSnowfall ?: false } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt index 00904447..5ce237a0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt @@ -7,10 +7,16 @@ package pl.szczodrzynski.edziennik.config import pl.szczodrzynski.edziennik.config.utils.get import pl.szczodrzynski.edziennik.config.utils.set import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT +import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel class ProfileConfigUI(private val config: ProfileConfig) { private var mAgendaViewType: Int? = null var agendaViewType: Int get() { mAgendaViewType = mAgendaViewType ?: config.values.get("agendaViewType", 0); return mAgendaViewType ?: AGENDA_DEFAULT } set(value) { config.set("agendaViewType", value); mAgendaViewType = value } + + private var mHomeCards: List? = null + var homeCards: List + get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() } + set(value) { config.set("homeCards", value); mHomeCards = value } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigMigration.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigMigration.kt index 39e4bd0a..8359ed0c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigMigration.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/utils/ConfigMigration.kt @@ -63,7 +63,6 @@ class ConfigMigration(app: App, config: Config) { if (dataVersion < 10) { ui.openDrawerOnBackPressed = false - ui.homeCards = listOf() ui.snowfall = false ui.bottomSheetOpened = false sync.dontShowAppManagerDialog = false diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.java index 8d11b11b..083b499a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.java @@ -61,7 +61,7 @@ public abstract class EventDao { @RawQuery(observedEntities = {Event.class}) abstract LiveData> getAll(SupportSQLiteQuery query); - public LiveData> getAll(int profileId, String filter) { + public LiveData> getAll(int profileId, String filter, String limit) { String query = "SELECT \n" + "*, \n" + "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName,\n" + @@ -75,24 +75,24 @@ public abstract class EventDao { "LEFT JOIN metadata ON eventId = thingId AND (thingType = " + TYPE_EVENT + " OR thingType = " + TYPE_HOMEWORK + ") AND metadata.profileId = "+profileId+"\n" + "WHERE events.profileId = "+profileId+" AND events.eventBlacklisted = 0 AND "+filter+"\n" + "GROUP BY eventId\n" + - "ORDER BY eventDate, eventStartTime ASC"; + "ORDER BY eventDate, eventStartTime ASC "+limit; Log.d("DB", query); return getAll(new SimpleSQLiteQuery(query)); } public LiveData> getAll(int profileId) { - return getAll(profileId, "1"); + return getAll(profileId, "1", ""); } public List getAllNow(int profileId) { return getAllNow(profileId, "1"); } public LiveData> getAllWhere(int profileId, String filter) { - return getAll(profileId, filter); + return getAll(profileId, filter, ""); } public LiveData> getAllByType(int profileId, long type, String filter) { - return getAll(profileId, "eventType = "+type+" AND "+filter); + return getAll(profileId, "eventType = "+type+" AND "+filter, ""); } public LiveData> getAllByDate(int profileId, @NonNull Date date) { - return getAll(profileId, "eventDate = '"+date.getStringY_m_d()+"'"); + return getAll(profileId, "eventDate = '"+date.getStringY_m_d()+"'", ""); } public List getAllByDateNow(int profileId, @NonNull Date date) { return getAllNow(profileId, "eventDate = '"+date.getStringY_m_d()+"'"); @@ -100,7 +100,10 @@ public abstract class EventDao { public LiveData> getAllByDateTime(int profileId, @NonNull Date date, Time time) { if (time == null) return getAllByDate(profileId, date); - return getAll(profileId, "eventDate = '"+date.getStringY_m_d()+"' AND eventStartTime = '"+time.getStringValue()+"'"); + return getAll(profileId, "eventDate = '"+date.getStringY_m_d()+"' AND eventStartTime = '"+time.getStringValue()+"'", ""); + } + public LiveData> getAllNearest(int profileId, @NonNull Date today, int limit) { + return getAll(profileId, "eventDate >= '"+today.getStringY_m_d()+"'", "LIMIT "+limit); } @RawQuery diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventListAdapter.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventListAdapter.kt index 064502ba..ef69a86f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventListAdapter.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventListAdapter.kt @@ -16,6 +16,8 @@ import pl.szczodrzynski.edziennik.utils.models.Date class EventListAdapter( val context: Context, + val simpleMode: Boolean = false, + val showDate: Boolean = false, val onItemClick: ((event: EventFull) -> Unit)? = null, val onEventEditClick: ((event: EventFull) -> Unit)? = null ) : RecyclerView.Adapter() { @@ -40,12 +42,15 @@ class EventListAdapter( val bullet = " • " + b.simpleMode = simpleMode + b.topic.text = event.topic b.details.text = mutableListOf( + if (showDate) event.eventDate.getRelativeString(context, 7) ?: event.eventDate.formattedStringShort else null, event.typeName, - event.startTime?.stringHM ?: app.getString(R.string.event_all_day), - event.subjectLongName + if (simpleMode) null else event.startTime?.stringHM ?: app.getString(R.string.event_all_day), + if (simpleMode) null else event.subjectLongName ).concat(bullet) b.addedBy.setText( diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/ProfileRemoveDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/ProfileRemoveDialog.kt index 4edb5c58..14321317 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/ProfileRemoveDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/ProfileRemoveDialog.kt @@ -75,10 +75,6 @@ class ProfileRemoveDialog( app.db.teamDao().clear(profileId) app.db.timetableDao().clear(profileId) - val homeCards = app.config.ui.homeCards.toMutableList() - homeCards.removeAll { it.profileId == profileId } - app.config.ui.homeCards = homeCards - val loginStoreId = profileObject.loginStoreId val profilesUsingLoginStore = app.db.profileDao().getIdsByLoginStoreIdNow(loginStoreId) if (profilesUsingLoginStore.size == 1) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt index 65fad773..9c0f7799 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt @@ -26,10 +26,7 @@ import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.databinding.FragmentHomeBinding import pl.szczodrzynski.edziennik.ui.dialogs.home.StudentNumberDialog -import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeDebugCard -import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeGradesCard -import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeLuckyNumberCard -import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeTimetableCard +import pl.szczodrzynski.edziennik.ui.modules.home.cards.* import pl.szczodrzynski.edziennik.utils.Themes import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem @@ -40,16 +37,21 @@ class HomeFragment : Fragment(), CoroutineScope { private const val TAG = "HomeFragment" fun swapCards(fromPosition: Int, toPosition: Int, cardAdapter: HomeCardAdapter) { - val homeCards = App.config.ui.homeCards.toMutableList() - val fromPair = homeCards[fromPosition] - homeCards[fromPosition] = homeCards[toPosition] - homeCards[toPosition] = fromPair - App.config.ui.homeCards = homeCards - val fromCard = cardAdapter.items[fromPosition] + val toCard = cardAdapter.items[toPosition] + if (fromCard.id == 100 || toCard.id == 100) { + // debug card is not swappable + return + } cardAdapter.items[fromPosition] = cardAdapter.items[toPosition] cardAdapter.items[toPosition] = fromCard cardAdapter.notifyItemMoved(fromPosition, toPosition) + + val homeCards = App.config.forProfile().ui.homeCards.toMutableList() + val fromPair = homeCards[fromPosition] + homeCards[fromPosition] = homeCards[toPosition] + homeCards[toPosition] = fromPair + App.config.forProfile().ui.homeCards = homeCards } } @@ -107,15 +109,15 @@ class HomeFragment : Fragment(), CoroutineScope { val showUnified = false - val cards = app.config.ui.homeCards.filter { it.profileId == app.profile.id }.toMutableList() + val cards = app.config.forProfile().ui.homeCards.filter { it.profileId == app.profile.id }.toMutableList() if (cards.isEmpty()) { cards += listOf( HomeCardModel(app.profile.id, HomeCard.CARD_LUCKY_NUMBER), HomeCardModel(app.profile.id, HomeCard.CARD_TIMETABLE), - /*HomeCardModel(app.profile.id, HomeCard.CARD_EVENTS),*/ + HomeCardModel(app.profile.id, HomeCard.CARD_EVENTS), HomeCardModel(app.profile.id, HomeCard.CARD_GRADES) ) - app.config.ui.homeCards = app.config.ui.homeCards.toMutableList().also { it.addAll(cards) } + app.config.forProfile().ui.homeCards = app.config.forProfile().ui.homeCards.toMutableList().also { it.addAll(cards) } } val items = mutableListOf() @@ -124,6 +126,7 @@ class HomeFragment : Fragment(), CoroutineScope { HomeCard.CARD_LUCKY_NUMBER -> HomeLuckyNumberCard(it.cardId, app, activity, this, app.profile) HomeCard.CARD_TIMETABLE -> HomeTimetableCard(it.cardId, app, activity, this, app.profile) HomeCard.CARD_GRADES -> HomeGradesCard(it.cardId, app, activity, this, app.profile) + HomeCard.CARD_EVENTS -> HomeEventsCard(it.cardId, app, activity, this, app.profile) else -> null } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeEventsCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeEventsCard.kt new file mode 100644 index 00000000..bd77efba --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeEventsCard.kt @@ -0,0 +1,107 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2020-2-28. + */ + +package pl.szczodrzynski.edziennik.ui.modules.home.cards + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.core.view.plusAssign +import androidx.core.view.setMargins +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.LinearLayoutManager +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.data.db.entity.Profile +import pl.szczodrzynski.edziennik.databinding.CardHomeEventsBinding +import pl.szczodrzynski.edziennik.dp +import pl.szczodrzynski.edziennik.onClick +import pl.szczodrzynski.edziennik.ui.dialogs.event.EventDetailsDialog +import pl.szczodrzynski.edziennik.ui.dialogs.event.EventListAdapter +import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog +import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard +import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter +import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment +import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration +import pl.szczodrzynski.edziennik.utils.models.Date +import kotlin.coroutines.CoroutineContext + +class HomeEventsCard( + override val id: Int, + val app: App, + val activity: MainActivity, + val fragment: HomeFragment, + val profile: Profile +) : HomeCard, CoroutineScope { + companion object { + private const val TAG = "HomeEventsCard" + } + + private var job: Job = Job() + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + private lateinit var adapter: EventListAdapter + + override fun bind(position: Int, holder: HomeCardAdapter.ViewHolder) { launch { + holder.root.removeAllViews() + val b = CardHomeEventsBinding.inflate(LayoutInflater.from(holder.root.context)) + b.root.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply { + setMargins(8.dp) + } + holder.root += b.root + + adapter = EventListAdapter( + activity, + simpleMode = true, + showDate = true, + onItemClick = { + EventDetailsDialog( + activity, + it + ) + }, + onEventEditClick = { + EventManualDialog( + activity, + it.profileId, + editingEvent = it + ) + } + ) + + app.db.eventDao().getAllNearest(App.profileId, Date.getToday(), 4).observe(activity, Observer { events -> + adapter.items = events + if (b.eventsView.adapter == null) { + b.eventsView.adapter = adapter + b.eventsView.apply { + isNestedScrollingEnabled = false + setHasFixedSize(true) + layoutManager = LinearLayoutManager(context) + addItemDecoration(SimpleDividerItemDecoration(context)) + } + } + adapter.notifyDataSetChanged() + + if (events != null && events.isNotEmpty()) { + b.eventsView.visibility = View.VISIBLE + b.eventsNoData.visibility = View.GONE + } else { + b.eventsView.visibility = View.GONE + b.eventsNoData.visibility = View.VISIBLE + } + }) + + holder.root.onClick { + activity.loadTarget(MainActivity.DRAWER_ITEM_AGENDA) + } + }} + + override fun unbind(position: Int, holder: HomeCardAdapter.ViewHolder) = Unit +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkAdapter.java b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkAdapter.java index 3460dd6b..c8b42fbb 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkAdapter.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/homework/HomeworkAdapter.java @@ -17,7 +17,6 @@ import androidx.recyclerview.widget.RecyclerView; import java.util.List; import pl.szczodrzynski.edziennik.App; -import pl.szczodrzynski.edziennik.ExtensionsKt; import pl.szczodrzynski.edziennik.MainActivity; import pl.szczodrzynski.edziennik.R; import pl.szczodrzynski.edziennik.data.db.full.EventFull; @@ -45,28 +44,6 @@ public class HomeworkAdapter extends RecyclerView.Adapter 0) { - if (dayDiff == 1) { - return context.getString(R.string.tomorrow); - } - else if (dayDiff == 2) { - return context.getString(R.string.the_day_after); - } - return ExtensionsKt.plural(context, R.plurals.time_till_days, Math.abs(dayDiff)); - } - else if (dayDiff < 0) { - if (dayDiff == -1) { - return context.getString(R.string.yesterday); - } - else if (dayDiff == -2) { - return context.getString(R.string.the_day_before); - } - return context.getString(R.string.ago_format, ExtensionsKt.plural(context, R.plurals.time_till_days, Math.abs(dayDiff))); - } - return context.getString(R.string.today); - } - @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { App app = (App) context.getApplicationContext(); @@ -75,7 +52,7 @@ public class HomeworkAdapter extends RecyclerView.Adapter { public int year = 0; public int month = 0; @@ -283,6 +288,37 @@ public class Date implements Comparable { } } + public static String dayDiffString(Context context, int dayDiff) { + if (dayDiff > 0) { + if (dayDiff == 1) { + return context.getString(R.string.tomorrow); + } + else if (dayDiff == 2) { + return context.getString(R.string.the_day_after); + } + return context.getString(R.string.in_format, ExtensionsKt.plural(context, R.plurals.time_till_days, Math.abs(dayDiff))); + } + else if (dayDiff < 0) { + if (dayDiff == -1) { + return context.getString(R.string.yesterday); + } + else if (dayDiff == -2) { + return context.getString(R.string.the_day_before); + } + return context.getString(R.string.ago_format, ExtensionsKt.plural(context, R.plurals.time_till_days, Math.abs(dayDiff))); + } + return context.getString(R.string.today); + } + + @Nullable + public String getRelativeString(Context context, int maxDiff) { + int diffDays = Date.diffDays(this, Date.getToday()); + if (maxDiff != 0 && diffDays > maxDiff) { + return null; + } + return dayDiffString(context, diffDays); + } + @Override public int compareTo(@NonNull Date o) { return this.getValue() - o.getValue(); diff --git a/app/src/main/res/layout/card_home_events.xml b/app/src/main/res/layout/card_home_events.xml new file mode 100644 index 00000000..598cb3bd --- /dev/null +++ b/app/src/main/res/layout/card_home_events.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/event_list_item.xml b/app/src/main/res/layout/event_list_item.xml index 8b19f9d1..c5d48310 100644 --- a/app/src/main/res/layout/event_list_item.xml +++ b/app/src/main/res/layout/event_list_item.xml @@ -6,6 +6,13 @@ + + + + + + android:fontFamily="@font/community_material_font_v3_5_95_1" + android:visibility="@{simpleMode ? View.GONE : View.VISIBLE}"/> @@ -72,6 +81,7 @@ android:textAppearance="@style/NavView.TextView.Helper" android:singleLine="true" android:ellipsize="middle" + android:visibility="@{simpleMode ? View.GONE : View.VISIBLE}" tools:text="Udostępniono 10 grudnia przez Ktoś Z Twojej Klasy • 2B3T" /> - \ No newline at end of file + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e7f1a2a7..154897ea 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1189,4 +1189,7 @@ %s - %s (%s lekcji - %s godzin %s minut) Developer mode Te ustawienia nie są przeznaczone dla zwykłych użytkowników, wyłącznie dla twórcy tej aplikacji.\n\nNie są nawet w żaden sposób opisane, nie wiadomo co robią, więc możesz nawet nie wiedzieć kiedy coś zepsujesz.\n\nWłączenie tych opcji może spowodować utratę danych w aplikacji, uszkodzenie twojego systemu lub nawet uruchomienie wirusa na baterii.\n\nLepiej uważaj. + Najbliższe wydarzenia + Nie ma więcej wydarzeń w kalendarzu. + za %s