From dbdfc7fdd88e8eba8f7cae202b717455fb342952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Thu, 14 Nov 2019 23:33:13 +0100 Subject: [PATCH] [Widget] Add new Timetable widget with APIv2. --- app/src/main/AndroidManifest.xml | 5 + .../pl/szczodrzynski/edziennik/Extensions.kt | 3 +- .../edziennik/WidgetTimetable.java | 450 ------------------ .../edziennik/WidgetTimetable.kt | 371 +++++++++++++++ .../data/db/modules/timetable/TimetableDao.kt | 71 +-- .../ui/dialogs/event/EventManualV2Dialog.kt | 9 +- .../dialogs/timetable/LessonDetailsDialog.kt | 17 +- .../models/ItemWidgetTimetableModel.java | 1 + .../widgets/WidgetConfigActivity.java | 4 +- .../widgets/timetable/LessonDialogActivity.kt | 76 +++ .../WidgetTimetableListProvider.java | 46 +- app/src/main/res/values/strings.xml | 1 + 12 files changed, 535 insertions(+), 519 deletions(-) delete mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.java create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.kt create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/widgets/timetable/LessonDialogActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dd139fc5..d842cb6d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -105,6 +105,11 @@ android:excludeFromRecents="true" android:noHistory="true" android:theme="@style/AppTheme.NoDisplay" /> + .filterOutArchived() { +fun MutableList.filterOutArchived(): MutableList { this.removeAll { it.archived } + return this } fun Activity.isStoragePermissionGranted(): Boolean { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.java b/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.java deleted file mode 100644 index 7dca917e..00000000 --- a/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.java +++ /dev/null @@ -1,450 +0,0 @@ -package pl.szczodrzynski.edziennik; - -import android.app.PendingIntent; -import android.appwidget.AppWidgetManager; -import android.appwidget.AppWidgetProvider; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.PorterDuff; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import android.util.SparseArray; -import android.view.View; -import android.widget.RemoteViews; - -import com.mikepenz.iconics.IconicsColor; -import com.mikepenz.iconics.IconicsDrawable; -import com.mikepenz.iconics.IconicsSize; -import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask; -import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull; -import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange; -import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull; -import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; -import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment; -import pl.szczodrzynski.edziennik.utils.models.Date; -import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel; -import pl.szczodrzynski.edziennik.utils.models.Time; -import pl.szczodrzynski.edziennik.utils.models.Week; -import pl.szczodrzynski.edziennik.widgets.WidgetConfig; -import pl.szczodrzynski.edziennik.widgets.timetable.LessonDetailsActivity; -import pl.szczodrzynski.edziennik.widgets.timetable.WidgetTimetableService; - -import static pl.szczodrzynski.edziennik.ExtensionsKt.filterOutArchived; -import static pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_HOMEWORK; -import static pl.szczodrzynski.edziennik.utils.Utils.bs; - - -public class WidgetTimetable extends AppWidgetProvider { - - - public static final String ACTION_SYNC_DATA = "ACTION_SYNC_DATA"; - private static final String TAG = "WidgetTimetable"; - private static int modeInt = 0; - - public WidgetTimetable() { - // Start the worker thread - //HandlerThread sWorkerThread = new HandlerThread("WidgetTimetable-worker"); - //sWorkerThread.start(); - //Handler sWorkerQueue = new Handler(sWorkerThread.getLooper()); - } - - public static SparseArray> timetables = null; - - @Override - public void onReceive(Context context, Intent intent) { - if (ACTION_SYNC_DATA.equals(intent.getAction())) { - EdziennikTask.Companion.sync().enqueue(context); - } - super.onReceive(context, intent); - } - - public static PendingIntent getPendingSelfIntent(Context context, String action) { - Intent intent = new Intent(context, WidgetTimetable.class); - intent.setAction(action); - return getPendingSelfIntent(context, intent); - } - public static PendingIntent getPendingSelfIntent(Context context, Intent intent) { - return PendingIntent.getBroadcast(context, 0, intent, 0); - } - - public static Bitmap drawableToBitmap (Drawable drawable) { - - if (drawable instanceof BitmapDrawable) { - return ((BitmapDrawable)drawable).getBitmap(); - } - - Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - drawable.draw(canvas); - - return bitmap; - } - - @Override - public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { - ComponentName thisWidget = new ComponentName(context, WidgetTimetable.class); - - timetables = new SparseArray<>(); - //timetables.clear(); - - App app = (App)context.getApplicationContext(); - - int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); - // There may be multiple widgets active, so update all of them - for (int appWidgetId : allWidgetIds) { - - //d(TAG, "thr "+Thread.currentThread().getName()); - - WidgetConfig widgetConfig = app.appConfig.widgetTimetableConfigs.get(appWidgetId); - if (widgetConfig == null) { - widgetConfig = new WidgetConfig(app.profileFirstId()); - app.appConfig.widgetTimetableConfigs.put(appWidgetId, widgetConfig); - app.appConfig.savePending = true; - } - - RemoteViews views; - if (widgetConfig.bigStyle) { - views = new RemoteViews(context.getPackageName(), widgetConfig.darkTheme ? R.layout.widget_timetable_dark_big : R.layout.widget_timetable_big); - } - else { - views = new RemoteViews(context.getPackageName(), widgetConfig.darkTheme ? R.layout.widget_timetable_dark : R.layout.widget_timetable); - } - - PorterDuff.Mode mode = PorterDuff.Mode.DST_IN; - /*if (widgetConfig.darkTheme) { - switch (modeInt) { - case 0: - mode = PorterDuff.Mode.ADD; - d(TAG, "ADD"); - break; - case 1: - mode = PorterDuff.Mode.DST_ATOP; - d(TAG, "DST_ATOP"); - break; - case 2: - mode = PorterDuff.Mode.DST_IN; - d(TAG, "DST_IN"); - break; - case 3: - mode = PorterDuff.Mode.DST_OUT; - d(TAG, "DST_OUT"); - break; - case 4: - mode = PorterDuff.Mode.DST_OVER; - d(TAG, "DST_OVER"); - break; - case 5: - mode = PorterDuff.Mode.LIGHTEN; - d(TAG, "LIGHTEN"); - break; - case 6: - mode = PorterDuff.Mode.MULTIPLY; - d(TAG, "MULTIPLY"); - break; - case 7: - mode = PorterDuff.Mode.OVERLAY; - d(TAG, "OVERLAY"); - break; - case 8: - mode = PorterDuff.Mode.SCREEN; - d(TAG, "SCREEN"); - break; - case 9: - mode = PorterDuff.Mode.SRC_ATOP; - d(TAG, "SRC_ATOP"); - break; - case 10: - mode = PorterDuff.Mode.SRC_IN; - d(TAG, "SRC_IN"); - break; - case 11: - mode = PorterDuff.Mode.SRC_OUT; - d(TAG, "SRC_OUT"); - break; - case 12: - mode = PorterDuff.Mode.SRC_OVER; - d(TAG, "SRC_OVER"); - break; - case 13: - mode = PorterDuff.Mode.XOR; - d(TAG, "XOR"); - break; - default: - modeInt = 0; - mode = PorterDuff.Mode.ADD; - d(TAG, "ADD"); - break; - } - }*/ - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { - // this code seems to crash the launcher on >= P - float transparency = widgetConfig.opacity; //0...1 - long colorFilter = 0x01000000L * (long) (255f * transparency); - try { - final Method[] declaredMethods = Class.forName("android.widget.RemoteViews").getDeclaredMethods(); - final int len = declaredMethods.length; - if (len > 0) { - for (int m = 0; m < len; m++) { - final Method method = declaredMethods[m]; - if (method.getName().equals("setDrawableParameters")) { - method.setAccessible(true); - method.invoke(views, R.id.widgetTimetableListView, true, -1, (int) colorFilter, mode, -1); - method.invoke(views, R.id.widgetTimetableHeader, true, -1, (int) colorFilter, mode, -1); - break; - } - } - } - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - } - - Intent refreshIntent = new Intent(context, WidgetTimetable.class); - refreshIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); - refreshIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); - PendingIntent pendingRefreshIntent = PendingIntent.getBroadcast(context, - 0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT); - views.setOnClickPendingIntent(R.id.widgetTimetableRefresh, pendingRefreshIntent); - - views.setOnClickPendingIntent(R.id.widgetTimetableSync, WidgetTimetable.getPendingSelfIntent(context, ACTION_SYNC_DATA)); - - views.setImageViewBitmap(R.id.widgetTimetableRefresh, new IconicsDrawable(context, CommunityMaterial.Icon2.cmd_refresh) - .color(IconicsColor.colorInt(Color.WHITE)) - .size(IconicsSize.dp(widgetConfig.bigStyle ? 24 : 16)).toBitmap()); - - views.setImageViewBitmap(R.id.widgetTimetableSync, new IconicsDrawable(context, CommunityMaterial.Icon2.cmd_sync) - .color(IconicsColor.colorInt(Color.WHITE)) - .size(IconicsSize.dp(widgetConfig.bigStyle ? 24 : 16)).toBitmap()); - - boolean unified = widgetConfig.profileId == -1; - - List profileList = new ArrayList<>(); - if (unified) { - profileList = app.db.profileDao().getAllNow(); - filterOutArchived(profileList); - } - else { - Profile profile = app.db.profileDao().getFullByIdNow(widgetConfig.profileId); - if (profile != null) { - profileList.add(profile); - } - } - - //d(TAG, "Profiles: "+ Arrays.toString(profileList.toArray())); - - if (profileList == null || profileList.size() == 0) { - views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE); - views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_profile_doesnt_exist)); - } - else { - views.setViewVisibility(R.id.widgetTimetableLoading, View.GONE); - //Register profile; - - long bellSyncDiffMillis = 0; - if (app.appConfig.bellSyncDiff != null) { - bellSyncDiffMillis = app.appConfig.bellSyncDiff.hour * 60 * 60 * 1000 + app.appConfig.bellSyncDiff.minute * 60 * 1000 + app.appConfig.bellSyncDiff.second * 1000; - bellSyncDiffMillis *= app.appConfig.bellSyncMultiplier; - bellSyncDiffMillis *= -1; - } - - List lessonList = new ArrayList<>(); - - Time syncedNow = Time.fromMillis(Time.getNow().getInMillis() + bellSyncDiffMillis); - - Date today = Date.getToday(); - - int openProfileId = -1; - Date displayingDate = null; - int displayingWeekDay = 0; - if (unified) { - views.setTextViewText(R.id.widgetTimetableSubtitle, app.getString(R.string.widget_timetable_title_unified)); - } - else { - views.setTextViewText(R.id.widgetTimetableSubtitle, profileList.get(0).getName()); - openProfileId = profileList.get(0).getId(); - } - - List lessons = app.db.lessonDao().getAllWeekNow(unified ? -1 : openProfileId, today.clone().stepForward(0, 0, -today.getWeekDay()), today); - - int scrollPos = 0; - - for (Profile profile: profileList) { - Date profileDisplayingDate = HomeFragment.findDateWithLessons(profile.getId(), lessons, syncedNow, 1); - int profileDisplayingWeekDay = profileDisplayingDate.getWeekDay(); - int dayDiff = Date.diffDays(profileDisplayingDate, Date.getToday()); - - //d(TAG, "For profile "+profile.name+" displayingDate is "+profileDisplayingDate.getStringY_m_d()); - if (displayingDate == null || profileDisplayingDate.getValue() < displayingDate.getValue()) { - displayingDate = profileDisplayingDate; - displayingWeekDay = profileDisplayingWeekDay; - //d(TAG, "Setting as global dd"); - if (dayDiff == 0) { - views.setTextViewText(R.id.widgetTimetableTitle, app.getString(R.string.day_today_format, Week.getFullDayName(displayingWeekDay))); - } else if (dayDiff == 1) { - views.setTextViewText(R.id.widgetTimetableTitle, app.getString(R.string.day_tomorrow_format, Week.getFullDayName(displayingWeekDay))); - } else { - views.setTextViewText(R.id.widgetTimetableTitle, Week.getFullDayName(displayingWeekDay) + " " + profileDisplayingDate.getStringDm()); - } - } - } - - for (Profile profile: profileList) { - int pos = 0; - - List events = app.db.eventDao().getAllByDateNow(profile.getId(), displayingDate); - if (events == null) - events = new ArrayList<>(); - - if (unified) { - ItemWidgetTimetableModel separator = new ItemWidgetTimetableModel(); - separator.profileId = profile.getId(); - separator.bigStyle = widgetConfig.bigStyle; - separator.darkTheme = widgetConfig.darkTheme; - separator.separatorProfileName = profile.getName(); - lessonList.add(separator); - } - - for (LessonFull lesson : lessons) { - //d(TAG, "Profile "+profile.id+" Lesson profileId "+lesson.profileId+" weekDay "+lesson.weekDay+", "+lesson); - if (profile.getId() != lesson.profileId || displayingWeekDay != lesson.weekDay) - continue; - //d(TAG, "Not skipped"); - ItemWidgetTimetableModel model = new ItemWidgetTimetableModel(); - - model.bigStyle = widgetConfig.bigStyle; - model.darkTheme = widgetConfig.darkTheme; - - model.profileId = profile.getId(); - - model.lessonDate = displayingDate; - model.startTime = lesson.startTime; - model.endTime = lesson.endTime; - - model.lessonPassed = (syncedNow.getValue() > lesson.endTime.getValue()) && displayingWeekDay == Week.getTodayWeekDay(); - model.lessonCurrent = (Time.inRange(lesson.startTime, lesson.endTime, syncedNow)) && displayingWeekDay == Week.getTodayWeekDay(); - - if (model.lessonCurrent) { - scrollPos = pos; - } else if (model.lessonPassed) { - scrollPos = pos + 1; - } - pos++; - - model.subjectName = bs(lesson.subjectLongName); - model.classroomName = lesson.classroomName; - - model.bellSyncDiffMillis = bellSyncDiffMillis; - - if (lesson.changeId != 0) { - if (lesson.changeType == LessonChange.TYPE_CHANGE) { - model.lessonChange = true; - if (lesson.changedClassroomName()) { - model.newClassroomName = lesson.changeClassroomName; - } - - if (lesson.changedSubjectLongName()) { - model.newSubjectName = lesson.changeSubjectLongName; - } - } - if (lesson.changeType == LessonChange.TYPE_CANCELLED) { - model.lessonCancelled = true; - } - } - - for (EventFull event : events) { - if (event.startTime == null) - continue; - if (event.eventDate.getValue() == displayingDate.getValue() - && event.startTime.getValue() == lesson.startTime.getValue()) { - model.eventColors.add(event.type == TYPE_HOMEWORK ? ItemWidgetTimetableModel.EVENT_COLOR_HOMEWORK : event.getColor()); - } - } - - lessonList.add(model); - } - } - - if (lessonList.size() == 0) { - views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE); - views.setRemoteAdapter(R.id.widgetTimetableListView, new Intent()); - views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_no_lessons)); - appWidgetManager.updateAppWidget(appWidgetId, views); - } - else { - views.setViewVisibility(R.id.widgetTimetableLoading, View.GONE); - - timetables.put(appWidgetId, lessonList); - //WidgetTimetableListProvider.widgetsLessons.put(appWidgetId, lessons); - //views.setRemoteAdapter(R.id.widgetTimetableListView, new Intent()); - Intent listIntent = new Intent(context, WidgetTimetableService.class); - listIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); - listIntent.setData(Uri.parse(listIntent.toUri(Intent.URI_INTENT_SCHEME))); - views.setRemoteAdapter(R.id.widgetTimetableListView, listIntent); - - // template to handle the click listener for each item - Intent intentTemplate = new Intent(context, LessonDetailsActivity.class); - // Old activities shouldn't be in the history stack - intentTemplate.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - PendingIntent pendingIntentTimetable = PendingIntent.getActivity(context, - 0, - intentTemplate, - 0); - views.setPendingIntentTemplate(R.id.widgetTimetableListView, pendingIntentTimetable); - - Intent openIntent = new Intent(context, MainActivity.class); - openIntent.setAction("android.intent.action.MAIN"); - if (!unified) { - openIntent.putExtra("profileId", openProfileId); - openIntent.putExtra("timetableDate", displayingDate.getValue()); - } - openIntent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE); - PendingIntent pendingOpenIntent = PendingIntent.getActivity(context, - appWidgetId, openIntent, PendingIntent.FLAG_UPDATE_CURRENT); - views.setOnClickPendingIntent(R.id.widgetTimetableHeader, pendingOpenIntent); - - if (!unified) - views.setScrollPosition(R.id.widgetTimetableListView, scrollPos); - } - } - - appWidgetManager.updateAppWidget(appWidgetId, views); - appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widgetTimetableListView); - } - //modeInt++; - } - - @Override - public void onEnabled(Context context) { - // Enter relevant functionality for when the first widget is created - } - - @Override - public void onDeleted(Context context, int[] appWidgetIds) { - App app = (App) context.getApplicationContext(); - for (int appWidgetId: appWidgetIds) { - app.appConfig.widgetTimetableConfigs.remove(appWidgetId); - } - app.saveConfig("widgetTimetableConfigs"); - } -} - diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.kt new file mode 100644 index 00000000..088f4c60 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/WidgetTimetable.kt @@ -0,0 +1,371 @@ +package pl.szczodrzynski.edziennik + +import android.app.PendingIntent +import android.appwidget.AppWidgetManager +import android.appwidget.AppWidgetProvider +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.PorterDuff +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.net.Uri +import android.os.Build +import android.util.SparseArray +import android.view.View +import android.widget.RemoteViews +import com.mikepenz.iconics.IconicsDrawable +import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial +import com.mikepenz.iconics.utils.colorInt +import com.mikepenz.iconics.utils.sizeDp +import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask +import pl.szczodrzynski.edziennik.data.db.modules.events.Event.TYPE_HOMEWORK +import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson +import pl.szczodrzynski.edziennik.utils.models.Date +import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel +import pl.szczodrzynski.edziennik.utils.models.Time +import pl.szczodrzynski.edziennik.utils.models.Week +import pl.szczodrzynski.edziennik.widgets.WidgetConfig +import pl.szczodrzynski.edziennik.widgets.timetable.LessonDialogActivity +import pl.szczodrzynski.edziennik.widgets.timetable.WidgetTimetableService +import java.lang.reflect.InvocationTargetException + + +class WidgetTimetable : AppWidgetProvider() { + + override fun onReceive(context: Context, intent: Intent) { + if (ACTION_SYNC_DATA == intent.action) { + EdziennikTask.sync().enqueue(context) + } + super.onReceive(context, intent) + } + + override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { + val thisWidget = ComponentName(context, WidgetTimetable::class.java) + + timetables = SparseArray() + //timetables.clear(); + + val app = context.applicationContext as App + + var bellSyncDiffMillis: Long = 0 + if (app.appConfig.bellSyncDiff != null) { + bellSyncDiffMillis = (app.appConfig.bellSyncDiff.hour * 60 * 60 * 1000 + app.appConfig.bellSyncDiff.minute * 60 * 1000 + app.appConfig.bellSyncDiff.second * 1000).toLong() + bellSyncDiffMillis *= app.appConfig.bellSyncMultiplier.toLong() + bellSyncDiffMillis *= -1 + } + + val allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget) + + allWidgetIds?.forEach { appWidgetId -> + var widgetConfig = app.appConfig.widgetTimetableConfigs[appWidgetId] + if (widgetConfig == null) { + widgetConfig = WidgetConfig(app.profileFirstId()) + app.appConfig.widgetTimetableConfigs[appWidgetId] = widgetConfig + app.appConfig.savePending = true + } + + val views = if (widgetConfig.bigStyle) { + RemoteViews(context.packageName, if (widgetConfig.darkTheme) R.layout.widget_timetable_dark_big else R.layout.widget_timetable_big) + } else { + RemoteViews(context.packageName, if (widgetConfig.darkTheme) R.layout.widget_timetable_dark else R.layout.widget_timetable) + } + + val refreshIntent = Intent(app, WidgetTimetable::class.java) + refreshIntent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE + refreshIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds) + val pendingRefreshIntent = PendingIntent.getBroadcast(context, + 0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT) + views.setOnClickPendingIntent(R.id.widgetTimetableRefresh, pendingRefreshIntent) + + views.setOnClickPendingIntent(R.id.widgetTimetableSync, getPendingSelfIntent(context, ACTION_SYNC_DATA)) + + views.setImageViewBitmap(R.id.widgetTimetableRefresh, IconicsDrawable(context, CommunityMaterial.Icon2.cmd_refresh) + .colorInt(Color.WHITE) + .sizeDp(if (widgetConfig.bigStyle) 24 else 16).toBitmap()) + + views.setImageViewBitmap(R.id.widgetTimetableSync, IconicsDrawable(context, CommunityMaterial.Icon2.cmd_sync) + .colorInt(Color.WHITE) + .sizeDp(if (widgetConfig.bigStyle) 24 else 16).toBitmap()) + + prepareAppWidget(app, appWidgetId, views, widgetConfig, bellSyncDiffMillis) + + appWidgetManager.updateAppWidget(appWidgetId, views) + appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widgetTimetableListView) + } + } + + private fun prepareAppWidget( + app: App, + appWidgetId: Int, + views: RemoteViews, + widgetConfig: WidgetConfig, + bellSyncDiffMillis: Long + ) { + // get the current bell-synced time + val now = Time.fromMillis(Time.getNow().inMillis + bellSyncDiffMillis) + + // set the widget transparency + val mode = PorterDuff.Mode.DST_IN + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + // this code seems to crash the launcher on >= P + val transparency = widgetConfig.opacity //0...1 + val colorFilter = 0x01000000L * (255f * transparency).toLong() + try { + val declaredMethods = Class.forName("android.widget.RemoteViews").declaredMethods + val len = declaredMethods.size + if (len > 0) { + for (m in 0 until len) { + val method = declaredMethods[m] + if (method.name == "setDrawableParameters") { + method.isAccessible = true + method.invoke(views, R.id.widgetTimetableListView, true, -1, colorFilter.toInt(), mode, -1) + method.invoke(views, R.id.widgetTimetableHeader, true, -1, colorFilter.toInt(), mode, -1) + break + } + } + } + } catch (e: ClassNotFoundException) { + e.printStackTrace() + } catch (e: InvocationTargetException) { + e.printStackTrace() + } catch (e: IllegalAccessException) { + e.printStackTrace() + } catch (e: IllegalArgumentException) { + e.printStackTrace() + } + } + + val unified = widgetConfig.profileId == -1 + + // get all profiles or one profile with the specified id + val profileList = if (unified) + app.db.profileDao().allNow.filterOutArchived() + else + listOfNotNull(app.db.profileDao().getByIdNow(widgetConfig.profileId)) + + // no profile was found + if (profileList.isEmpty()) { + views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE) + views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_profile_doesnt_exist)) + return + } + + views.setViewVisibility(R.id.widgetTimetableLoading, View.GONE) + + // set lesson search bounds + val today = Date.getToday() + val searchEnd = today.clone().stepForward(0, 0, 7) + + var scrollPos = 0 + + var profileId: Int? = null + var displayingDate: Date? = null + + val models = mutableListOf() + + // get all lessons within the search bounds + val lessonList = app.db.timetableDao().getBetweenDatesNow(today, searchEnd) + + for (profile in profileList) { + + // add a profile separator with its name + if (unified) { + val separator = ItemWidgetTimetableModel() + separator.profileId = profile.id + separator.bigStyle = widgetConfig.bigStyle + separator.darkTheme = widgetConfig.darkTheme + separator.separatorProfileName = profile.name + models.add(separator) + } + + // search for lessons to display + val timetableDate = Date.getToday() + var checkedDays = 0 + var lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate } + while ((lessons.isEmpty() || lessons.none { + it.displayDate != today || (it.displayDate == today && it.displayEndTime != null && it.displayEndTime!! >= now) + }) && checkedDays < 7) { + timetableDate.stepForward(0, 0, 1) + lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate } + checkedDays++ + } + + // set the displayingDate to show in the header + if (!unified) { + if (lessons.isNotEmpty()) + displayingDate = timetableDate + profileId = profile.id + } + + // get all events for the current date + val events = app.db.eventDao().getAllByDateNow(profile.id, timetableDate)?.filterNotNull() ?: emptyList() + + lessons.forEachIndexed { pos, lesson -> + val model = ItemWidgetTimetableModel() + + model.bigStyle = widgetConfig.bigStyle + model.darkTheme = widgetConfig.darkTheme + + model.profileId = profile.id + + model.lessonId = lesson.id + model.lessonDate = timetableDate + model.startTime = lesson.startTime + model.endTime = lesson.endTime + + // check if the lesson has already passed or it's currently in progress + if (lesson.displayDate == today) { + lesson.displayEndTime?.let { endTime -> + model.lessonPassed = now > endTime + lesson.displayStartTime?.let { startTime -> + model.lessonCurrent = now in startTime..endTime + } + } + } + + // set where should the list view scroll to + if (model.lessonCurrent) { + scrollPos = pos + } else if (model.lessonPassed) { + scrollPos = pos + 1 + } + + // set the subject and classroom name + model.subjectName = lesson.displaySubjectName + model.classroomName = lesson.displayClassroom + + // set the bell sync to calculate progress in ListProvider + model.bellSyncDiffMillis = bellSyncDiffMillis + + // make the model aware of the lesson type + when (lesson.type) { + Lesson.TYPE_CANCELLED -> { + model.lessonCancelled = true + } + Lesson.TYPE_CHANGE, + Lesson.TYPE_SHIFTED_SOURCE, + Lesson.TYPE_SHIFTED_TARGET -> { + model.lessonChange = true + } + } + + // add every event on this lesson + for (event in events) { + if (event.startTime != null && event.startTime != lesson.displayStartTime) + continue + model.eventColors.add(if (event.type == TYPE_HOMEWORK) ItemWidgetTimetableModel.EVENT_COLOR_HOMEWORK else event.getColor()) + } + + models += model + } + } + + if (unified) { + // set the title for an unified widget + views.setTextViewText(R.id.widgetTimetableTitle, app.getString(R.string.widget_timetable_title_unified)) + views.setViewVisibility(R.id.widgetTimetableSubtitle, View.GONE) + } else { + // set the title to present the widget's profile + views.setTextViewText(R.id.widgetTimetableTitle, profileList[0].name) + views.setViewVisibility(R.id.widgetTimetableTitle, View.VISIBLE) + // make the subtitle show current date for these lessons + displayingDate?.let { + when (Date.diffDays(it, Date.getToday())) { + 0 -> views.setTextViewText(R.id.widgetTimetableSubtitle, app.getString(R.string.day_today_format, Week.getFullDayName(it.weekDay))) + 1 -> views.setTextViewText(R.id.widgetTimetableSubtitle, app.getString(R.string.day_tomorrow_format, Week.getFullDayName(it.weekDay))) + else -> views.setTextViewText(R.id.widgetTimetableSubtitle, Week.getFullDayName(it.weekDay) + " " + it.formattedString) + } + } + } + + // intent running when the header is clicked + val openIntent = Intent(app, MainActivity::class.java) + openIntent.action = "android.intent.action.MAIN" + if (!unified) { + // per-profile widget should redirect to it + correct day + profileId?.let { + openIntent.putExtra("profileId", it) + } + displayingDate?.let { + openIntent.putExtra("timetableDate", it.value) + } + } + openIntent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE) + val pendingOpenIntent = PendingIntent.getActivity(app, appWidgetId, openIntent, 0) + views.setOnClickPendingIntent(R.id.widgetTimetableHeader, pendingOpenIntent) + + if (lessonList.isEmpty()) { + views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE) + views.setRemoteAdapter(R.id.widgetTimetableListView, Intent()) + views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_no_lessons)) + return + } + + timetables!!.put(appWidgetId, models) + + // apply the list service to the list view + val listIntent = Intent(app, WidgetTimetableService::class.java) + listIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) + listIntent.data = Uri.parse(listIntent.toUri(Intent.URI_INTENT_SCHEME)) + views.setRemoteAdapter(R.id.widgetTimetableListView, listIntent) + + // create an intent used to display the lesson details dialog + val intentTemplate = Intent(app, LessonDialogActivity::class.java) + intentTemplate.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + val pendingIntentTimetable = PendingIntent.getActivity(app, appWidgetId, intentTemplate, 0) + views.setPendingIntentTemplate(R.id.widgetTimetableListView, pendingIntentTimetable) + + if (!unified) + views.setScrollPosition(R.id.widgetTimetableListView, scrollPos) + } + + override fun onEnabled(context: Context) { + // Enter relevant functionality for when the first widget is created + } + + override fun onDeleted(context: Context, appWidgetIds: IntArray) { + val app = context.applicationContext as App + for (appWidgetId in appWidgetIds) { + app.appConfig.widgetTimetableConfigs.remove(appWidgetId) + } + app.saveConfig("widgetTimetableConfigs") + } + + companion object { + + + val ACTION_SYNC_DATA = "ACTION_SYNC_DATA" + private val TAG = "WidgetTimetable" + private val modeInt = 0 + + var timetables: SparseArray>? = null + + fun getPendingSelfIntent(context: Context, action: String): PendingIntent { + val intent = Intent(context, WidgetTimetable::class.java) + intent.action = action + return getPendingSelfIntent(context, intent) + } + + fun getPendingSelfIntent(context: Context, intent: Intent): PendingIntent { + return PendingIntent.getBroadcast(context, 0, intent, 0) + } + + fun drawableToBitmap(drawable: Drawable): Bitmap { + + if (drawable is BitmapDrawable) { + return drawable.bitmap + } + + val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + drawable.setBounds(0, 0, canvas.width, canvas.height) + drawable.draw(canvas) + + return bitmap + } + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt index fc566ac5..14db6253 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt @@ -10,6 +10,27 @@ import pl.szczodrzynski.edziennik.utils.models.Date @Dao interface TimetableDao { + companion object { + private const val QUERY = """ + SELECT + timetable.*, + subjects.subjectLongName AS subjectName, + teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName, + teams.teamName AS teamName, + oldS.subjectLongName AS oldSubjectName, + oldT.teacherName ||" "|| oldT.teacherSurname AS oldTeacherName, + oldG.teamName AS oldTeamName, + metadata.seen, metadata.notified, metadata.addedDate + FROM timetable + LEFT JOIN subjects USING(profileId, subjectId) + LEFT JOIN teachers USING(profileId, teacherId) + LEFT JOIN teams USING(profileId, teamId) + LEFT JOIN subjects AS oldS ON timetable.profileId = oldS.profileId AND timetable.oldSubjectId = oldS.subjectId + LEFT JOIN teachers AS oldT ON timetable.profileId = oldT.profileId AND timetable.oldTeacherId = oldT.teacherId + LEFT JOIN teams AS oldG ON timetable.profileId = oldG.profileId AND timetable.oldTeamId = oldG.teamId + LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId + """ + } @Insert(onConflict = OnConflictStrategy.REPLACE) operator fun plusAssign(lessonList: List) @@ -25,49 +46,31 @@ interface TimetableDao { fun clearBetweenDates(profileId: Int, dateFrom: Date, dateTo: Date) @Query(""" - SELECT - timetable.*, - subjects.subjectLongName AS subjectName, - teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName, - teams.teamName AS teamName, - oldS.subjectLongName AS oldSubjectName, - oldT.teacherName ||" "|| oldT.teacherSurname AS oldTeacherName, - oldG.teamName AS oldTeamName, - metadata.seen, metadata.notified, metadata.addedDate - FROM timetable - LEFT JOIN subjects USING(profileId, subjectId) - LEFT JOIN teachers USING(profileId, teacherId) - LEFT JOIN teams USING(profileId, teamId) - LEFT JOIN subjects AS oldS ON timetable.profileId = oldS.profileId AND timetable.oldSubjectId = oldS.subjectId - LEFT JOIN teachers AS oldT ON timetable.profileId = oldT.profileId AND timetable.oldTeacherId = oldT.teacherId - LEFT JOIN teams AS oldG ON timetable.profileId = oldG.profileId AND timetable.oldTeamId = oldG.teamId - LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId + $QUERY WHERE timetable.profileId = :profileId AND (type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date) ORDER BY id, type """) fun getForDate(profileId: Int, date: Date) : LiveData> @Query(""" - SELECT - timetable.*, - subjects.subjectLongName AS subjectName, - teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName, - teams.teamName AS teamName, - oldS.subjectLongName AS oldSubjectName, - oldT.teacherName ||" "|| oldT.teacherSurname AS oldTeacherName, - oldG.teamName AS oldTeamName, - metadata.seen, metadata.notified, metadata.addedDate - FROM timetable - LEFT JOIN subjects USING(profileId, subjectId) - LEFT JOIN teachers USING(profileId, teacherId) - LEFT JOIN teams USING(profileId, teamId) - LEFT JOIN subjects AS oldS ON timetable.profileId = oldS.profileId AND timetable.oldSubjectId = oldS.subjectId - LEFT JOIN teachers AS oldT ON timetable.profileId = oldT.profileId AND timetable.oldTeacherId = oldT.teacherId - LEFT JOIN teams AS oldG ON timetable.profileId = oldG.profileId AND timetable.oldTeamId = oldG.teamId - LEFT JOIN metadata ON id = thingId AND thingType = ${Metadata.TYPE_LESSON_CHANGE} AND metadata.profileId = timetable.profileId + $QUERY WHERE timetable.profileId = :profileId AND ((type != 3 AND date > :today) OR ((type = 3 OR type = 1) AND oldDate > :today)) AND timetable.subjectId = :subjectId ORDER BY id, type LIMIT 1 """) fun getNextWithSubject(profileId: Int, today: Date, subjectId: Long) : LiveData + + @Query(""" + $QUERY + WHERE (type != 3 AND date >= :dateFrom AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom AND oldDate <= :dateTo) + ORDER BY profileId, id, type + """) + fun getBetweenDatesNow(dateFrom: Date, dateTo: Date) : List + + @Query(""" + $QUERY + WHERE timetable.profileId = :profileId AND timetable.id = :lessonId + ORDER BY id, type + """) + fun getByIdNow(profileId: Int, lessonId: Long) : LessonFull? } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualV2Dialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualV2Dialog.kt index 64644fb7..faaab700 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualV2Dialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/event/EventManualV2Dialog.kt @@ -30,7 +30,9 @@ class EventManualV2Dialog( val defaultDate: Date? = null, val defaultTime: Time? = null, val defaultType: Int? = null, - val editingEvent: Event? = null + val editingEvent: Event? = null, + val onShowListener: ((tag: String) -> Unit)? = null, + val onDismissListener: ((tag: String) -> Unit)? = null ) : CoroutineScope { companion object { @@ -49,13 +51,16 @@ class EventManualV2Dialog( init { run { job = Job() - + onShowListener?.invoke(TAG) b = DialogEventManualV2Binding.inflate(activity.layoutInflater) dialog = MaterialAlertDialogBuilder(activity) .setTitle(R.string.dialog_event_manual_title) .setView(b.root) .setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() } .setPositiveButton(R.string.save) { _, _ -> saveEvent() } + .setOnDismissListener { + onDismissListener?.invoke(TAG) + } .show() event = editingEvent?.clone() ?: Event().also { event -> diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt index 325cf419..2ad4557b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/timetable/LessonDetailsDialog.kt @@ -21,7 +21,9 @@ import pl.szczodrzynski.edziennik.utils.models.Week class LessonDetailsDialog( val activity: AppCompatActivity, - val lesson: LessonFull + val lesson: LessonFull, + val onShowListener: ((tag: String) -> Unit)? = null, + val onDismissListener: ((tag: String) -> Unit)? = null ) { companion object { private const val TAG = "LessonDetailsDialog" @@ -31,6 +33,7 @@ class LessonDetailsDialog( private lateinit var dialog: AlertDialog init { run { + onShowListener?.invoke(TAG) b = DialogLessonDetailsBinding.inflate(activity.layoutInflater) dialog = MaterialAlertDialogBuilder(activity) .setView(b.root) @@ -38,8 +41,13 @@ class LessonDetailsDialog( dialog.dismiss() } .setNeutralButton(R.string.add) { dialog, _ -> - dialog.dismiss() - EventManualV2Dialog(activity, lesson.profileId, lesson) + EventManualV2Dialog( + activity, + lesson.profileId, + lesson, + onShowListener = onShowListener, + onDismissListener = onDismissListener + ) /*MaterialAlertDialogBuilder(activity) .setItems(R.array.main_menu_add_options) { dialog2, which -> dialog2.dismiss() @@ -59,6 +67,9 @@ class LessonDetailsDialog( .setNegativeButton(R.string.cancel) { dialog2, _ -> dialog2.dismiss() } .show()*/ } + .setOnDismissListener { + onDismissListener?.invoke(TAG) + } .show() update() }} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemWidgetTimetableModel.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemWidgetTimetableModel.java index 479845da..0ddd210a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemWidgetTimetableModel.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemWidgetTimetableModel.java @@ -9,6 +9,7 @@ public class ItemWidgetTimetableModel { public String separatorProfileName = null; public int profileId; + public long lessonId; public Date lessonDate; public Time startTime; public Time endTime; diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/WidgetConfigActivity.java b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/WidgetConfigActivity.java index 4004109c..38d2814d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/WidgetConfigActivity.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/WidgetConfigActivity.java @@ -21,8 +21,8 @@ import java.util.List; import pl.szczodrzynski.edziennik.App; import pl.szczodrzynski.edziennik.R; import pl.szczodrzynski.edziennik.WidgetTimetable; -import pl.szczodrzynski.edziennik.databinding.DialogWidgetConfigBinding; import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile; +import pl.szczodrzynski.edziennik.databinding.DialogWidgetConfigBinding; import pl.szczodrzynski.edziennik.widgets.luckynumber.WidgetLuckyNumber; import pl.szczodrzynski.edziennik.widgets.notifications.WidgetNotifications; @@ -78,7 +78,7 @@ public class WidgetConfigActivity extends Activity { AsyncTask.execute(() -> { profileList = app.db.profileDao().getAllNow(); - filterOutArchived(profileList); + profileList = filterOutArchived(profileList); if (widgetType == WIDGET_NOTIFICATIONS) this.runOnUiThread(this::configure); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/timetable/LessonDialogActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/timetable/LessonDialogActivity.kt new file mode 100644 index 00000000..fd118390 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/timetable/LessonDialogActivity.kt @@ -0,0 +1,76 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2019-11-14. + */ + +package pl.szczodrzynski.edziennik.widgets.timetable + +import android.content.Intent +import android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import kotlinx.coroutines.* +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.ui.dialogs.timetable.LessonDetailsDialog +import pl.szczodrzynski.edziennik.utils.Themes +import kotlin.coroutines.CoroutineContext + +class LessonDialogActivity : AppCompatActivity(), CoroutineScope { + companion object { + private const val TAG = "LessonDialogActivity" + } + + private lateinit var job: Job + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + private val shownDialogs = hashSetOf() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + window.setBackgroundDrawable(ColorDrawable(0)) + + job = Job() + + setTheme(Themes.appThemeNoDisplay) + + val app = application as App + launch { + val deferred = async(Dispatchers.Default) { + val extras = intent?.extras + + val profileId = extras?.getInt("profileId") ?: return@async null + + if (extras.getBoolean("separatorItem", false)) { + val i = Intent(app, MainActivity::class.java) + .putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE) + .putExtra("profileId", profileId) + .addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT) + app.startActivity(i) + finish() + return@async null + } + + val lessonId = extras.getLong("lessonId") + + app.db.timetableDao().getByIdNow(profileId, lessonId) + } + val lesson = deferred.await() + lesson?.let { + LessonDetailsDialog( + this@LessonDialogActivity, + lesson, + onShowListener = { tag -> + shownDialogs.add(tag) + }, + onDismissListener = { tag -> + shownDialogs.remove(tag) + if (shownDialogs.isEmpty()) + finish() + } + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/timetable/WidgetTimetableListProvider.java b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/timetable/WidgetTimetableListProvider.java index 2872c15f..83881d8d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/widgets/timetable/WidgetTimetableListProvider.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/widgets/timetable/WidgetTimetableListProvider.java @@ -12,13 +12,14 @@ import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; -import androidx.annotation.DrawableRes; import android.text.Html; import android.util.Log; import android.view.View; import android.widget.RemoteViews; import android.widget.RemoteViewsService; +import androidx.annotation.DrawableRes; + import com.mikepenz.iconics.IconicsColor; import com.mikepenz.iconics.IconicsDrawable; import com.mikepenz.iconics.IconicsSize; @@ -62,7 +63,7 @@ public class WidgetTimetableListProvider implements RemoteViewsService.RemoteVie public void onDataSetChanged() { // executed EVERY TIME Log.d(TAG, "onDataSetChanged for appWidgetId: "+appWidgetId); - lessons = WidgetTimetable.timetables == null ? null : WidgetTimetable.timetables.get(appWidgetId); + lessons = WidgetTimetable.Companion.getTimetables() == null ? null : WidgetTimetable.Companion.getTimetables().get(appWidgetId); } @Override @@ -163,9 +164,13 @@ public class WidgetTimetableListProvider implements RemoteViewsService.RemoteVie Intent intent = new Intent(); intent.putExtra("profileId", lesson.profileId); - intent.putExtra("date", lesson.lessonDate.getStringValue()); - intent.putExtra("startTime", lesson.startTime.getStringValue()); - intent.putExtra("endTime", lesson.endTime.getStringValue()); + intent.putExtra("lessonId", lesson.lessonId); + if (lesson.lessonDate != null) + intent.putExtra("date", lesson.lessonDate.getStringValue()); + if (lesson.startTime != null) + intent.putExtra("startTime", lesson.startTime.getStringValue()); + if (lesson.endTime != null) + intent.putExtra("endTime", lesson.endTime.getStringValue()); views.setOnClickFillInIntent(R.id.widgetTimetableRoot, intent); views.setTextViewText(R.id.widgetTimetableTime, lesson.startTime.getStringHM() + " - " + lesson.endTime.getStringHM()); @@ -239,30 +244,18 @@ public class WidgetTimetableListProvider implements RemoteViewsService.RemoteVie } } } - //views.setViewVisibility(R.id.widgetTimetableEvent1, View.VISIBLE); - //views.setBitmap(R.id.widgetTimetableEvent1, "setImageBitmap", getColoredBitmap(context, R.drawable.event_color_circle, 0xff4caf50, eventIndicatorSize, eventIndicatorSize)); + + if (lesson.subjectName == null) { + lesson.subjectName = context.getString(R.string.timetable_no_subject_name); + } + if (lesson.classroomName == null) { + lesson.classroomName = context.getString(R.string.timetable_no_classroom); + } views.setViewVisibility(R.id.widgetTimetableOldSubjectName, View.GONE); if (lesson.lessonChange) { - if (lesson.newSubjectName == null) { - views.setTextViewText(R.id.widgetTimetableSubjectName, Html.fromHtml(""+lesson.subjectName+"")); - } - else { - views.setViewVisibility(R.id.widgetTimetableOldSubjectName, View.VISIBLE); - views.setTextViewText(R.id.widgetTimetableOldSubjectName, Html.fromHtml(""+lesson.subjectName+"")); - views.setTextViewText(R.id.widgetTimetableSubjectName, lesson.newSubjectName); - } - - if (lesson.newClassroomName == null) { - if (lesson.classroomName == null || lesson.classroomName.equals("")) { - lesson.classroomName = context.getString(R.string.timetable_no_classroom); - } - views.setTextViewText(R.id.widgetTimetableClassroomName, lesson.classroomName); - } - else { - views.setTextViewText(R.id.widgetTimetableClassroomName, Html.fromHtml(""+lesson.newClassroomName+"")); - } - + views.setTextViewText(R.id.widgetTimetableSubjectName, Html.fromHtml(""+lesson.subjectName+"")); + views.setTextViewText(R.id.widgetTimetableClassroomName, Html.fromHtml(""+lesson.classroomName+"")); } else if (lesson.lessonCancelled) { views.setTextViewText(R.id.widgetTimetableSubjectName, Html.fromHtml(""+lesson.subjectName+"")); @@ -272,7 +265,6 @@ public class WidgetTimetableListProvider implements RemoteViewsService.RemoteVie views.setTextViewText(R.id.widgetTimetableSubjectName, lesson.subjectName); views.setTextViewText(R.id.widgetTimetableClassroomName, lesson.classroomName); } - } else if (!triedToReload) { // try to reload the widget diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 936cf55e..95ff61c1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1025,4 +1025,5 @@ Profil został usunięty. Wystąpił błąd Synchronizacja ręczna + (brak nazwy)