package com.orgzly.android.widgets;
import android.app.AlarmManager;
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.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.RemoteViews;
import com.orgzly.BuildConfig;
import com.orgzly.R;
import com.orgzly.android.AppIntent;
import com.orgzly.android.Filter;
import com.orgzly.android.Shelf;
import com.orgzly.android.provider.clients.FiltersClient;
import com.orgzly.android.ui.ShareActivity;
import com.orgzly.android.ui.util.ActivityUtils;
import com.orgzly.android.util.LogUtils;
import java.util.Calendar;
/**
* The AppWidgetProvider for the list widget
*/
public class ListWidgetProvider extends AppWidgetProvider {
private static final String TAG = ListWidgetProvider.class.getName();
private static final String PREFERENCES_ID = "list-widget";
public static final String EXTRA_CLICK_TYPE = "click_type";
public static final int OPEN_CLICK_TYPE = 1;
public static final int DONE_CLICK_TYPE = 2;
public static final String EXTRA_NOTE_ID = "note_id";
public static final String EXTRA_BOOK_ID = "book_id";
public static final String EXTRA_FILTER_ID = "filter_id";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
if (BuildConfig.LOG_DEBUG) LogUtils.d(TAG, "onUpdate");
for (int appWidgetId : appWidgetIds) {
updateAppWidgetLayout(context, appWidgetManager, appWidgetId);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
private static void updateAppWidgetLayout(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
Filter filter = getFilter(context, appWidgetId);
Intent serviceIntent = new Intent(context, ListWidgetService.class);
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
serviceIntent.putExtra(ListWidgetService.EXTRA_QUERY_STRING, filter.getQuery());
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.list_widget);
remoteViews.setRemoteAdapter(R.id.list_widget_list_view, serviceIntent);
remoteViews.setEmptyView(R.id.list_widget_list_view, R.id.list_widget_empty_view);
if (filter.getQuery() == null) {
remoteViews.setTextViewText(R.id.list_widget_empty_view, context.getString(R.string.select_a_filter_long));
} else {
remoteViews.setTextViewText(R.id.list_widget_empty_view, context.getString(R.string.no_notes_found_after_search));
}
/* Set the PendingIntent template for the clicks on the rows */
final Intent onClickIntent = new Intent(context, ListWidgetProvider.class);
onClickIntent.setAction(AppIntent.ACTION_LIST_WIDGET_CLICK);
onClickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
onClickIntent.setData(Uri.parse(onClickIntent.toUri(Intent.URI_INTENT_SCHEME)));
final PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(context, 0,
onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setPendingIntentTemplate(R.id.list_widget_list_view, onClickPendingIntent);
remoteViews.setOnClickPendingIntent(R.id.list_widget_header_add, ShareActivity.createNewNoteIntent(context));
Intent filterSelectIntent = new Intent(context, FilterSelectDialogActivity.class);
filterSelectIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
filterSelectIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
remoteViews.setOnClickPendingIntent(R.id.list_widget_header_filter, PendingIntent.getActivity(context, 0, filterSelectIntent, PendingIntent.FLAG_UPDATE_CURRENT));
remoteViews.setTextViewText(
R.id.list_widget_header_filter,
filter.getName());
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
private static void updateAppWidgetLayouts(Context context) {
if (BuildConfig.LOG_DEBUG) LogUtils.d(TAG, "updateAppWidgetLayouts");
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisAppWidgetComponentName = new ComponentName(context.getPackageName(), ListWidgetProvider.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidgetComponentName);
for (int appWidgetId : appWidgetIds) {
updateAppWidgetLayout(context, appWidgetManager, appWidgetId);
}
}
private static void updateListContents(Context context) {
if (BuildConfig.LOG_DEBUG) LogUtils.d(TAG, "updateListContents");
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisAppWidgetComponentName = new ComponentName(context.getPackageName(), ListWidgetProvider.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidgetComponentName);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.list_widget_list_view);
}
@Override
public void onEnabled(Context context) {
IntentFilter filter = new IntentFilter();
filter.addAction(AppIntent.ACTION_LIST_WIDGET_UPDATE);
filter.addAction(AppIntent.ACTION_LIST_WIDGET_UPDATE_LAYOUT);
LocalBroadcastManager.getInstance(context).registerReceiver(this, filter);
scheduleUpdate(context);
}
@Override
public void onDisabled(Context context) {
LocalBroadcastManager.getInstance(context).unregisterReceiver(this);
clearUpdate(context);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
for (int id : appWidgetIds) {
SharedPreferences.Editor editor = context.getSharedPreferences(PREFERENCES_ID, Context.MODE_PRIVATE).edit();
editor.remove(getFilterPreferenceKey(id));
editor.apply();
}
}
private static void scheduleUpdate(Context context) {
/*
schedule updates via AlarmManager, because we don't want to wake the device on every update
see https://developer.android.com/guide/topics/appwidgets/index.html#MetaData
*/
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent intent = getAlarmIntent(context);
alarmManager.cancel(intent);
/* repeat after every full hour because results of search can change on new day
because of timezones repeat every hour instead of every day */
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.HOUR_OF_DAY, 1);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 1);
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_HOUR, intent);
}
private static void clearUpdate(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(getAlarmIntent(context));
}
private static PendingIntent getAlarmIntent(Context context) {
Intent intent = new Intent(context, ListWidgetProvider.class);
intent.setAction(AppIntent.ACTION_LIST_WIDGET_UPDATE);
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
private static void setFilterFromIntent(Context context, Intent intent) {
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
long filterId = intent.getLongExtra(EXTRA_FILTER_ID, 0);
setFilter(context, appWidgetId, filterId);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
updateAppWidgetLayout(context, appWidgetManager, appWidgetId);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_widget_list_view);
}
private static Filter getFilter(Context context, int appWidgetId) {
long filterId = context.getSharedPreferences(PREFERENCES_ID, Context.MODE_PRIVATE).getLong(getFilterPreferenceKey(appWidgetId), -1);
Filter filter = null;
if (filterId != -1) {
filter = FiltersClient.get(context, filterId);
}
if (filter == null) {
filter = new Filter(context.getString(R.string.select_a_filter), null);
}
return filter;
}
private static void setFilter(Context context, int appWidgetId, long id) {
SharedPreferences.Editor editor = context.getSharedPreferences(PREFERENCES_ID, Context.MODE_PRIVATE).edit();
editor.putLong(getFilterPreferenceKey(appWidgetId), id);
editor.apply();
}
private static String getFilterPreferenceKey(int appWidgetId) {
return "widget-filter-" + appWidgetId;
}
private void setNoteDone(Context context, Intent intent) {
final Shelf shelf = new Shelf(context);
final long noteId = intent.getLongExtra(ListWidgetProvider.EXTRA_NOTE_ID, 0L);
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
shelf.setStateToDone(noteId);
return null;
}
}.execute();
}
private void openNote(Context context, Intent intent) {
long noteId = intent.getLongExtra(ListWidgetProvider.EXTRA_NOTE_ID, 0L);
long bookId = intent.getLongExtra(ListWidgetProvider.EXTRA_BOOK_ID, 0L);
try {
ActivityUtils.mainActivityPendingIntent(context, bookId, noteId).send();
} catch (PendingIntent.CanceledException e) {
Log.e(TAG, "Error opening note: " + e);
}
}
@Override
public void onReceive(Context context, Intent intent) {
if (BuildConfig.LOG_DEBUG) LogUtils.d(TAG, intent);
if (AppIntent.ACTION_LIST_WIDGET_UPDATE.equals(intent.getAction())) {
updateListContents(context);
} else if (AppIntent.ACTION_LIST_WIDGET_UPDATE_LAYOUT.equals(intent.getAction())) {
updateAppWidgetLayouts(context);
} else if (AppIntent.ACTION_LIST_WIDGET_SET_FILTER.equals(intent.getAction())) {
setFilterFromIntent(context, intent);
} else if (AppIntent.ACTION_LIST_WIDGET_CLICK.equals(intent.getAction())) {
switch (intent.getIntExtra(EXTRA_CLICK_TYPE, -1)) {
case OPEN_CLICK_TYPE:
openNote(context, intent);
break;
case DONE_CLICK_TYPE:
setNoteDone(context, intent);
break;
}
} else {
super.onReceive(context, intent);
}
}
}