Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,18 @@ import android.appwidget.AppWidgetManager
import android.content.Context
import android.net.Uri
import android.widget.RemoteViews
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetProvider
import es.antonborri.home_widget.HomeWidgetPlugin
import org.json.JSONException
import android.content.Intent
import android.widget.RemoteViewsService
import org.json.JSONObject
import org.json.JSONArray as OrgJSONArray
import android.os.Bundle
import android.app.PendingIntent
import android.appwidget.AppWidgetProvider
import android.os.Build


@TargetApi(Build.VERSION_CODES.CUPCAKE)
class TaskWarriorWidgetProvider : AppWidgetProvider() {

override fun onReceive(context: Context, intent: Intent) {
// Handle the custom action from your Widget buttons/list
if (intent.action == "TASK_ACTION") {
val uuid = intent.getStringExtra("uuid") ?: ""
val launchedFor = intent.getStringExtra("launchedFor")

// 1. Construct the URI exactly as Flutter expects it
// Scheme: taskwarrior://
// Host: cardclicked OR addclicked
val deepLinkUri = if (launchedFor == "ADD_TASK") {
Uri.parse("taskwarrior://addclicked")
} else {
// For list items, we attach the UUID
Uri.parse("taskwarrior://cardclicked?uuid=$uuid")
}

// 2. Create the Intent to open MainActivity
val launchIntent = Intent(context, MainActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = deepLinkUri
// These flags ensure the app opens correctly whether running or not
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
}

context.startActivity(launchIntent)
}
super.onReceive(context, intent)
}
fun getLayoutId(context: Context) : Int{
val sharedPrefs = HomeWidgetPlugin.getData(context)
val theme = sharedPrefs.getString("themeMode", "")
Expand Down Expand Up @@ -78,25 +44,34 @@ override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appW
val views = RemoteViews(context.packageName, getLayoutId(context)).apply {

// Set up the Logo click (Open App)
val pendingIntent: PendingIntent = HomeWidgetLaunchIntent.getActivity(
val pendingIntent: PendingIntent = PendingIntent.getActivity(
context,
MainActivity::class.java
widgetId,
Intent(context, MainActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = Uri.parse("taskwarrior://home")
flags =
Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP or
Intent.FLAG_ACTIVITY_SINGLE_TOP
},
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
setOnClickPendingIntent(R.id.logo, pendingIntent)

// Set up the Add Button click (Custom Action)
val intent_for_add = Intent(context, TaskWarriorWidgetProvider::class.java).apply {
action = "TASK_ACTION"
putExtra("launchedFor", "ADD_TASK")
// Unique data to ensure the broadcast is fresh
data = Uri.parse("taskwarrior://addtask/$widgetId")
}

val pendingIntentAdd: PendingIntent = PendingIntent.getBroadcast(
val pendingIntentAdd: PendingIntent = PendingIntent.getActivity(
context,
widgetId,
intent_for_add,
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
widgetId,
Intent(context, MainActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = Uri.parse("taskwarrior://addclicked")
flags =
Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP or
Intent.FLAG_ACTIVITY_SINGLE_TOP
},
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
setOnClickPendingIntent(R.id.add_btn, pendingIntentAdd)

Expand All @@ -105,19 +80,19 @@ override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appW
}

// 4. Set up the Click Template for List Items (Deep Linking)
val clickPendingIntent: PendingIntent = Intent(
val clickPendingIntent: PendingIntent = PendingIntent.getActivity(
context,
TaskWarriorWidgetProvider::class.java
).run {
action = "TASK_ACTION"
// Important: Use widgetId as requestCode to keep it unique
PendingIntent.getBroadcast(
context,
widgetId,
this,
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
}
widgetId,
Intent(context, MainActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = Uri.parse("taskwarrior://cardclicked")
flags =
Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP or
Intent.FLAG_ACTIVITY_SINGLE_TOP
},
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
views.setPendingIntentTemplate(R.id.list_view, clickPendingIntent)

// 5. THE THEME FIX: Notify the manager that the list data/layout needs a refresh
Expand Down Expand Up @@ -198,16 +173,11 @@ class ListViewRemoteViewsFactory(
return RemoteViews(context.packageName, getListItemLayoutId()).apply {
setTextViewText(R.id.todo__title, task.title)
setImageViewResource(R.id.dot, getDotIdByPriority(task.priority))
val a = Intent().apply {

Bundle().also { extras ->
extras.putString("action", "show_task")
extras.putString("uuid", tasks[position].uuid)
putExtras(extras)
}

val fillInIntent = Intent().apply {
action = Intent.ACTION_VIEW
data = Uri.parse("taskwarrior://cardclicked?uuid=${tasks[position].uuid}")
}
setOnClickFillInIntent(R.id.list_item_container,a)
setOnClickFillInIntent(R.id.list_item_container, fillInIntent)
}

}
Expand Down Expand Up @@ -236,4 +206,4 @@ data class Task(val title: String, val urgencyLevel: String,val uuid:String, val
return Task(title, urgencyLevel, uuid, priority)
}
}
}
}
20 changes: 18 additions & 2 deletions lib/app/services/deep_link_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,25 @@ class DeepLinkService extends GetxService {

void _initDeepLinks() {
_appLinks = AppLinks();

_appLinks.uriLinkStream.listen((uri) {
debugPrint('🔗 LINK RECEIVED: $uri');
_handleWidgetUri(uri);
});

_loadInitialLink();
}

Future<void> _loadInitialLink() async {
try {
final Uri? initialUri = await _appLinks.getInitialLink();
if (initialUri != null) {
debugPrint('🔗 INITIAL LINK: $initialUri');
_handleWidgetUri(initialUri);
}
} catch (e) {
debugPrint('Failed to get initial link: $e');
}
}

void _handleWidgetUri(Uri uri) {
Expand Down Expand Up @@ -53,7 +68,8 @@ class DeepLinkService extends GetxService {
Get.toNamed(Routes.DETAIL_ROUTE, arguments: ["uuid", uuid]);
}
} else if (uri.host == "addclicked") {
if (Get.context != null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (Get.context == null) return;
Get.dialog(
Material(
child: AddTaskBottomSheet(
Expand All @@ -63,7 +79,7 @@ class DeepLinkService extends GetxService {
),
),
);
}
});
}
}
}