1package soy.iko.opencode.platform
3import android.app.PendingIntent
4import android.appwidget.AppWidgetManager
5import android.appwidget.AppWidgetProvider
6import android.content.ComponentName
7import android.content.Context
8import android.content.Intent
10import android.os.Build
11import android.widget.RemoteViews
12import soy.iko.opencode.MainActivity
13import soy.iko.opencode.R
16 * Home-screen widget listing recent opencode sessions (fed by
17 * [soy.iko.opencode.data.repo.RecentSessionsStore]) with a "New session" action. Each row deep-links
18 * into its session; the header opens the app. The list is backed by [SessionsWidgetService].
20class SessionsWidgetProvider : AppWidgetProvider() {
22 override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
23 for (id in appWidgetIds) render(context, appWidgetManager, id)
27 /** Re-render all widgets and tell them to reload their list data (call after the
28 * recent-session list changes). No-op when no widget is placed. */
29 fun refresh(context: Context) {
30 val manager = AppWidgetManager.getInstance(context) ?: return
31 val ids = runCatching {
32 manager.getAppWidgetIds(ComponentName(context, SessionsWidgetProvider::class.java))
33 }.getOrNull() ?: return
34 if (ids.isEmpty()) return
35 for (id in ids) render(context, manager, id)
36 manager.notifyAppWidgetViewDataChanged(ids, R.id.widget_list)
39 private fun render(context: Context, manager: AppWidgetManager, widgetId: Int) {
40 val views = RemoteViews(context.packageName, R.layout.widget_sessions)
42 // Header: title opens the app; the "+" starts a new session.
43 views.setOnClickPendingIntent(
45 activityPending(context, requestCode = 2, Intent(context, MainActivity::class.java)),
47 views.setOnClickPendingIntent(
50 context, requestCode = 1,
51 Intent(context, MainActivity::class.java).apply { action = MainActivity.ACTION_NEW_SESSION },
55 // Bind the list to the RemoteViewsService. A unique data Uri per widget id keeps
56 // the framework from reusing one adapter across widgets.
57 val serviceIntent = Intent(context, SessionsWidgetService::class.java).apply {
58 putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId)
59 data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
61 views.setRemoteAdapter(R.id.widget_list, serviceIntent)
62 views.setEmptyView(R.id.widget_list, R.id.widget_empty)
64 // Template intent filled in per row (fill-in carries EXTRA_SESSION_ID). Must be
65 // mutable on Android 12+ so the row's fill-in can be merged.
66 val templateIntent = Intent(context, MainActivity::class.java).apply { action = Intent.ACTION_VIEW }
67 val mutableFlag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
68 val templatePending = PendingIntent.getActivity(
69 context, 3, templateIntent, PendingIntent.FLAG_UPDATE_CURRENT or mutableFlag,
71 views.setPendingIntentTemplate(R.id.widget_list, templatePending)
73 manager.updateAppWidget(widgetId, views)
74 manager.notifyAppWidgetViewDataChanged(widgetId, R.id.widget_list)
77 private fun activityPending(context: Context, requestCode: Int, intent: Intent): PendingIntent =
78 PendingIntent.getActivity(
79 context, requestCode, intent,
80 PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list