Skip to content

Commit

Permalink
Create launcher widget for todo (closes #1997, PR #2379)
Browse files Browse the repository at this point in the history
  • Loading branch information
wshoy authored Sep 24, 2024
1 parent f31cfa7 commit d161e62
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 2 deletions.
16 changes: 16 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,22 @@
android:name="other.writeily.widget.WrFilesWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />

<receiver
android:name=".widget.TodoWidgetProvider"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>

<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/todo_widget" />
</receiver>

<service
android:name=".widget.TodoWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import net.gsantner.markor.model.Document;
import net.gsantner.markor.util.MarkorContextUtils;
import net.gsantner.markor.web.MarkorWebViewClient;
import net.gsantner.markor.widget.TodoWidgetProvider;
import net.gsantner.opoc.frontend.filebrowser.GsFileBrowserOptions;
import net.gsantner.opoc.frontend.settings.GsFontPreferenceCompat;
import net.gsantner.opoc.frontend.textview.TextViewUndoRedo;
Expand Down Expand Up @@ -285,6 +286,10 @@ public void onPause() {
_appSettings.addRecentFile(_document.file);
_appSettings.setDocumentPreviewState(_document.path, _isPreviewVisible);
_appSettings.setLastEditPosition(_document.path, TextViewUtils.getSelection(_hlEditor)[0]);

if(_document.path.equals(_appSettings.getTodoFile().getAbsolutePath())){
TodoWidgetProvider.updateTodoWidgets();
}
super.onPause();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import net.gsantner.markor.frontend.filebrowser.MarkorFileBrowserFactory;
import net.gsantner.markor.model.Document;
import net.gsantner.markor.util.MarkorContextUtils;
import net.gsantner.markor.widget.TodoWidgetProvider;
import net.gsantner.opoc.format.GsSimpleMarkdownParser;
import net.gsantner.opoc.frontend.base.GsFragmentBase;
import net.gsantner.opoc.frontend.filebrowser.GsFileBrowserFragment;
Expand Down Expand Up @@ -486,6 +487,7 @@ public GsFileBrowserFragment getNotebook() {
protected void onPause() {
super.onPause();
WrMarkorWidgetProvider.updateLauncherWidgets();
TodoWidgetProvider.updateTodoWidgets();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import net.gsantner.markor.model.AppSettings;
import net.gsantner.markor.util.BackupUtils;
import net.gsantner.markor.util.MarkorContextUtils;
import net.gsantner.markor.widget.TodoWidgetProvider;
import net.gsantner.opoc.frontend.base.GsActivityBase;
import net.gsantner.opoc.frontend.base.GsPreferenceFragmentBase;
import net.gsantner.opoc.frontend.filebrowser.GsFileBrowserOptions;
Expand Down Expand Up @@ -231,6 +232,7 @@ protected void onPreferenceChanged(final SharedPreferences prefs, final String k
}
} else if (eq(key, R.string.pref_key__notebook_directory, R.string.pref_key__quicknote_filepath, R.string.pref_key__todo_filepath)) {
WrMarkorWidgetProvider.updateLauncherWidgets();
TodoWidgetProvider.updateTodoWidgets();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,10 @@ public List<String> getProjects() {
}

public String getCreationDate() {
return getCreationaDate("");
return getCreationDate("");
}

public String getCreationaDate(final String defaultValue) {
public String getCreationDate(final String defaultValue) {
if (creationDate == null) {
creationDate = parseOneValueOrDefault(line, PATTERN_CREATION_DATE, defaultValue);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package net.gsantner.markor.widget;

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.os.Build;
import android.widget.RemoteViews;

import net.gsantner.markor.ApplicationObject;
import net.gsantner.markor.R;
import net.gsantner.markor.activity.openeditor.OpenFromShortcutOrWidgetActivity;
import net.gsantner.markor.model.AppSettings;
import net.gsantner.markor.model.Document;

public class TodoWidgetProvider extends AppWidgetProvider {

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

int requestCode = 1;
final AppSettings appSettings = ApplicationObject.settings();

final int staticFlags = PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0);
final int mutableFlags = PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_MUTABLE : 0);

for (int appWidgetId : appWidgetIds) {

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.todo_widget_layout);

final Intent intent = new Intent(context, TodoWidgetService.class);
views.setRemoteAdapter(R.id.todo_widget_list_view, intent);
views.setEmptyView(R.id.todo_widget_list_view, R.id.todo_widget_empty_view);
views.setInt(R.id.todo_widget_list_view, "setBackgroundColor", appSettings.getEditorBackgroundColor());

final Intent openTodo = new Intent(context, OpenFromShortcutOrWidgetActivity.class)
.setAction(Intent.ACTION_EDIT)
.putExtra(Document.EXTRA_FILE, appSettings.getTodoFile());
views.setPendingIntentTemplate(R.id.todo_widget_list_view, PendingIntent.getActivity(context, requestCode++, openTodo, mutableFlags));
views.setOnClickPendingIntent(R.id.todo_widget_container, PendingIntent.getActivity(context, requestCode++, openTodo, staticFlags));

// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}

super.onUpdate(context, appWidgetManager, appWidgetIds);
}

// Update all widget lists and shortcuts for all widgets
public static void updateTodoWidgets() {
final Context context = ApplicationObject.get().getApplicationContext();
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
if (appWidgetManager == null) {
// The device does not support widgets.
return;
}
final ComponentName comp = new ComponentName(context, TodoWidgetProvider.class);
final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(comp);

// Update List
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.todo_widget_list_view);

// Trigger remote views update
context.sendBroadcast(new Intent(context, TodoWidgetProvider.class)
.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package net.gsantner.markor.widget;

import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;

import net.gsantner.markor.ApplicationObject;
import net.gsantner.markor.R;
import net.gsantner.markor.format.todotxt.TodoTxtTask;
import net.gsantner.markor.model.AppSettings;
import net.gsantner.markor.model.Document;

import java.util.ArrayList;
import java.util.List;

public class TodoWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {

private final Context _context;
private final AppSettings _appSettings;
private final Document _document;
private final List<TodoTxtTask> _tasks;

public TodoWidgetRemoteViewsFactory(Context context, Intent intent) {
_context = context;
_appSettings = ApplicationObject.settings();
_document = new Document(_appSettings.getTodoFile());
_tasks = new ArrayList<>();
}

@Override
public void onCreate() {
onDataSetChanged();
}

@Override
public void onDataSetChanged() {
_tasks.clear();
final String content = _document.loadContent(_context);
if (content == null) {
return;
}
List<TodoTxtTask> tasks = TodoTxtTask.getAllTasks(content);
_tasks.addAll(tasks);
}

@Override
public void onDestroy() {
_tasks.clear();
}

@Override
public int getCount() {
return _tasks.size();
}

@Override
public RemoteViews getViewAt(int position) {
RemoteViews views = new RemoteViews(_context.getPackageName(), R.layout.todo_widget_list_item);
views.setTextViewText(R.id.todo_widget_item_text, _tasks.get(position).getDescription());
views.setInt(R.id.todo_widget_item_text, "setTextColor", _appSettings.getEditorForegroundColor());

final Intent fillInIntent = new Intent()
.putExtra(Document.EXTRA_FILE_LINE_NUMBER, position);
views.setOnClickFillInIntent(R.id.todo_widget_item_text, fillInIntent);

return views;
}

@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 false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

package net.gsantner.markor.widget;

import android.content.Intent;
import android.widget.RemoteViewsService;

public class TodoWidgetService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return (new TodoWidgetRemoteViewsFactory(getApplicationContext(), intent));
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions app/src/main/res/layout/todo_widget_layout.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/todo_widget_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background">

<ListView
android:id="@+id/todo_widget_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/grey"
android:dividerHeight="0.5dp" />

<TextView
android:id="@+id/todo_widget_empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Empty"
android:gravity="center"
android:visibility="gone" />
</LinearLayout>
8 changes: 8 additions & 0 deletions app/src/main/res/layout/todo_widget_list_item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/todo_widget_item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="3dp"
android:textSize="15sp"
android:textColor="@color/primary_text" />
12 changes: 12 additions & 0 deletions app/src/main/res/xml/todo_widget.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/todo_widget_layout"
android:minWidth="120dp"
android:minHeight="80dp"
android:targetCellHeight="2"
android:targetCellWidth="2"
android:minResizeWidth="60dp"
android:minResizeHeight="40dp"
android:previewImage="@drawable/todo_widget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="1800000" />

0 comments on commit d161e62

Please sign in to comment.