diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6a43f4dba..309541c56 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -174,11 +174,13 @@
+ android:permission="android.permission.BIND_REMOTEVIEWS"
+ android:exported="false"/>
+ android:permission="android.permission.BIND_REMOTEVIEWS"
+ android:exported="false"/>
repo.removeNoteListWidget(appWidgetId));
- }
- }
-
- /**
- * Update note list widgets, if the note data was changed.
- */
- public static void updateNoteListWidgets(Context context) {
- context.sendBroadcast(new Intent(context, NoteListWidget.class).setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE));
- }
-}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidget.kt b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidget.kt
new file mode 100644
index 000000000..cab4ab972
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidget.kt
@@ -0,0 +1,135 @@
+/*
+ * Nextcloud Notes - Android Client
+ *
+ * SPDX-FileCopyrightText: 2017-2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package it.niedermann.owncloud.notes.widget.notelist
+
+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.net.Uri
+import android.util.Log
+import android.widget.RemoteViews
+import com.owncloud.android.lib.common.utils.Log_OC
+import it.niedermann.owncloud.notes.R
+import it.niedermann.owncloud.notes.edit.EditNoteActivity
+import it.niedermann.owncloud.notes.persistence.NotesRepository
+import it.niedermann.owncloud.notes.shared.util.WidgetUtil
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+import androidx.core.net.toUri
+
+class NoteListWidget : AppWidgetProvider() {
+ private val executor: ExecutorService = Executors.newCachedThreadPool()
+
+ override fun onUpdate(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetIds: IntArray
+ ) {
+ super.onUpdate(context, appWidgetManager, appWidgetIds)
+ updateAppWidget(context, appWidgetManager, appWidgetIds)
+ }
+
+ override fun onReceive(context: Context, intent: Intent) {
+ super.onReceive(context, intent)
+ val awm = AppWidgetManager.getInstance(context)
+
+ if (intent.action == null) {
+ Log.w(TAG, "Intent action is null")
+ return
+ }
+
+ if (intent.action != AppWidgetManager.ACTION_APPWIDGET_UPDATE) {
+ Log.w(TAG, "Intent action is not ACTION_APPWIDGET_UPDATE")
+ return
+ }
+
+ if (!intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
+ Log.w(TAG, "Update widget via default appWidgetIds")
+ updateAppWidget(
+ context,
+ awm,
+ awm.getAppWidgetIds(ComponentName(context, NoteListWidget::class.java))
+ )
+ }
+
+ if (intent.extras == null) {
+ Log.w(TAG, "Intent doesn't have bundle")
+ return
+ }
+
+ Log.w(TAG, "Update widget via given appWidgetIds")
+
+ val appWidgetIds = intArrayOf(intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) ?: -1)
+
+ updateAppWidget(
+ context,
+ awm,
+ appWidgetIds
+ )
+ }
+
+ override fun onDeleted(context: Context, appWidgetIds: IntArray) {
+ super.onDeleted(context, appWidgetIds)
+ val repo = NotesRepository.getInstance(context)
+
+ for (appWidgetId in appWidgetIds) {
+ executor.submit(Runnable { repo.removeNoteListWidget(appWidgetId) })
+ }
+ }
+
+ companion object {
+ private val TAG: String = NoteListWidget::class.java.getSimpleName()
+ fun updateAppWidget(context: Context, awm: AppWidgetManager, appWidgetIds: IntArray) {
+ val repo = NotesRepository.getInstance(context)
+ appWidgetIds.forEach { appWidgetId ->
+ repo.getNoteListWidgetData(appWidgetId)?.let { data ->
+ val serviceIntent = Intent(context, NoteListWidgetService::class.java).apply {
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
+ setData(toUri(Intent.URI_INTENT_SCHEME).toUri())
+ }
+
+
+ Log.v(TAG, "-- data - $data")
+
+ val editNoteIntent = Intent(context, EditNoteActivity::class.java).apply {
+ setPackage(context.packageName)
+ }
+
+ val pendingIntentFlags =
+ WidgetUtil.pendingIntentFlagCompat(PendingIntent.FLAG_UPDATE_CURRENT or Intent.FILL_IN_COMPONENT)
+ val editNotePendingIntent =
+ PendingIntent.getActivity(context, 0, editNoteIntent, pendingIntentFlags)
+
+ val views = RemoteViews(context.packageName, R.layout.widget_note_list).apply {
+ setRemoteAdapter(R.id.note_list_widget_lv, serviceIntent)
+ setPendingIntentTemplate(R.id.note_list_widget_lv, editNotePendingIntent)
+ setEmptyView(
+ R.id.note_list_widget_lv,
+ R.id.widget_note_list_placeholder_tv
+ )
+ }
+
+ awm.run {
+ updateAppWidget(appWidgetId, views)
+ notifyAppWidgetViewDataChanged(appWidgetId, R.id.note_list_widget_lv)
+ }
+ }
+ }
+ }
+
+ @JvmStatic
+ fun updateNoteListWidgets(context: Context) {
+ val intent = Intent(context, NoteListWidget::class.java).apply {
+ setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
+ }
+ context.sendBroadcast(intent)
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.java b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.java
deleted file mode 100644
index 939973a37..000000000
--- a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Nextcloud Notes - Android Client
- *
- * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-package it.niedermann.owncloud.notes.widget.notelist;
-
-import static it.niedermann.owncloud.notes.edit.EditNoteActivity.PARAM_CATEGORY;
-import static it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData.MODE_DISPLAY_ALL;
-import static it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData.MODE_DISPLAY_CATEGORY;
-import static it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData.MODE_DISPLAY_STARRED;
-
-import android.appwidget.AppWidgetManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.RemoteViews;
-import android.widget.RemoteViewsService;
-
-import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import it.niedermann.owncloud.notes.R;
-import it.niedermann.owncloud.notes.edit.EditNoteActivity;
-import it.niedermann.owncloud.notes.main.MainActivity;
-import it.niedermann.owncloud.notes.persistence.NotesRepository;
-import it.niedermann.owncloud.notes.persistence.entity.Account;
-import it.niedermann.owncloud.notes.persistence.entity.Note;
-import it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData;
-import it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType;
-import it.niedermann.owncloud.notes.shared.model.NavigationCategory;
-import it.niedermann.owncloud.notes.shared.util.NotesColorUtil;
-
-public class NoteListWidgetFactory implements RemoteViewsService.RemoteViewsFactory {
- private static final String TAG = NoteListWidgetFactory.class.getSimpleName();
-
- private final Context context;
- private final int appWidgetId;
- private final NotesRepository repo;
- @NonNull
- private final List dbNotes = new ArrayList<>();
- private NotesListWidgetData data;
-
- NoteListWidgetFactory(Context context, Intent intent) {
- this.context = context;
- this.appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
- repo = NotesRepository.getInstance(context);
- }
-
- @Override
- public void onCreate() {
- // Nothing to do hereā¦
- }
-
- @Override
- public void onDataSetChanged() {
- dbNotes.clear();
- try {
- data = repo.getNoteListWidgetData(appWidgetId);
- if (data == null) {
- Log.w(TAG, "Widget data is null");
- return;
- }
-
- Log.v(TAG, "--- data - " + data);
- switch (data.getMode()) {
- case MODE_DISPLAY_ALL ->
- dbNotes.addAll(repo.searchRecentByModified(data.getAccountId(), "%"));
- case MODE_DISPLAY_STARRED ->
- dbNotes.addAll(repo.searchFavoritesByModified(data.getAccountId(), "%"));
- default -> {
- if (data.getCategory() != null) {
- dbNotes.addAll(repo.searchCategoryByModified(data.getAccountId(), "%", data.getCategory()));
- } else {
- dbNotes.addAll(repo.searchUncategorizedByModified(data.getAccountId(), "%"));
- }
- }
- }
- } catch (Exception e) {
- Log.w(TAG, "Error caught at onDataSetChanged: " + e);
- }
- }
-
- @Override
- public void onDestroy() {
- //NoOp
- }
-
- @Override
- public int getCount() {
- return dbNotes.size() + 1;
- }
-
- private Intent getEditNoteIntent(Bundle bundle) {
- final Intent intent = new Intent(context, EditNoteActivity.class);
- intent.setPackage(context.getPackageName());
- intent.putExtras(bundle);
- intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
-
- return intent;
- }
-
- private Intent getCreateNoteIntent(Account localAccount ) {
- final Bundle bundle = new Bundle();
- bundle.putSerializable(PARAM_CATEGORY, data.getMode() == MODE_DISPLAY_STARRED ? new NavigationCategory(ENavigationCategoryType.FAVORITES) : new NavigationCategory(localAccount.getId(), data.getCategory()));
- bundle.putLong(EditNoteActivity.PARAM_ACCOUNT_ID, data.getAccountId());
-
- return getEditNoteIntent(bundle);
- }
-
- private Intent getOpenNoteIntent(Note note) {
- final Bundle bundle = new Bundle();
- bundle.putLong(EditNoteActivity.PARAM_NOTE_ID, note.getId());
- bundle.putLong(EditNoteActivity.PARAM_ACCOUNT_ID, note.getAccountId());
-
- return getEditNoteIntent(bundle);
- }
-
- @Override
- public RemoteViews getViewAt(int position) {
- final RemoteViews note_content;
-
- if (position == 0) {
- final Account localAccount = repo.getAccountById(data.getAccountId());
-
- final Intent createNoteIntent = getCreateNoteIntent(localAccount);
- final Intent openIntent = new Intent(Intent.ACTION_MAIN).setComponent(new ComponentName(context.getPackageName(), MainActivity.class.getName()));
-
- note_content = new RemoteViews(context.getPackageName(), R.layout.widget_entry_add);
- note_content.setOnClickFillInIntent(R.id.widget_entry_content_tv, openIntent);
- note_content.setOnClickFillInIntent(R.id.widget_entry_fav_icon, createNoteIntent);
- note_content.setTextViewText(R.id.widget_entry_content_tv, getCategoryTitle(context, data.getMode(), data.getCategory()));
- note_content.setImageViewResource(R.id.widget_entry_fav_icon, R.drawable.ic_add_blue_24dp);
- note_content.setInt(R.id.widget_entry_fav_icon, "setColorFilter", NotesColorUtil.contrastRatioIsSufficient(ContextCompat.getColor(context, R.color.widget_background), localAccount.getColor())
- ? localAccount.getColor()
- : ContextCompat.getColor(context, R.color.widget_foreground));
- } else {
- position--;
- if (position > dbNotes.size() - 1 || dbNotes.get(position) == null) {
- Log.e(TAG, "Could not find position \"" + position + "\" in dbNotes list.");
- return null;
- }
-
- final Note note = dbNotes.get(position);
- final Intent openNoteIntent = getOpenNoteIntent(note);
-
- note_content = new RemoteViews(context.getPackageName(), R.layout.widget_entry);
- note_content.setOnClickFillInIntent(R.id.widget_note_list_entry, openNoteIntent);
- note_content.setTextViewText(R.id.widget_entry_content_tv, note.getTitle());
- note_content.setImageViewResource(R.id.widget_entry_fav_icon, note.getFavorite()
- ? R.drawable.ic_star_yellow_24dp
- : R.drawable.ic_star_grey_ccc_24dp);
- }
-
- return note_content;
-
- }
-
- @NonNull
- private static String getCategoryTitle(@NonNull Context context, int displayMode, String category) {
- return switch (displayMode) {
- case MODE_DISPLAY_STARRED ->
- context.getString(R.string.label_favorites);
- case MODE_DISPLAY_CATEGORY ->
- "".equals(category)
- ? context.getString(R.string.action_uncategorized)
- : category;
- default -> context.getString(R.string.app_name);
- };
- }
-
- @Override
- public RemoteViews getLoadingView() {
- return null;
- }
-
- @Override
- public int getViewTypeCount() {
- return 2;
- }
-
- @Override
- public long getItemId(int position) {
- if (position == 0) {
- return -1;
- } else {
- position--;
- if (position > dbNotes.size() - 1 || dbNotes.get(position) == null) {
- Log.e(TAG, "Could not find position \"" + position + "\" in dbNotes list.");
- return -2;
- }
- return dbNotes.get(position).getId();
- }
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.kt b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.kt
new file mode 100644
index 000000000..97f92ad94
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/widget/notelist/NoteListWidgetFactory.kt
@@ -0,0 +1,181 @@
+/*
+ * Nextcloud Notes - Android Client
+ *
+ * SPDX-FileCopyrightText: 2017-2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package it.niedermann.owncloud.notes.widget.notelist
+
+import android.appwidget.AppWidgetManager
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import android.widget.RemoteViews
+import android.widget.RemoteViewsService.RemoteViewsFactory
+import androidx.core.net.toUri
+import it.niedermann.owncloud.notes.R
+import it.niedermann.owncloud.notes.edit.EditNoteActivity
+import it.niedermann.owncloud.notes.persistence.NotesRepository
+import it.niedermann.owncloud.notes.persistence.entity.Account
+import it.niedermann.owncloud.notes.persistence.entity.Note
+import it.niedermann.owncloud.notes.persistence.entity.NotesListWidgetData
+import it.niedermann.owncloud.notes.shared.model.ENavigationCategoryType
+import it.niedermann.owncloud.notes.shared.model.NavigationCategory
+
+class NoteListWidgetFactory internal constructor(private val context: Context, intent: Intent) :
+ RemoteViewsFactory {
+ private val appWidgetId: Int = intent.getIntExtra(
+ AppWidgetManager.EXTRA_APPWIDGET_ID,
+ AppWidgetManager.INVALID_APPWIDGET_ID
+ )
+ private val repo: NotesRepository = NotesRepository.getInstance(context)
+ private val dbNotes: MutableList = ArrayList()
+ private var data: NotesListWidgetData? = null
+
+ override fun onCreate() = Unit
+
+ override fun onDataSetChanged() {
+ dbNotes.clear()
+ try {
+ data = repo.getNoteListWidgetData(appWidgetId)
+ if (data == null) {
+ Log.w(TAG, "Widget data is null")
+ return
+ }
+ val widgetData = data ?: return
+
+ Log.v(TAG, "--- data - $widgetData")
+
+ when (widgetData.mode) {
+ NotesListWidgetData.MODE_DISPLAY_ALL -> dbNotes.addAll(
+ repo.searchRecentByModified(
+ widgetData.accountId, "%"
+ )
+ )
+
+ NotesListWidgetData.MODE_DISPLAY_STARRED -> dbNotes.addAll(
+ repo.searchFavoritesByModified(
+ widgetData.accountId, "%"
+ )
+ )
+
+ else -> {
+ if (widgetData.category != null) {
+ dbNotes.addAll(
+ repo.searchCategoryByModified(
+ widgetData.accountId,
+ "%",
+ widgetData.category
+ )
+ )
+ } else {
+ dbNotes.addAll(
+ repo.searchUncategorizedByModified(
+ widgetData.accountId,
+ "%"
+ )
+ )
+ }
+ }
+ }
+ } catch (e: Exception) {
+ Log.w(TAG, "Error caught at onDataSetChanged: $e")
+ }
+ }
+
+ override fun onDestroy() = Unit
+
+ override fun getCount(): Int {
+ return dbNotes.size
+ }
+
+ private fun getEditNoteIntent(bundle: Bundle): Intent {
+ return Intent(context, EditNoteActivity::class.java).apply {
+ setPackage(context.packageName)
+ putExtras(bundle)
+ setData(toUri(Intent.URI_INTENT_SCHEME).toUri())
+ }
+ }
+
+ private fun getCreateNoteIntent(localAccount: Account): Intent {
+ val bundle = Bundle()
+
+ data?.let {
+ val navigationCategory = if (it.mode == NotesListWidgetData.MODE_DISPLAY_STARRED) NavigationCategory(
+ ENavigationCategoryType.FAVORITES
+ ) else NavigationCategory(localAccount.id, it.category)
+
+ bundle.putSerializable(EditNoteActivity.PARAM_CATEGORY, navigationCategory)
+ bundle.putLong(EditNoteActivity.PARAM_ACCOUNT_ID, it.accountId)
+ }
+
+ return getEditNoteIntent(bundle)
+ }
+
+ private fun getOpenNoteIntent(note: Note): Intent {
+ val bundle = Bundle().apply {
+ putLong(EditNoteActivity.PARAM_NOTE_ID, note.id)
+ putLong(EditNoteActivity.PARAM_ACCOUNT_ID, note.accountId)
+ }
+
+ return getEditNoteIntent(bundle)
+ }
+
+ override fun getViewAt(position: Int): RemoteViews? {
+ val note = dbNotes.getOrNull(position) ?: return null
+
+ val openNoteIntent = getOpenNoteIntent(note)
+
+ var createNoteIntent: Intent? = null
+ data?.let {
+ val localAccount = repo.getAccountById(it.accountId)
+ createNoteIntent = getCreateNoteIntent(localAccount)
+ }
+
+ return RemoteViews(context.packageName, R.layout.widget_entry).apply {
+ setOnClickFillInIntent(R.id.widget_note_list_entry, openNoteIntent)
+
+ createNoteIntent?.let {
+ setOnClickFillInIntent(R.id.widget_entry_fav_icon, createNoteIntent)
+ }
+
+ setTextViewText(R.id.widget_entry_title, note.title)
+
+ if (note.category.isEmpty()) {
+ setViewVisibility(R.id.widget_entry_category, View.GONE)
+ } else {
+ setViewVisibility(R.id.widget_entry_category, View.VISIBLE)
+ setTextViewText(R.id.widget_entry_category, note.category)
+ }
+
+ val starIconId = if (note.favorite) {
+ R.drawable.ic_star_yellow_24dp
+ } else {
+ R.drawable.ic_star_grey_ccc_24dp
+ }
+ setImageViewResource(R.id.widget_entry_fav_icon, starIconId)
+ }
+ }
+
+ override fun getLoadingView(): RemoteViews? {
+ return null
+ }
+
+ override fun getViewTypeCount(): Int {
+ return 2
+ }
+
+ override fun getItemId(position: Int): Long {
+ return dbNotes[position].id
+ }
+
+ override fun hasStableIds(): Boolean {
+ return true
+ }
+
+ companion object {
+ private val TAG: String = NoteListWidgetFactory::class.java.getSimpleName()
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidget.java b/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidget.java
deleted file mode 100644
index 954ba45b8..000000000
--- a/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidget.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Nextcloud Notes - Android Client
- *
- * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: GPL-3.0-or-later
- */
-package it.niedermann.owncloud.notes.widget.singlenote;
-
-import static it.niedermann.owncloud.notes.shared.util.WidgetUtil.pendingIntentFlagCompat;
-
-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.net.Uri;
-import android.util.Log;
-import android.widget.RemoteViews;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import it.niedermann.owncloud.notes.R;
-import it.niedermann.owncloud.notes.edit.BaseNoteFragment;
-import it.niedermann.owncloud.notes.edit.EditNoteActivity;
-import it.niedermann.owncloud.notes.persistence.NotesRepository;
-import it.niedermann.owncloud.notes.persistence.entity.SingleNoteWidgetData;
-
-public class SingleNoteWidget extends AppWidgetProvider {
-
- private static final String TAG = SingleNoteWidget.class.getSimpleName();
- private final ExecutorService executor = Executors.newCachedThreadPool();
-
- static void updateAppWidget(Context context, AppWidgetManager awm, int[] appWidgetIds) {
- final var templateIntent = new Intent(context, EditNoteActivity.class);
- final var repo = NotesRepository.getInstance(context);
-
- for (int appWidgetId : appWidgetIds) {
- final var data = repo.getSingleNoteWidgetData(appWidgetId);
- if (data != null) {
- templateIntent.putExtra(BaseNoteFragment.PARAM_ACCOUNT_ID, data.getAccountId());
-
- final var serviceIntent = new Intent(context, SingleNoteWidgetService.class);
- serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
- serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
-
- final var views = new RemoteViews(context.getPackageName(), R.layout.widget_single_note);
- views.setPendingIntentTemplate(R.id.single_note_widget_lv, PendingIntent.getActivity(context, appWidgetId, templateIntent,
- pendingIntentFlagCompat(PendingIntent.FLAG_UPDATE_CURRENT)));
- views.setRemoteAdapter(R.id.single_note_widget_lv, serviceIntent);
- views.setEmptyView(R.id.single_note_widget_lv, R.id.widget_single_note_placeholder_tv);
-
- awm.notifyAppWidgetViewDataChanged(appWidgetId, R.id.single_note_widget_lv);
- awm.updateAppWidget(appWidgetId, views);
- } else {
- Log.i(TAG, "onUpdate has been triggered before the user finished configuring the widget");
- }
- }
- }
-
- @Override
- public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
- super.onUpdate(context, appWidgetManager, appWidgetIds);
- updateAppWidget(context, appWidgetManager, appWidgetIds);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- super.onReceive(context, intent);
- final var awm = AppWidgetManager.getInstance(context);
-
- updateAppWidget(context, AppWidgetManager.getInstance(context),
- (awm.getAppWidgetIds(new ComponentName(context, SingleNoteWidget.class))));
- }
-
- @Override
- public void onDeleted(Context context, int[] appWidgetIds) {
- final var repo = NotesRepository.getInstance(context);
-
- for (int appWidgetId : appWidgetIds) {
- executor.submit(() -> repo.removeSingleNoteWidget(appWidgetId));
- }
- super.onDeleted(context, appWidgetIds);
- }
-
- /**
- * Update single note widget, if the note data was changed.
- */
- public static void updateSingleNoteWidgets(Context context) {
- context.sendBroadcast(new Intent(context, SingleNoteWidget.class).setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE));
- }
-}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidget.kt b/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidget.kt
new file mode 100644
index 000000000..8c2cd829a
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/widget/singlenote/SingleNoteWidget.kt
@@ -0,0 +1,101 @@
+/*
+ * Nextcloud Notes - Android Client
+ *
+ * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+package it.niedermann.owncloud.notes.widget.singlenote
+
+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.widget.RemoteViews
+import it.niedermann.owncloud.notes.R
+import it.niedermann.owncloud.notes.edit.BaseNoteFragment
+import it.niedermann.owncloud.notes.edit.EditNoteActivity
+import it.niedermann.owncloud.notes.persistence.NotesRepository
+import it.niedermann.owncloud.notes.shared.util.WidgetUtil
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+import androidx.core.net.toUri
+
+class SingleNoteWidget : AppWidgetProvider() {
+ private val executor: ExecutorService = Executors.newCachedThreadPool()
+
+ override fun onUpdate(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetIds: IntArray
+ ) {
+ super.onUpdate(context, appWidgetManager, appWidgetIds)
+ updateAppWidget(context, appWidgetManager, appWidgetIds)
+ }
+
+ override fun onReceive(context: Context, intent: Intent?) {
+ super.onReceive(context, intent)
+ val awm = AppWidgetManager.getInstance(context)
+
+ val provider = ComponentName(context, SingleNoteWidget::class.java)
+ val appWidgetIds = awm.getAppWidgetIds(provider)
+ updateAppWidget(context, awm, appWidgetIds)
+ }
+
+ override fun onDeleted(context: Context, appWidgetIds: IntArray) {
+ val repo = NotesRepository.getInstance(context)
+
+ for (appWidgetId in appWidgetIds) {
+ executor.submit { repo.removeSingleNoteWidget(appWidgetId) }
+ }
+ super.onDeleted(context, appWidgetIds)
+ }
+
+ companion object {
+ private val TAG: String = SingleNoteWidget::class.java.getSimpleName()
+ fun updateAppWidget(context: Context, awm: AppWidgetManager, appWidgetIds: IntArray) {
+ val templateIntent = Intent(context, EditNoteActivity::class.java)
+ val repo = NotesRepository.getInstance(context)
+
+ appWidgetIds.forEach { appWidgetId ->
+ repo.getSingleNoteWidgetData(appWidgetId)?.let { data ->
+ templateIntent.putExtra(BaseNoteFragment.PARAM_ACCOUNT_ID, data.accountId)
+
+ val serviceIntent = Intent(context, SingleNoteWidgetService::class.java).apply {
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
+ setData(toUri(Intent.URI_INTENT_SCHEME).toUri())
+ }
+
+
+ val views = RemoteViews(context.packageName, R.layout.widget_single_note).apply {
+ setPendingIntentTemplate(
+ R.id.single_note_widget_lv, PendingIntent.getActivity(
+ context, appWidgetId, templateIntent,
+ WidgetUtil.pendingIntentFlagCompat(PendingIntent.FLAG_UPDATE_CURRENT)
+ )
+ )
+ setRemoteAdapter(R.id.single_note_widget_lv, serviceIntent)
+ setEmptyView(
+ R.id.single_note_widget_lv,
+ R.id.widget_single_note_placeholder_tv
+ )
+ }
+
+ awm.run {
+ updateAppWidget(appWidgetId, views)
+ notifyAppWidgetViewDataChanged(appWidgetId, R.id.single_note_widget_lv)
+ }
+ }
+ }
+ }
+
+ @JvmStatic
+ fun updateSingleNoteWidgets(context: Context) {
+ val intent = Intent(context, SingleNoteWidget::class.java).apply {
+ setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
+ }
+ context.sendBroadcast(intent)
+ }
+ }
+}
diff --git a/app/src/main/res/layout/widget_entry.xml b/app/src/main/res/layout/widget_entry.xml
index 56bcad6b1..bde69e01b 100644
--- a/app/src/main/res/layout/widget_entry.xml
+++ b/app/src/main/res/layout/widget_entry.xml
@@ -2,7 +2,7 @@
@@ -22,24 +23,33 @@
android:layout_height="@dimen/widget_note_list_fav_icon_height"
android:layout_gravity="center_vertical"
android:contentDescription="@string/widget_entry_fav_contentDescription"
- android:foregroundGravity="center_vertical"
android:paddingStart="@dimen/widget_note_list_inner_padding"
android:paddingEnd="@dimen/widget_note_list_outer_padding"
app:srcCompat="@drawable/ic_star_yellow_24dp" />
+ tools:text="First note" />
+
diff --git a/app/src/main/res/layout/widget_note_list.xml b/app/src/main/res/layout/widget_note_list.xml
index 844a56c98..c91ab2e55 100644
--- a/app/src/main/res/layout/widget_note_list.xml
+++ b/app/src/main/res/layout/widget_note_list.xml
@@ -17,7 +17,7 @@