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 @@