refactor: out with the old, in with the new

This commit is contained in:
pml68 2024-03-08 22:43:52 +01:00
parent 8488921075
commit 1933b84f68
16 changed files with 951 additions and 1066 deletions

View File

@ -1,8 +0,0 @@
package hu.refilc.naplo;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterFragmentActivity;
public class MainActivity extends FlutterFragmentActivity {
}

View File

@ -0,0 +1,5 @@
package hu.refilc.naplo
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity()

View File

@ -1,103 +0,0 @@
package hu.refilc.naplo.database;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.sql.SQLException;
import hu.refilc.naplo.database.SQLiteHelper;
public class DBManager {
private Context context;
private SQLiteDatabase database;
private SQLiteHelper dbHelper;
public DBManager(Context c) {
this.context = c;
}
public DBManager open() throws SQLException {
this.dbHelper = new SQLiteHelper(this.context);
this.database = this.dbHelper.getWritableDatabase();
return this;
}
public void close() {
this.dbHelper.close();
}
public Cursor fetchWidget(int wid) {
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_WIDGETS, new String[]{SQLiteHelper._ID, SQLiteHelper.DAY_SEL}, SQLiteHelper._ID + " = " + wid, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
public Cursor fetchTimetable() {
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_USER_DATA, new String[]{SQLiteHelper.TIMETABLE}, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
public Cursor fetchLastUser() {
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.LAST_ACCOUNT_ID}, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
public Cursor fetchTheme() {
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.THEME, SQLiteHelper.CUSTOM_ACCENT_COLOR, SQLiteHelper.CUSTOM_BACKGROUND_COLOR}, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
public Cursor fetchLocale() {
Cursor cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, new String[]{SQLiteHelper.LOCALE}, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
public void deleteWidget(int _id) {
this.database.delete(SQLiteHelper.TABLE_NAME_WIDGETS, "_id=" + _id, null);
}
/*public void changeSettings(int _id, Map<String, String> map) {
ContentValues con = new ContentValues();
for(Map.Entry<String, String> e: map.entrySet()){
con.put(e.getKey(), e.getValue());
}
this.database.update(SQLiteHelper.TABLE_NAME_WIDGETS, con, "_id = " + _id, null);
}
public void insertSettings(int _id, Map<String, String> map) {
ContentValues con = new ContentValues();
for(Map.Entry<String, String> e: map.entrySet()){
con.put(e.getKey(), e.getValue());
//Log.d("Settings added", e.getKey() + " - " + e.getValue());
}
this.database.insert(SQLiteHelper.TABLE_NAME_WIDGETS, null, con);
}*/
public void insertSelDay(int _id, int day_sel) {
ContentValues con = new ContentValues();
con.put(SQLiteHelper._ID, _id);
con.put(SQLiteHelper.DAY_SEL, day_sel);
this.database.insert(SQLiteHelper.TABLE_NAME_WIDGETS, null, con);
}
public int update(int _id, int day_sel) {
ContentValues con = new ContentValues();
con.put(SQLiteHelper.DAY_SEL, day_sel);
return this.database.update(SQLiteHelper.TABLE_NAME_WIDGETS, con, SQLiteHelper._ID + " = " + _id, null);
}
}

View File

@ -0,0 +1,73 @@
package hu.refilc.naplo.database
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import java.sql.SQLException
import hu.refilc.naplo.database.SQLiteHelper
import kotlin.arrayOf
class DBManager(private val context: Context) {
private lateinit var database: SQLiteDatabase
private lateinit var dbHelper: SQLiteHelper
fun open(): DBManager {
this.dbHelper = SQLiteHelper(this.context)
this.database = this.dbHelper.getWritableDatabase()
return this
}
fun close() {
this.dbHelper.close()
}
fun fetchWidget(wid: Int): Cursor {
val cursor: Cursor = this.database.query(SQLiteHelper.TABLE_NAME_WIDGETS, arrayOf(SQLiteHelper._ID, SQLiteHelper.DAY_SEL), "${SQLiteHelper._ID} = $wid", null, null, null, null)
if (cursor != null) cursor.moveToFirst()
return cursor
}
fun fetchTimetable(): Cursor {
val cursor: Cursor = this.database.query(SQLiteHelper.TABLE_NAME_USER_DATA, arrayOf(SQLiteHelper.TIMETABLE), null, null, null, null, null)
if (cursor != null) cursor.moveToFirst()
return cursor
}
fun fetchLastUser(): Cursor {
val cursor: Cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, arrayOf(SQLiteHelper.LAST_ACCOUNT_ID), null, null, null, null, null)
if (cursor != null) cursor.moveToFirst()
return cursor
}
fun fetchTheme(): Cursor {
val cursor: Cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, arrayOf(SQLiteHelper.THEME, SQLiteHelper.CUSTOM_ACCENT_COLOR, SQLiteHelper.CUSTOM_BACKGROUND_COLOR), null, null, null, null, null)
if (cursor != null) cursor.moveToFirst()
return cursor
}
fun fetchLocale(): Cursor {
val cursor: Cursor = this.database.query(SQLiteHelper.TABLE_NAME_SETTINGS, arrayOf(SQLiteHelper.LOCALE), null, null, null, null, null)
if (cursor != null) cursor.moveToFirst()
return cursor
}
fun deleteWidget(_id: Int) {
this.database.delete(SQLiteHelper.TABLE_NAME_WIDGETS, "_id=$_id", null)
}
fun insertSelDay(_id: Int, day_sel: Int) {
val con: ContentValues = ContentValues()
con.put(SQLiteHelper._ID, _id)
con.put(SQLiteHelper.DAY_SEL, day_sel)
this.database.insert(SQLiteHelper.TABLE_NAME_WIDGETS, null, con)
}
fun update(_id: Int, day_sel: Int): Int {
val con: ContentValues = ContentValues()
con.put(SQLiteHelper.DAY_SEL, day_sel)
return this.database.update(SQLiteHelper.TABLE_NAME_WIDGETS, con, "${SQLiteHelper._ID} = $_id", null)
}
}

View File

@ -1,35 +0,0 @@
package hu.refilc.naplo.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class SQLiteHelper extends SQLiteOpenHelper {
private static final String CREATE_TABLE_WIDGET = " create table widgets ( _id INTEGER NOT NULL, day_sel INTEGER NOT NULL);";
private static final String DB_NAME = "app.db";
private static final int DB_VERSION = 1;
public static final String _ID = "_id";
public static final String DAY_SEL = "day_sel";
public static final String TIMETABLE = "timetable";
public static final String LAST_ACCOUNT_ID = "last_account_id";
public static final String THEME = "theme";
public static final String LOCALE = "language";
public static final String CUSTOM_ACCENT_COLOR = "custom_accent_color";
public static final String CUSTOM_BACKGROUND_COLOR = "custom_background_color";
public static final String TABLE_NAME_WIDGETS = "widgets";
public static final String TABLE_NAME_USER_DATA = "user_data";
public static final String TABLE_NAME_SETTINGS = "settings";
public SQLiteHelper(Context context) {
super(context, DB_NAME, null, 7);
}
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_WIDGET);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS widgets");
onCreate(db);
}
}

View File

@ -0,0 +1,33 @@
package hu.refilc.naplo.database
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
class SQLiteHelper(context: Context): SQLiteOpenHelper(context, DB_NAME, null, 7) {
companion object {
private final val CREATE_TABLE_WIDGET: String = " create table widgets ( _id INTEGER NOT NULL, day_sel INTEGER NOT NULL);"
private final val DB_NAME: String = "app.db"
private final val DB_VERSION: Int = 1
final val _ID: String = "_id"
final val DAY_SEL: String = "day_sel"
final val TIMETABLE: String = "timetable"
final val LAST_ACCOUNT_ID: String = "last_account_id"
final val THEME: String = "theme"
final val LOCALE: String = "language"
final val CUSTOM_ACCENT_COLOR: String = "custom_accent_color"
final val CUSTOM_BACKGROUND_COLOR: String = "custom_background_color"
final val TABLE_NAME_WIDGETS: String = "widgets"
final val TABLE_NAME_USER_DATA: String = "user_data"
final val TABLE_NAME_SETTINGS: String = "settings"
}
override fun onCreate(db: SQLiteDatabase) {
db.execSQL(CREATE_TABLE_WIDGET)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE IF EXISTS widgets")
onCreate(db)
}
}

View File

@ -1,36 +0,0 @@
package hu.refilc.naplo.utils;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import java.util.Calendar;
import java.util.Date;
public class Utils {
public static boolean hasNetwork(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
public static Date getWeekStartDate() {
Calendar calendar = Calendar.getInstance();
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
calendar.add(Calendar.DATE, -1);
}
return calendar.getTime();
}
public static Date getWeekEndDate() {
Calendar calendar = Calendar.getInstance();
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
calendar.add(Calendar.DATE, 1);
}
calendar.add(Calendar.DATE, -1);
return calendar.getTime();
}
}

View File

@ -0,0 +1,41 @@
package hu.refilc.naplo.utils
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkInfo
import java.util.Calendar
import java.util.Date
class Utils {
companion object {
@JvmStatic
fun hasNetwork(context: Context): Boolean {
val cm: ConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val netInfo: NetworkInfo = cm.getActiveNetworkInfo() as NetworkInfo
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true
}
return false
}
@JvmStatic
fun getWeekStartDate(): Date {
var calendar: Calendar = Calendar.getInstance()
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
calendar.add(Calendar.DATE, -1)
}
return calendar.getTime()
}
@JvmStatic
fun getWeekEndDate(): Date {
var calendar: Calendar = Calendar.getInstance()
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
calendar.add(Calendar.DATE, 1)
}
calendar.add(Calendar.DATE, -1)
return calendar.getTime()
}
}
}

View File

@ -1,65 +0,0 @@
package hu.refilc.naplo.utils;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDate;
public class Week {
private final LocalDate start;
private final LocalDate end;
private Week(LocalDate start, LocalDate end) {
this.start = start;
this.end = end;
}
public static Week current() {
return fromDate(LocalDate.now());
}
public static Week fromId(int id) {
LocalDate _now = getYearStart().plusDays(id * 7L);
return new Week(_now.minusDays(_now.getDayOfWeek().getValue() - 1), _now.plusDays(7 - _now.getDayOfWeek().getValue()));
}
public static Week fromDate(LocalDate date) {
return new Week(date.minusDays(date.getDayOfWeek().getValue() - 1), date.plusDays(7 - date.getDayOfWeek().getValue()));
}
public Week next() {
return Week.fromDate(start.plusDays(8));
}
public int id() {
return (int) Math.ceil(Duration.between(getYearStart().atStartOfDay(), start.atStartOfDay()).toDays() / 7f);
}
private static LocalDate getYearStart() {
LocalDate now = LocalDate.now();
LocalDate start = getYearStart(now.getYear());
return start.isBefore(now) ? start : getYearStart(now.getYear() -1);
}
private static LocalDate getYearStart(int year) {
LocalDate time = LocalDate.of(year, 9, 1);
if (time.getDayOfWeek() == DayOfWeek.SATURDAY)
return time.plusDays(2);
else if (time.getDayOfWeek() == DayOfWeek.SUNDAY)
return time.plusDays(1);
return time;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Week week = (Week) o;
return this.id() == week.id();
}
@Override
public int hashCode() {
return id();
}
}

View File

@ -0,0 +1,57 @@
package hu.refilc.naplo.utils
import java.time.DayOfWeek
import java.time.Duration
import java.time.LocalDate
import kotlin.math.ceil
class Week private constructor(private final val start: LocalDate, private final val end: LocalDate) {
companion object {
fun current(): Week {
return fromDate(LocalDate.now())
}
fun fromId(id: Int): Week {
val _now: LocalDate = getYearStart().plusDays(id * 7L)
return Week(_now.minusDays(_now.getDayOfWeek().getValue() - 1L), _now.plusDays(7L - _now.getDayOfWeek().getValue()))
}
fun fromDate(date: LocalDate): Week {
return Week(date.minusDays(date.getDayOfWeek().getValue() - 1L), date.plusDays(7L - date.getDayOfWeek().getValue()))
}
private fun getYearStart(): LocalDate {
val now: LocalDate = LocalDate.now()
val start: LocalDate = getYearStart(now.getYear())
return if (start.isBefore(now)) start else getYearStart(now.getYear() - 1)
}
private fun getYearStart(year: Int): LocalDate {
val time: LocalDate = LocalDate.of(year, 9, 1)
if (time.getDayOfWeek() == DayOfWeek.SATURDAY)
return time.plusDays(2)
else if (time.getDayOfWeek() == DayOfWeek.SUNDAY)
return time.plusDays(1)
return time
}
}
fun next(): Week {
return Week.fromDate(start.plusDays(8))
}
fun id(): Int {
return Math.ceil(Duration.between(getYearStart().atStartOfDay(), start.atStartOfDay()).toDays() / 7.0).toInt()
}
override fun equals(o: Any?): Boolean {
if (this == o as Week) return true
if (o == null || Week::class != o::class) return false
val week: Week = o as Week
return this.id() == week.id()
}
override fun hashCode(): Int {
return id()
}
}

View File

@ -1,425 +0,0 @@
package hu.refilc.naplo.widget_timetable;
import android.app.PendingIntent;
import android.app.UiModeManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.Toast;
import org.joda.time.DateTime;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.time.DayOfWeek;
import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import hu.refilc.naplo.database.DBManager;
import hu.refilc.naplo.MainActivity;
import hu.refilc.naplo.R;
import hu.refilc.naplo.utils.Week;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import es.antonborri.home_widget.HomeWidgetBackgroundIntent;
import es.antonborri.home_widget.HomeWidgetLaunchIntent;
import es.antonborri.home_widget.HomeWidgetProvider;
public class WidgetTimetable extends HomeWidgetProvider {
private static final String ACTION_WIDGET_CLICK_NAV_LEFT = "list_widget.ACTION_WIDGET_CLICK_NAV_LEFT";
private static final String ACTION_WIDGET_CLICK_NAV_RIGHT = "list_widget.ACTION_WIDGET_CLICK_NAV_RIGHT";
private static final String ACTION_WIDGET_CLICK_NAV_TODAY = "list_widget.ACTION_WIDGET_CLICK_NAV_TODAY";
private static final String ACTION_WIDGET_CLICK_NAV_REFRESH = "list_widget.ACTION_WIDGET_CLICK_NAV_REFRESH";
private static final String ACTION_WIDGET_CLICK_BUY_PREMIUM = "list_widget.ACTION_WIDGET_CLICK_BUY_PREMIUM";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, SharedPreferences widgetData) {
Integer[] fullTheme = getFullTheme(context);
Integer[] textColors = getTextColors(context, fullTheme);
for (int i = 0; i < appWidgetIds.length; i++) {
RemoteViews views = generateView(context, appWidgetIds[i]);
if(userLoggedIn(context)) {
int rday = selectDay(context, appWidgetIds[i], 0, true);
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
views.setInt(R.id.nav_current, "setTextColor", getColor(context, textColors[0]));
}
pushUpdate(context, views, appWidgetIds[i]);
}
}
public static void pushUpdate(Context context, RemoteViews remoteViews, int appWidgetSingleId) {
AppWidgetManager manager = AppWidgetManager.getInstance(context);
manager.updateAppWidget(appWidgetSingleId, remoteViews);
manager.notifyAppWidgetViewDataChanged(appWidgetSingleId, R.id.widget_list);
}
public static int getColor(Context context, int color) {
return context.getResources().getColor(color);
}
public static Integer[] getTextColors(Context context, Integer[] fullTheme) {
UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
int nightMode = uiModeManager.getNightMode();
int textColor;
int textDescColor;
if (fullTheme[0] == 0 && nightMode == UiModeManager.MODE_NIGHT_NO) {
textColor = R.color.text_light;
textDescColor = R.color.text_desc_light;
} else if (fullTheme[0] == 1) {
textColor = R.color.text_light;
textDescColor = R.color.text_desc_light;
} else {
textColor = R.color.text;
textDescColor = R.color.text_desc;
}
return new Integer[]{textColor, textDescColor};
}
public static Integer[] getFullTheme(Context context) {
DBManager dbManager = new DBManager(context.getApplicationContext());
try {
dbManager.open();
Cursor cursor = dbManager.fetchTheme();
dbManager.close();
int theme = cursor.getInt(0);
int customBackgroundColor = cursor.getInt(2);
return new Integer[]{theme, customBackgroundColor};
} catch (Exception e) {
e.printStackTrace();
}
return new Integer[]{0, 0};
}
public static RemoteViews generateView(Context context, int appId) {
Integer[] fullTheme = getFullTheme(context);
Integer[] textColors = getTextColors(context, fullTheme);
Intent serviceIntent = new Intent(context, WidgetTimetableService.class);
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appId);
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_timetable);
views.setViewVisibility(R.id.need_login, View.GONE);
views.setViewVisibility(R.id.tt_grid_cont, View.GONE);
views.setInt(R.id.nav_to_left, "setColorFilter", getColor(context, textColors[1]));
views.setInt(R.id.nav_to_right, "setColorFilter", getColor(context, textColors[1]));
views.setInt(R.id.nav_refresh, "setColorFilter", getColor(context, textColors[1]));
views.setInt(R.id.empty_view, "setTextColor", getColor(context, textColors[0]));
if(!userLoggedIn(context)) {
views.setViewVisibility(R.id.need_login, View.VISIBLE);
views.setOnClickPendingIntent(R.id.open_login, makePending(context, ACTION_WIDGET_CLICK_BUY_PREMIUM, appId));
} else {
views.setViewVisibility(R.id.tt_grid_cont, View.VISIBLE);
views.setInt(R.id.widget_list, "setBackgroundColor", fullTheme[1]);
views.setInt(R.id.bottom_nav, "setBackgroundColor", fullTheme[1]);
views.setOnClickPendingIntent(R.id.nav_to_left, makePending(context, ACTION_WIDGET_CLICK_NAV_LEFT, appId));
views.setOnClickPendingIntent(R.id.nav_to_right, makePending(context, ACTION_WIDGET_CLICK_NAV_RIGHT, appId));
views.setOnClickPendingIntent(R.id.nav_current, makePending(context, ACTION_WIDGET_CLICK_NAV_TODAY, appId));
views.setOnClickPendingIntent(R.id.nav_refresh, makePending(context, ACTION_WIDGET_CLICK_NAV_REFRESH, appId));
views.setRemoteAdapter(R.id.widget_list, serviceIntent);
views.setEmptyView(R.id.widget_list, R.id.empty_view);
views.setInt(R.id.empty_view, "setBackgroundColor", fullTheme[1]);
}
return views;
}
static PendingIntent makePending(Context context, String action, int appWidgetId) {
Intent activebtnnext = new Intent(context, WidgetTimetable.class);
activebtnnext.setAction(action);
activebtnnext.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
return PendingIntent.getBroadcast(context, appWidgetId, activebtnnext , PendingIntent.FLAG_IMMUTABLE);
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
int appId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
RemoteViews views = generateView(context, appId);
try {
if(userLoggedIn(context)) {
if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_LEFT)) {
int rday = selectDay(context, appId, -1, false);
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
pushUpdate(context, views, appId);
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_RIGHT)) {
int rday = selectDay(context, appId, 1, false);
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
pushUpdate(context, views, appId);
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_TODAY)) {
int rday = getToday(context);
setSelectedDay(context, appId, rday);
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday));
pushUpdate(context, views, appId);
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_REFRESH)) {
PendingIntent pendingIntent = HomeWidgetLaunchIntent.INSTANCE.getActivity(context, MainActivity.class, Uri.parse("timetable://refresh"));
pendingIntent.send();
} else if (intent.getAction().equals("android.appwidget.action.APPWIDGET_DELETED")) {
DBManager dbManager = new DBManager(context.getApplicationContext());
try {
dbManager.open();
dbManager.deleteWidget(appId);
dbManager.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
if(intent.getAction().equals(ACTION_WIDGET_CLICK_BUY_PREMIUM)) {
PendingIntent pendingIntent = HomeWidgetLaunchIntent.INSTANCE.getActivity(context, MainActivity.class, Uri.parse("settings://premium"));
pendingIntent.send();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
public static String convertDayOfWeek(Context context, int rday) {
/*if(rday == -1) return DayOfWeek.of(1).getDisplayName(TextStyle.FULL, new Locale("hu", "HU"));
String dayOfWeek = DayOfWeek.of(rday + 1).getDisplayName(TextStyle.FULL, new Locale("hu", "HU"));*/
String dayOfWeek = "Unknown";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Locale loc = getLocale(context);
if (rday == -1)
return DayOfWeek.of(1).getDisplayName(TextStyle.FULL, loc);
dayOfWeek = DayOfWeek.of(rday + 1).getDisplayName(TextStyle.FULL, loc);
}
return dayOfWeek.substring(0, 1).toUpperCase() + dayOfWeek.substring(1).toLowerCase();
}
public static void setSelectedDay(Context context, int wid, int day) {
DBManager dbManager = new DBManager(context.getApplicationContext());
try {
dbManager.open();
dbManager.update(wid, day);
dbManager.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static int getToday(Context context) {
int rday = new DateTime().getDayOfWeek() - 1;
List<JSONArray> s = genJsonDays(context);
try {
if(checkIsAfter(s, rday)) rday += 1;
} catch (Exception e) {
e.printStackTrace();
}
return retDay(rday, s.size());
}
public static int selectDay(Context context, int wid, int add, Boolean afterSubjects) {
DBManager dbManager = new DBManager(context.getApplicationContext());
try {
dbManager.open();
Cursor cursor = dbManager.fetchWidget(wid);
List<JSONArray> s = genJsonDays(context);
int retday = new DateTime().getDayOfWeek() - 1;
if(cursor.getCount() != 0) retday = retDay(cursor.getInt(1) + add, s.size());
if(afterSubjects) if(checkIsAfter(s, retday)) retday += 1;
retday = retDay(retday, s.size());
if(cursor.getCount() == 0) dbManager.insertSelDay(wid, retday);
else dbManager.update(wid, retday);
dbManager.close();
// get the date of the first lesson
DateTime dt = new DateTime(s.get(retday).getJSONObject(0).getString("Datum"));
retday = dt.getDayOfWeek() - 1;
return retday;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
public static Boolean checkIsAfter(List<JSONArray> s, int retday) throws Exception {
retday = retDay(retday, s.size());
String vegIdopont = s.get(retday).getJSONObject(s.get(retday).length() - 1).getString("VegIdopont");
return new DateTime().isAfter(new DateTime(vegIdopont));
}
public static int retDay(int retday, int size) {
if (retday < 0) retday = size - 1;
else if (retday > size - 1) retday = 0;
return retday;
}
public static List<JSONArray> genJsonDays(Context context) {
List<JSONArray> genDays = new ArrayList<>();
Map<String, JSONArray> dayMap = new HashMap<>();
DBManager dbManager = new DBManager(context.getApplicationContext());
try {
dbManager.open();
Cursor ct = dbManager.fetchTimetable();
if (ct.getCount() == 0) {
return genDays;
}
JSONObject fetchedTimetable = new JSONObject(ct.getString(0));
String currentWeek = String.valueOf(Week.current().id());
JSONArray week = fetchedTimetable.getJSONArray(currentWeek);
// Organize lessons into dates
for (int i = 0; i < week.length(); i++) {
try {
JSONObject entry = week.getJSONObject(i);
String date = entry.getString("Datum");
dayMap.computeIfAbsent(date, k -> new JSONArray()).put(entry);
} catch (JSONException e) {
e.printStackTrace();
}
}
genDays.addAll(dayMap.values());
// Sort the 'genDays' list of JSON based on the start time of the first entry
genDays.sort((day1, day2) -> {
try {
// Extract the start time of the first entry in each day's JSON
String startTime1 = day1.getJSONObject(0).getString("KezdetIdopont");
String startTime2 = day2.getJSONObject(0).getString("KezdetIdopont");
// Compare the start times and return the result for sorting
return startTime1.compareTo(startTime2);
} catch (JSONException e) {
e.printStackTrace();
return 0;
}
});
} catch (Exception e) {
e.printStackTrace();
} finally {
dbManager.close();
}
return genDays;
}
public static String zeroPad(int value, int padding){
StringBuilder b = new StringBuilder();
b.append(value);
while(b.length() < padding){
b.insert(0,"0");
}
return b.toString();
}
public static Locale getLocale(Context context) {
DBManager dbManager = new DBManager(context.getApplicationContext());
try {
dbManager.open();
String loc = dbManager.fetchLocale().getString(0);
dbManager.close();
if(loc.equals("hu") || loc.equals("de")) {
return new Locale(loc, loc.toUpperCase());
}
} catch (Exception e) {
e.printStackTrace();
}
return new Locale("en", "GB");
}
public static boolean userLoggedIn(Context context) {
return !lastUserId(context).equals("");
}
public static String lastUserId(Context context) {
DBManager dbManager = new DBManager(context.getApplicationContext());
try {
dbManager.open();
Cursor cursor = dbManager.fetchLastUser();
dbManager.close();
if(cursor != null && !cursor.getString(0).equals("")) {
String last_user = cursor.getString(0);
return last_user;
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
@Override
public void onEnabled(Context context) {
}
@Override
public void onDisabled(Context context) {
}
}

View File

@ -0,0 +1,402 @@
package hu.refilc.naplo.widget_timetable
import android.app.PendingIntent
import android.app.UiModeManager
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.util.Log
import android.view.View
import android.widget.RemoteViews
import android.widget.Toast
import org.joda.time.DateTime
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.time.DayOfWeek
import java.time.format.TextStyle
import java.util.Collections
import java.util.Comparator
import java.util.Locale
import java.util.HashMap
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Date
import hu.refilc.naplo.database.DBManager
import hu.refilc.naplo.MainActivity
import hu.refilc.naplo.R
import hu.refilc.naplo.utils.Week
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetProvider
import kotlin.collections.mutableMapOf
class WidgetTimetable : HomeWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray,
widgetData: SharedPreferences
) {
val fullTheme: Array<Int> = getFullTheme(context)
val textColors: Array<Int> = getTextColors(context, fullTheme)
for (i in appWidgetIds.indices) {
val views: RemoteViews = generateView(context, appWidgetIds[i])
if (userLoggedIn(context)) {
val rday = selectDay(context, appWidgetIds[i], 0, true)
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday))
views.setInt(R.id.nav_current, "setTextColor", getColor(context, textColors[0]))
}
pushUpdate(context, views, appWidgetIds[i])
}
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
val appId: Int = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID
)
val views: RemoteViews = generateView(context, appId)
try {
if (userLoggedIn(context)) {
if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_LEFT)) {
val rday = selectDay(context, appId, -1, false)
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday))
pushUpdate(context, views, appId)
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_RIGHT)) {
val rday = selectDay(context, appId, 1, false)
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday))
pushUpdate(context, views, appId)
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_TODAY)) {
val rday = getToday(context)
setSelectedDay(context, appId, rday)
views.setTextViewText(R.id.nav_current, convertDayOfWeek(context, rday))
pushUpdate(context, views, appId)
} else if (intent.getAction().equals(ACTION_WIDGET_CLICK_NAV_REFRESH)) {
val pendingIntent: PendingIntent =
HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("timetable://refresh")
)
pendingIntent.send()
} else if (intent.getAction()
.equals("android.appwidget.action.APPWIDGET_DELETED")
) {
val dbManager = DBManager(context.getApplicationContext())
try {
dbManager.open()
dbManager.deleteWidget(appId)
dbManager.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
if (intent.getAction().equals(ACTION_WIDGET_CLICK_BUY_PREMIUM)) {
val pendingIntent: PendingIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("settings://premium")
)
pendingIntent.send()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
override fun onEnabled(context: Context?) {
}
override fun onDisabled(context: Context?) {
}
companion object {
private const val ACTION_WIDGET_CLICK_NAV_LEFT = "list_widget.ACTION_WIDGET_CLICK_NAV_LEFT"
private const val ACTION_WIDGET_CLICK_NAV_RIGHT =
"list_widget.ACTION_WIDGET_CLICK_NAV_RIGHT"
private const val ACTION_WIDGET_CLICK_NAV_TODAY =
"list_widget.ACTION_WIDGET_CLICK_NAV_TODAY"
private const val ACTION_WIDGET_CLICK_NAV_REFRESH =
"list_widget.ACTION_WIDGET_CLICK_NAV_REFRESH"
private const val ACTION_WIDGET_CLICK_BUY_PREMIUM =
"list_widget.ACTION_WIDGET_CLICK_BUY_PREMIUM"
fun pushUpdate(context: Context?, remoteViews: RemoteViews?, appWidgetSingleId: Int) {
val manager: AppWidgetManager = AppWidgetManager.getInstance(context)
manager.updateAppWidget(appWidgetSingleId, remoteViews)
manager.notifyAppWidgetViewDataChanged(appWidgetSingleId, R.id.widget_list)
}
fun getColor(context: Context, color: Int): Int {
return context.getResources().getColor(color)
}
fun getTextColors(context: Context, fullTheme: Array<Int>): Array<Int> {
val uiModeManager: UiModeManager =
context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
val nightMode: Int = uiModeManager.getNightMode()
val textColor: Int
val textDescColor: Int
if (fullTheme[0] == 0 && nightMode == UiModeManager.MODE_NIGHT_NO) {
textColor = R.color.text_light
textDescColor = R.color.text_desc_light
} else if (fullTheme[0] == 1) {
textColor = R.color.text_light
textDescColor = R.color.text_desc_light
} else {
textColor = R.color.text
textDescColor = R.color.text_desc
}
return arrayOf(textColor, textDescColor)
}
fun getFullTheme(context: Context): Array<Int> {
val dbManager = DBManager(context.getApplicationContext())
try {
dbManager.open()
val cursor: Cursor = dbManager.fetchTheme()
dbManager.close()
val theme: Int = cursor.getInt(0)
val customBackgroundColor: Int = cursor.getInt(2)
return arrayOf(theme, customBackgroundColor)
} catch (e: Exception) {
e.printStackTrace()
}
return arrayOf(0, 0)
}
fun generateView(context: Context, appId: Int): RemoteViews {
val fullTheme: Array<Int> = getFullTheme(context)
val textColors: Array<Int> = getTextColors(context, fullTheme)
val serviceIntent = Intent(context, WidgetTimetableService::class.java)
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appId)
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)))
val views = RemoteViews(context.getPackageName(), R.layout.widget_timetable)
views.setViewVisibility(R.id.need_login, View.GONE)
views.setViewVisibility(R.id.tt_grid_cont, View.GONE)
views.setInt(R.id.nav_to_left, "setColorFilter", getColor(context, textColors[1]))
views.setInt(R.id.nav_to_right, "setColorFilter", getColor(context, textColors[1]))
views.setInt(R.id.nav_refresh, "setColorFilter", getColor(context, textColors[1]))
views.setInt(R.id.empty_view, "setTextColor", getColor(context, textColors[0]))
if (!userLoggedIn(context)) {
views.setViewVisibility(R.id.need_login, View.VISIBLE)
views.setOnClickPendingIntent(
R.id.open_login,
makePending(context, ACTION_WIDGET_CLICK_BUY_PREMIUM, appId)
)
} else {
views.setViewVisibility(R.id.tt_grid_cont, View.VISIBLE)
views.setInt(R.id.widget_list, "setBackgroundColor", fullTheme[1])
views.setInt(R.id.bottom_nav, "setBackgroundColor", fullTheme[1])
views.setOnClickPendingIntent(
R.id.nav_to_left,
makePending(context, ACTION_WIDGET_CLICK_NAV_LEFT, appId)
)
views.setOnClickPendingIntent(
R.id.nav_to_right,
makePending(context, ACTION_WIDGET_CLICK_NAV_RIGHT, appId)
)
views.setOnClickPendingIntent(
R.id.nav_current,
makePending(context, ACTION_WIDGET_CLICK_NAV_TODAY, appId)
)
views.setOnClickPendingIntent(
R.id.nav_refresh,
makePending(context, ACTION_WIDGET_CLICK_NAV_REFRESH, appId)
)
views.setRemoteAdapter(R.id.widget_list, serviceIntent)
views.setEmptyView(R.id.widget_list, R.id.empty_view)
views.setInt(R.id.empty_view, "setBackgroundColor", fullTheme[1])
}
return views
}
fun makePending(context: Context?, action: String?, appWidgetId: Int): PendingIntent {
val activebtnnext = Intent(context, WidgetTimetable::class.java)
activebtnnext.setAction(action)
activebtnnext.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
return PendingIntent.getBroadcast(
context,
appWidgetId,
activebtnnext,
PendingIntent.FLAG_IMMUTABLE
)
}
fun convertDayOfWeek(context: Context, rday: Int): String {
/*if(rday == -1) return DayOfWeek.of(1).getDisplayName(TextStyle.FULL, new Locale("hu", "HU"))
String dayOfWeek = DayOfWeek.of(rday + 1).getDisplayName(TextStyle.FULL, new Locale("hu", "HU"))*/
var dayOfWeek = "Unknown"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val loc: Locale = getLocale(context)
if (rday == -1) return DayOfWeek.of(1).getDisplayName(TextStyle.FULL, loc)
dayOfWeek = DayOfWeek.of(rday + 1).getDisplayName(TextStyle.FULL, loc)
}
return dayOfWeek.substring(0, 1).toUpperCase() + dayOfWeek.substring(1).toLowerCase()
}
fun setSelectedDay(context: Context, wid: Int, day: Int) {
val dbManager = DBManager(context.getApplicationContext())
try {
dbManager.open()
dbManager.update(wid, day)
dbManager.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
fun getToday(context: Context): Int {
var rday: Int = DateTime().getDayOfWeek() - 1
val s: MutableList<JSONArray> = genJsonDays(context)
try {
if (checkIsAfter(s, rday)) rday += 1
} catch (e: Exception) {
e.printStackTrace()
}
return retDay(rday, s.size)
}
fun selectDay(context: Context, wid: Int, add: Int, afterSubjects: Boolean): Int {
val dbManager = DBManager(context.getApplicationContext())
try {
dbManager.open()
val cursor: Cursor = dbManager.fetchWidget(wid)
val s: MutableList<JSONArray> = genJsonDays(context)
var retday: Int = DateTime().getDayOfWeek() - 1
if (cursor.getCount() !== 0) retday = retDay(cursor.getInt(1) + add, s.size)
if (afterSubjects) if (checkIsAfter(s, retday)) retday += 1
retday = retDay(retday, s.size)
if (cursor.getCount() === 0) dbManager.insertSelDay(
wid,
retday
) else dbManager.update(wid, retday)
dbManager.close()
// get the date of the first lesson
val dt = DateTime(s[retday].getJSONObject(0).getString("Datum"))
retday = dt.getDayOfWeek() - 1
return retday
} catch (e: Exception) {
e.printStackTrace()
}
return 0
}
fun checkIsAfter(s: MutableList<JSONArray>, retday: Int): Boolean {
var retday = retday
retday = retDay(retday, s.size)
val vegIdopont: String =
s[retday].getJSONObject(s[retday].length() - 1).getString("VegIdopont")
return DateTime().isAfter(DateTime(vegIdopont))
}
fun retDay(retday: Int, size: Int): Int {
var retday = retday
if (retday < 0) retday = size - 1 else if (retday > size - 1) retday = 0
return retday
}
fun genJsonDays(context: Context): MutableList<JSONArray> {
val genDays: MutableList<JSONArray> = mutableListOf<JSONArray>()
val dayMap: MutableMap<String, JSONArray> = mutableMapOf<String, JSONArray>()
val dbManager = DBManager(context.getApplicationContext())
try {
dbManager.open()
val ct: Cursor = dbManager.fetchTimetable()
if (ct.getCount() === 0) {
return genDays
}
val fetchedTimetable = JSONObject(ct.getString(0))
val currentWeek: String = Week.current().id().toString()
val week: JSONArray = fetchedTimetable.getJSONArray(currentWeek)
// Organize lessons into dates
for (i in 0 until week.length()) {
try {
val entry: JSONObject = week.getJSONObject(i)
val date: String = entry.getString("Datum")
dayMap.computeIfAbsent(date) { k -> JSONArray() }.put(entry)
} catch (e: JSONException) {
e.printStackTrace()
}
}
genDays.addAll(dayMap.values)
// Sort the 'genDays' list of JSON based on the start time of the first entry
genDays.sortWith( { day1, day2 ->
// Extract the start time of the first entry in each day's JSON
val startTime1: String = day1.getJSONObject(0).getString("KezdetIdopont")
val startTime2: String = day2.getJSONObject(0).getString("KezdetIdopont")
// Compare the start times and return the result for sorting
startTime1.compareTo(startTime2)
})
} catch (e: Exception) {
e.printStackTrace()
} finally {
dbManager.close()
}
return genDays
}
fun zeroPad(value: Int, padding: Int): String {
val b = StringBuilder()
b.append(value)
while (b.length < padding) {
b.insert(0, "0")
}
return b.toString()
}
fun getLocale(context: Context): Locale {
val dbManager = DBManager(context.getApplicationContext())
try {
dbManager.open()
val loc: String = dbManager.fetchLocale().getString(0)
dbManager.close()
if (loc.equals("hu") || loc.equals("de")) {
return Locale(loc, loc.toUpperCase())
}
} catch (e: Exception) {
e.printStackTrace()
}
return Locale("en", "GB")
}
fun userLoggedIn(context: Context): Boolean {
return !lastUserId(context).equals("")
}
fun lastUserId(context: Context): String {
val dbManager = DBManager(context.getApplicationContext())
try {
dbManager.open()
val cursor: Cursor = dbManager.fetchLastUser()
dbManager.close()
if (cursor != null && !cursor.getString(0).equals("")) {
return cursor.getString(0)
}
} catch (e: Exception) {
e.printStackTrace()
}
return ""
}
}
}

View File

@ -1,382 +0,0 @@
package hu.refilc.naplo.widget_timetable;
import android.app.UiModeManager;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
import org.joda.time.DateTime;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import hu.refilc.naplo.database.DBManager;
import hu.refilc.naplo.R;
public class WidgetTimetableDataProvider implements RemoteViewsService.RemoteViewsFactory {
private Context context;
private int appWidgetId;
private int rday = 0;
private Integer[] fullTheme;
private UiModeManager uiModeManager;
private int nightMode;
List<Lesson> day_subjects = new ArrayList<>();
List<Integer> lessonIndexes = new ArrayList<>();
Item witem;
/* Default values */
static class Item {
int Layout;
int BackgroundColor;
int NumVisibility;
int NameVisibility;
int NameNodescVisibility;
int DescVisibility;
int RoomVisibility;
int TimeVisibility;
int NumColor;
int NameColor;
int NameNodescColor;
int DescColor;
int RoomColor;
int TimeColor;
Integer[] NameNodescPadding = {0, 0, 0, 0};
public Item(int Layout, int BackgroundColor, int NumVisibility,int NameVisibility,int NameNodescVisibility,int DescVisibility,int RoomVisibility,int TimeVisibility,int NumColor,int NameColor,int NameNodescColor,int DescColor,int RoomColor, int TimeColor) {
this.Layout = Layout;
this.BackgroundColor = BackgroundColor;
this.NumVisibility = NumVisibility;
this.NameVisibility = NameVisibility;
this.NameNodescVisibility = NameNodescVisibility;
this.DescVisibility = DescVisibility;
this.RoomVisibility = RoomVisibility;
this.TimeVisibility = TimeVisibility;
this.NumColor = NumColor;
this.NameColor = NameColor;
this.NameNodescColor = NameNodescColor;
this.DescColor = DescColor;
this.RoomColor = RoomColor;
this.TimeColor = TimeColor;
}
}
static class Lesson {
String status;
String lessonIndex;
String lessonName;
String lessonTopic;
String lessonRoom;
long lessonStart;
long lessonEnd;
String substituteTeacher;
public Lesson(String status, String lessonIndex,String lessonName,String lessonTopic, String lessonRoom,long lessonStart,long lessonEnd,String substituteTeacher) {
this.status = status;
this.lessonIndex = lessonIndex;
this.lessonName = lessonName;
this.lessonTopic = lessonTopic;
this.lessonRoom = lessonRoom;
this.lessonStart = lessonStart;
this.lessonEnd = lessonEnd;
this.substituteTeacher = substituteTeacher;
}
}
Integer[] itemNameNodescPadding = {0, 0, 0, 0};
public WidgetTimetableDataProvider(Context context, Intent intent) {
this.context = context;
this.appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
this.fullTheme = getFullTheme(context);
this.uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
this.nightMode = uiModeManager.getNightMode();
}
@Override
public void onCreate() {
initData();
}
@Override
public void onDataSetChanged() {
initData();
}
@Override
public void onDestroy() {
}
@Override
public int getCount() {
return day_subjects.size();
}
public void setLayout(final RemoteViews view) {
/* Visibilities */
view.setViewVisibility(R.id.tt_item_num, witem.NumVisibility);
view.setViewVisibility(R.id.tt_item_name, witem.NameVisibility);
view.setViewVisibility(R.id.tt_item_name_nodesc, witem.NameNodescVisibility);
view.setViewVisibility(R.id.tt_item_desc, witem.DescVisibility);
view.setViewVisibility(R.id.tt_item_room, witem.RoomVisibility);
view.setViewVisibility(R.id.tt_item_time, witem.TimeVisibility);
/* backgroundResources */
view.setInt(R.id.main_lay, "setBackgroundResource", witem.Layout);
view.setInt(R.id.main_lay, "setBackgroundColor", witem.BackgroundColor);
/* Paddings */
view.setViewPadding(R.id.tt_item_name_nodesc, witem.NameNodescPadding[0], witem.NameNodescPadding[1], witem.NameNodescPadding[2], witem.NameNodescPadding[3]);
/* Text Colors */
view.setInt(R.id.tt_item_num, "setTextColor", witem.NumColor);
view.setInt(R.id.tt_item_name, "setTextColor", getColor(context, witem.NameColor));
view.setInt(R.id.tt_item_name_nodesc, "setTextColor", getColor(context, witem.NameNodescColor));
view.setInt(R.id.tt_item_desc, "setTextColor", getColor(context, witem.DescColor));
view.setInt(R.id.tt_item_room, "setTextColor", getColor(context, witem.RoomColor));
view.setInt(R.id.tt_item_time, "setTextColor", getColor(context, witem.TimeColor));
}
public int getColor(Context context, int color) {
return context.getResources().getColor(color);
}
@Override
public RemoteViews getViewAt(int position) {
RemoteViews view = new RemoteViews(context.getPackageName(), R.layout.timetable_item);
witem = defaultItem(fullTheme, nightMode, context);
Lesson curr_subject = day_subjects.get(position);
if (curr_subject.status.equals("empty")) {
witem.NumColor = getColor(context, R.color.text_miss_num);
witem.TimeVisibility = View.GONE;
witem.RoomVisibility = View.GONE;
witem.NameNodescColor = R.color.text_miss;
}
if (!curr_subject.substituteTeacher.equals("null")) {
witem.NumColor = getColor(context, R.color.yellow);
witem.Layout = R.drawable.card_layout_tile_helyetesitett;
}
if (curr_subject.status.equals("Elmaradt")) {
witem.NumColor = getColor(context, R.color.red);
witem.Layout = R.drawable.card_layout_tile_elmarad;
} else if (curr_subject.status.equals("TanevRendjeEsemeny")) {
witem.NumVisibility = View.GONE;
witem.TimeVisibility = View.GONE;
witem.RoomVisibility = View.GONE;
witem.NameNodescPadding[0] = 50;
witem.NameNodescPadding[2] = 50;
witem.NameNodescColor = R.color.text_miss;
}
if (curr_subject.lessonTopic.equals("null")) {
witem.DescVisibility = View.GONE;
witem.NameVisibility = View.GONE;
witem.NameNodescVisibility = View.VISIBLE;
}
setLayout(view);
String lessonIndexTrailing = curr_subject.lessonIndex.equals("+") ? "" : ".";
view.setTextViewText(R.id.tt_item_num, curr_subject.lessonIndex + lessonIndexTrailing);
view.setTextViewText(R.id.tt_item_name, curr_subject.lessonName);
view.setTextViewText(R.id.tt_item_name_nodesc, curr_subject.lessonName);
view.setTextViewText(R.id.tt_item_desc, curr_subject.lessonTopic);
view.setTextViewText(R.id.tt_item_room, curr_subject.lessonRoom);
if(curr_subject.lessonStart != 0 && curr_subject.lessonEnd != 0)
view.setTextViewText(R.id.tt_item_time, WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonStart).getHourOfDay(), 2) + ":" + WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonStart).getMinuteOfHour(), 2) +
"\n" + WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonEnd).getHourOfDay(), 2) + ":" + WidgetTimetable.zeroPad(new DateTime(curr_subject.lessonEnd).getMinuteOfHour(),2));
return view;
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return true;
}
private void initData() {
// refresh theme
fullTheme = getFullTheme(context);
rday = WidgetTimetable.selectDay(context, appWidgetId, 0, false);
day_subjects.clear();
lessonIndexes.clear();
try {
List<JSONArray> arr = WidgetTimetable.genJsonDays(context);
if(arr.isEmpty()) {
return;
}
JSONArray arr_lessons = WidgetTimetable.genJsonDays(context).get(rday);
for (int i = 0; i < arr_lessons.length(); i++) {
JSONObject obj_lessons = arr_lessons.getJSONObject(i);
day_subjects.add(jsonToLesson(obj_lessons));
}
} catch (JSONException e) {
e.printStackTrace();
}
if(day_subjects.size() > 0) {
Collections.sort(day_subjects, new Comparator<Lesson>() {
public int compare(Lesson o1, Lesson o2) {
return new DateTime(o1.lessonStart).compareTo(new DateTime(o2.lessonStart));
}
});
for (int i = 0; i < day_subjects.size(); i++) {
if(!day_subjects.get(i).lessonIndex.equals("+")) {
lessonIndexes.add(Integer.valueOf(day_subjects.get(i).lessonIndex));
}
}
if(lessonIndexes.size() > 0) {
int lessonsChecked = Collections.min(lessonIndexes);
int i = 0;
while(lessonsChecked < Collections.max(lessonIndexes)) {
if(!lessonIndexes.contains(lessonsChecked)) {
day_subjects.add(i, emptyLesson(lessonsChecked));
}
lessonsChecked++;
i++;
}
}
}
}
public static Integer[] getFullTheme(Context context) {
DBManager dbManager = new DBManager(context.getApplicationContext());
try {
dbManager.open();
Cursor cursor = dbManager.fetchTheme();
dbManager.close();
int theme = cursor.getInt(0);
int customAccentColor = cursor.getInt(1);
int customBackgroundColor = cursor.getInt(2);
return new Integer[]{theme, customAccentColor, customBackgroundColor};
} catch (Exception e) {
e.printStackTrace();
}
return new Integer[]{0, 0, 0};
}
public Item defaultItem(Integer[] fullTheme, int nightMode, Context context) {
int textColor;
int textDescColor;
if (fullTheme[0] == 0 && nightMode == UiModeManager.MODE_NIGHT_NO) {
textColor = R.color.text_light;
textDescColor = R.color.text_desc_light;
} else if (fullTheme[0] == 1) {
textColor = R.color.text_light;
textDescColor = R.color.text_desc_light;
} else {
textColor = R.color.text;
textDescColor = R.color.text_desc;
}
return new Item(
R.drawable.card_layout_tile,
fullTheme[2],
View.VISIBLE,
View.VISIBLE,
View.INVISIBLE,
View.VISIBLE,
View.VISIBLE,
View.VISIBLE,
fullTheme[1],
textColor,
textColor,
textDescColor,
textDescColor,
textColor
);
}
public Lesson emptyLesson(int lessonIndex) {
return new Lesson("empty", String.valueOf(lessonIndex), "Lyukasóra", "null", "null", 0, 0, "null");
}
public Lesson jsonToLesson(JSONObject json) {
try {
String name = json.getString("Nev");
name = name.substring(0, 1).toUpperCase() + name.substring(1); // Capitalize name
return new Lesson(
json.getJSONObject("Allapot").getString("Nev"),
!json.getString("Oraszam").equals("null") ? json.getString("Oraszam") : "+",
name,
json.getString("Tema"),
json.getString("TeremNeve"),
new DateTime(json.getString("KezdetIdopont")).getMillis(),
new DateTime(json.getString("VegIdopont")).getMillis(),
json.getString("HelyettesTanarNeve")
);
}catch (Exception e) {
Log.d("Filc", "exception: " + e);
};
return null;
}
}

View File

@ -0,0 +1,328 @@
package hu.refilc.naplo.widget_timetable
import android.app.UiModeManager
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.os.Build
import android.util.Log
import android.view.View
import android.widget.RemoteViews
import android.widget.RemoteViewsService
import org.joda.time.DateTime
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.util.Collections
import java.util.Comparator
import hu.refilc.naplo.database.DBManager
import hu.refilc.naplo.R
class WidgetTimetableDataProvider(context: Context, intent: Intent) : RemoteViewsService.RemoteViewsFactory {
private val context: Context
private val appWidgetId: Int
private var rday = 0
private var fullTheme: Array<Int>
private val uiModeManager: UiModeManager
private val nightMode: Int
var day_subjects: MutableList<Lesson> = mutableListOf<Lesson>()
var lessonIndexes: MutableList<Int> = mutableListOf<Int>()
var witem: Item? = null
/* Default values */
class Item(
var Layout: Int,
var BackgroundColor: Int,
var NumVisibility: Int,
var NameVisibility: Int,
var NameNodescVisibility: Int,
var DescVisibility: Int,
var RoomVisibility: Int,
var TimeVisibility: Int,
var NumColor: Int,
var NameColor: Int,
var NameNodescColor: Int,
var DescColor: Int,
var RoomColor: Int,
var TimeColor: Int
) {
var NameNodescPadding: Array<Int> = arrayOf(0, 0, 0, 0)
}
class Lesson(
var status: String,
var lessonIndex: String,
var lessonName: String,
var lessonTopic: String,
var lessonRoom: String,
var lessonStart: Long,
var lessonEnd: Long,
var substituteTeacher: String
)
var itemNameNodescPadding: Array<Int> = arrayOf(0, 0, 0, 0)
init {
this.context = context
appWidgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID
)
fullTheme = getFullTheme(context)
uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
nightMode = uiModeManager.getNightMode()
}
override fun onCreate() {
initData()
}
override fun onDataSetChanged() {
initData()
}
override fun onDestroy() {}
override fun getCount(): Int {
return day_subjects.size
}
fun setLayout(view: RemoteViews) {
/* Visibilities */
view.setViewVisibility(R.id.tt_item_num, witem!!.NumVisibility)
view.setViewVisibility(R.id.tt_item_name, witem!!.NameVisibility)
view.setViewVisibility(R.id.tt_item_name_nodesc, witem!!.NameNodescVisibility)
view.setViewVisibility(R.id.tt_item_desc, witem!!.DescVisibility)
view.setViewVisibility(R.id.tt_item_room, witem!!.RoomVisibility)
view.setViewVisibility(R.id.tt_item_time, witem!!.TimeVisibility)
/* backgroundResources */
view.setInt(R.id.main_lay, "setBackgroundResource", witem!!.Layout)
view.setInt(R.id.main_lay, "setBackgroundColor", witem!!.BackgroundColor)
/* Paddings */
view.setViewPadding(
R.id.tt_item_name_nodesc,
witem!!.NameNodescPadding[0],
witem!!.NameNodescPadding[1],
witem!!.NameNodescPadding[2],
witem!!.NameNodescPadding[3]
)
/* Text Colors */
view.setInt(R.id.tt_item_num, "setTextColor", witem!!.NumColor)
view.setInt(R.id.tt_item_name, "setTextColor", getColor(context, witem!!.NameColor))
view.setInt(R.id.tt_item_name_nodesc, "setTextColor", getColor(context, witem!!.NameNodescColor))
view.setInt(R.id.tt_item_desc, "setTextColor", getColor(context, witem!!.DescColor))
view.setInt(R.id.tt_item_room, "setTextColor", getColor(context, witem!!.RoomColor))
view.setInt(R.id.tt_item_time, "setTextColor", getColor(context, witem!!.TimeColor))
}
fun getColor(context: Context, color: Int): Int {
return context.getResources().getColor(color)
}
override fun getViewAt(position: Int): RemoteViews {
val view = RemoteViews(context.getPackageName(), R.layout.timetable_item)
witem = defaultItem(fullTheme, nightMode)
val curr_subject = day_subjects[position]
if (curr_subject.status.equals("empty")) {
witem!!.NumColor = getColor(context, R.color.text_miss_num)
witem!!.TimeVisibility = View.GONE
witem!!.RoomVisibility = View.GONE
witem!!.NameNodescColor = R.color.text_miss
}
if (!curr_subject.substituteTeacher.equals("null")) {
witem!!.NumColor = getColor(context, R.color.yellow)
witem!!.Layout = R.drawable.card_layout_tile_helyetesitett
}
if (curr_subject.status.equals("Elmaradt")) {
witem!!.NumColor = getColor(context, R.color.red)
witem!!.Layout = R.drawable.card_layout_tile_elmarad
} else if (curr_subject.status.equals("TanevRendjeEsemeny")) {
witem!!.NumVisibility = View.GONE
witem!!.TimeVisibility = View.GONE
witem!!.RoomVisibility = View.GONE
witem!!.NameNodescPadding[0] = 50
witem!!.NameNodescPadding[2] = 50
witem!!.NameNodescColor = R.color.text_miss
}
if (curr_subject.lessonTopic.equals("null")) {
witem!!.DescVisibility = View.GONE
witem!!.NameVisibility = View.GONE
witem!!.NameNodescVisibility = View.VISIBLE
}
setLayout(view)
val lessonIndexTrailing = if (curr_subject.lessonIndex.equals("+")) "" else "."
view.setTextViewText(R.id.tt_item_num, curr_subject.lessonIndex + lessonIndexTrailing)
view.setTextViewText(R.id.tt_item_name, curr_subject.lessonName)
view.setTextViewText(R.id.tt_item_name_nodesc, curr_subject.lessonName)
view.setTextViewText(R.id.tt_item_desc, curr_subject.lessonTopic)
view.setTextViewText(R.id.tt_item_room, curr_subject.lessonRoom)
if (curr_subject.lessonStart != 0L && curr_subject.lessonEnd != 0L) view.setTextViewText(
R.id.tt_item_time,
((WidgetTimetable.zeroPad(
DateTime(curr_subject.lessonStart).getHourOfDay(),
2
) + ":" + WidgetTimetable.zeroPad(
DateTime(curr_subject.lessonStart).getMinuteOfHour(),
2
)).toString() +
"\n" + WidgetTimetable.zeroPad(
DateTime(curr_subject.lessonEnd).getHourOfDay(),
2
)).toString() + ":" + WidgetTimetable.zeroPad(
DateTime(curr_subject.lessonEnd).getMinuteOfHour(),
2
)
)
return view
}
override fun getLoadingView(): RemoteViews {
val view = RemoteViews(context.getPackageName(), R.layout.timetable_item)
return view
}
override fun getViewTypeCount(): Int {
return 1
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun hasStableIds(): Boolean {
return true
}
private fun initData() {
// refresh theme
fullTheme = getFullTheme(context)
rday = WidgetTimetable.selectDay(context, appWidgetId, 0, false)
day_subjects.clear()
lessonIndexes.clear()
try {
val arr: MutableList<JSONArray> = WidgetTimetable.genJsonDays(context) as MutableList<JSONArray>
if (arr.isEmpty()) {
return
}
val arr_lessons: JSONArray = WidgetTimetable.genJsonDays(context).get(rday)
for (i in 0 until arr_lessons.length()) {
val obj_lessons: JSONObject = arr_lessons.getJSONObject(i)
day_subjects.add(jsonToLesson(obj_lessons))
}
} catch (e: JSONException) {
e.printStackTrace()
}
if (day_subjects.size > 0) {
Collections.sort(day_subjects, object : Comparator<Lesson?> {
override fun compare(o1: Lesson?, o2: Lesson?): Int {
return DateTime(o1?.lessonStart).compareTo(DateTime(o2?.lessonStart))
}
})
for (i in 0 until day_subjects.size) {
if (!day_subjects[i].lessonIndex.equals("+")) {
lessonIndexes.add(Integer.valueOf(day_subjects[i].lessonIndex))
}
}
if (lessonIndexes.size > 0) {
var lessonsChecked: Int = Collections.min(lessonIndexes)
var i = 0
while (lessonsChecked < Collections.max(lessonIndexes)) {
if (!lessonIndexes.contains(lessonsChecked)) {
day_subjects.add(i, emptyLesson(lessonsChecked))
}
lessonsChecked++
i++
}
}
}
}
fun defaultItem(fullTheme: Array<Int>, nightMode: Int): Item {
val textColor: Int
val textDescColor: Int
if (fullTheme[0] == 0 && nightMode == UiModeManager.MODE_NIGHT_NO) {
textColor = R.color.text_light
textDescColor = R.color.text_desc_light
} else if (fullTheme[0] == 1) {
textColor = R.color.text_light
textDescColor = R.color.text_desc_light
} else {
textColor = R.color.text
textDescColor = R.color.text_desc
}
return Item(
R.drawable.card_layout_tile,
fullTheme[2],
View.VISIBLE,
View.VISIBLE,
View.INVISIBLE,
View.VISIBLE,
View.VISIBLE,
View.VISIBLE,
fullTheme[1],
textColor,
textColor,
textDescColor,
textDescColor,
textColor
)
}
fun emptyLesson(lessonIndex: Int): Lesson {
return Lesson(
"empty",
lessonIndex.toString(),
"Lyukasóra",
"null",
"null",
0,
0,
"null"
)
}
fun jsonToLesson(json: JSONObject): Lesson {
try {
var name: String = json.getString("Nev")
name = name.substring(0, 1).toUpperCase() + name.substring(1) // Capitalize name
return Lesson(
json.getJSONObject("Allapot").getString("Nev"),
if (!json.getString("Oraszam").equals("null")) json.getString("Oraszam") else "+",
name,
json.getString("Tema"),
json.getString("TeremNeve"),
DateTime(json.getString("KezdetIdopont")).getMillis(),
DateTime(json.getString("VegIdopont")).getMillis(),
json.getString("HelyettesTanarNeve")
)
} catch (e: Exception) {
Log.d("Filc", "exception: $e")
}
return Lesson("", "", "", "", "", 0, 0, "")
}
companion object {
fun getFullTheme(context: Context): Array<Int> {
val dbManager = DBManager(context.getApplicationContext())
try {
dbManager.open()
val cursor: Cursor = dbManager.fetchTheme()
dbManager.close()
val theme: Int = cursor.getInt(0)
val customAccentColor: Int = cursor.getInt(1)
val customBackgroundColor: Int = cursor.getInt(2)
return arrayOf(theme, customAccentColor, customBackgroundColor)
} catch (e: Exception) {
e.printStackTrace()
}
return arrayOf(0, 0, 0)
}
}
}

View File

@ -1,12 +0,0 @@
package hu.refilc.naplo.widget_timetable;
import android.content.Intent;
import android.os.Build;
import android.widget.RemoteViewsService;
public class WidgetTimetableService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new WidgetTimetableDataProvider(getApplicationContext(), intent);
}
}

View File

@ -0,0 +1,12 @@
package hu.refilc.naplo.widget_timetable
import android.content.Context
import android.content.Intent
import android.os.Build
import android.widget.RemoteViewsService
class WidgetTimetableService: RemoteViewsService() {
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
return WidgetTimetableDataProvider(getApplicationContext(), intent)
}
}