From 9446e5f174c23db7b1510c601fd63b3b39e00d33 Mon Sep 17 00:00:00 2001 From: Benimautner Date: Sun, 2 Jun 2024 14:04:24 +0200 Subject: [PATCH] feat: add vikunja as text share intent receiver fix: qs tile add task for android api 34 --- android/app/src/main/AndroidManifest.xml | 6 ++ .../vikunja/flutteringvikunja/MainActivity.kt | 33 ++++++--- .../flutteringvikunja/VikunjaTileService.kt | 15 +++- lib/components/AddDialog.dart | 14 +++- lib/pages/landing_page.dart | 69 +++++++++++-------- lib/pages/project/project_task_list.dart | 2 +- 6 files changed, 96 insertions(+), 43 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index fd4ace3..d140377 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -58,6 +58,12 @@ + + + + + + diff --git a/android/app/src/main/kotlin/io/vikunja/flutteringvikunja/MainActivity.kt b/android/app/src/main/kotlin/io/vikunja/flutteringvikunja/MainActivity.kt index 11c6568..001d8b9 100644 --- a/android/app/src/main/kotlin/io/vikunja/flutteringvikunja/MainActivity.kt +++ b/android/app/src/main/kotlin/io/vikunja/flutteringvikunja/MainActivity.kt @@ -12,7 +12,8 @@ import io.flutter.plugin.common.MethodChannel import android.util.Log class MainActivity : FlutterActivity() { - private var isQuickTile: Boolean? = false + private var launchMethod: String? = null + private var sharedText: String? = null private val CHANNEL = "vikunja" override fun onCreate(savedInstanceState: Bundle?) { @@ -28,19 +29,19 @@ class MainActivity : FlutterActivity() { private fun handleIntent(intent: Intent, flutterEngine: FlutterEngine, isNewIntent: Boolean) { val action: String? = intent.action val type: String? = intent.type - Log.e("VIKUNJA", "Action: $action") - Log.e("VIKUNJA", "Type: $type") val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) + sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); if ("ACTION_INSERT" == action && type != null && "ADD_NEW_TASK" == type) { - Log.e("VIKUNJA","Is ACTION_INSERT"); if(isNewIntent) channel.invokeMethod("open_add_task", "") - isQuickTile = true; - } - else { - isQuickTile = false; + launchMethod = "open_add_task"; + } else if (Intent.ACTION_SEND == action && type != null && "text/plain" == type && sharedText != null) { + if(isNewIntent) + channel.invokeMethod("open_add_task_with_text", "$sharedText") + launchMethod = "open_add_task_with_text" } + } @@ -51,7 +52,21 @@ class MainActivity : FlutterActivity() { .setMethodCallHandler { call, result -> if (call.method!!.contentEquals("isQuickTile")) { - result.success(isQuickTile) + val list: MutableList = mutableListOf(); + if(launchMethod != null) { + list.add(launchMethod.toString()); + } + if (sharedText != null) { + list.add(sharedText.toString()); + } + if(list.size > 0) { + result.success(list); + } else { + result.error("UNAVAILABLE", "No Quick Tile", null); + } + + launchMethod = null + sharedText = null } } } diff --git a/android/app/src/main/kotlin/io/vikunja/flutteringvikunja/VikunjaTileService.kt b/android/app/src/main/kotlin/io/vikunja/flutteringvikunja/VikunjaTileService.kt index 88cad44..3fea6f1 100644 --- a/android/app/src/main/kotlin/io/vikunja/flutteringvikunja/VikunjaTileService.kt +++ b/android/app/src/main/kotlin/io/vikunja/flutteringvikunja/VikunjaTileService.kt @@ -2,6 +2,7 @@ package io.vikunja.flutteringvikunja import android.content.Intent +import android.app.PendingIntent import android.os.Build import android.service.quicksettings.TileService import android.util.Log @@ -17,7 +18,19 @@ class VikunjaTileService : TileService(){ addIntent.action = "ACTION_INSERT" addIntent.type = "ADD_NEW_TASK" addIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK - startActivityAndCollapse(addIntent) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + startActivityAndCollapse( + PendingIntent.getActivity( + this, + 0, + addIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + ) + } else { + startActivityAndCollapse(addIntent) + } // Called when the user click the tile } diff --git a/lib/components/AddDialog.dart b/lib/components/AddDialog.dart index 6223f10..7e1267b 100644 --- a/lib/components/AddDialog.dart +++ b/lib/components/AddDialog.dart @@ -1,3 +1,4 @@ +import 'package:after_layout/after_layout.dart'; import 'package:flutter/material.dart'; import 'package:vikunja_app/components/datetimePicker.dart'; import 'package:vikunja_app/global.dart'; @@ -17,18 +18,27 @@ class AddDialog extends StatefulWidget { final ValueChanged? onAdd; final void Function(String title, DateTime? dueDate)? onAddTask; final InputDecoration? decoration; - const AddDialog({Key? key, this.onAdd, this.decoration, this.onAddTask}) + final String? prefilledTitle; + const AddDialog({Key? key, this.onAdd, this.decoration, this.onAddTask, this.prefilledTitle}) : super(key: key); @override State createState() => AddDialogState(); } -class AddDialogState extends State { +class AddDialogState extends State with AfterLayoutMixin { NewTaskDue newTaskDue = NewTaskDue.day; DateTime? customDueDate; var textController = TextEditingController(); + @override + void afterFirstLayout(BuildContext context) { + setState(() { + textController.text = widget.prefilledTitle ?? ""; + }); + super.activate(); + } + @override Widget build(BuildContext context) { if (newTaskDue != NewTaskDue.custom) diff --git a/lib/pages/landing_page.dart b/lib/pages/landing_page.dart index cb5894c..9646e8c 100644 --- a/lib/pages/landing_page.dart +++ b/lib/pages/landing_page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:after_layout/after_layout.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -28,8 +30,7 @@ class LandingPage extends HomeScreenWidget { State createState() => LandingPageState(); } -class LandingPageState extends State - with AfterLayoutMixin { +class LandingPageState extends State { int? defaultList; bool onlyDueDate = true; List _tasks = []; @@ -44,40 +45,47 @@ class LandingPageState extends State ); } - @override - void initState() { - Future.delayed( - Duration.zero, - () => _updateDefaultList().then((value) { - try { - platform.invokeMethod("isQuickTile", "").then((value) => - {if (value is bool && value) _addItemDialog(context)}); - } catch (e) { - log(e.toString()); - } - VikunjaGlobal.of(context) - .settingsManager - .getLandingPageOnlyDueDateTasks() - .then((value) => onlyDueDate = value); - })); - super.initState(); + + void handleMethod(List method) { + switch (method[0]) { + case "open_add_task": + _addItemDialog(context); + break; + case "open_add_task_with_text": + print("open_add_task_with_text: ${method[1]}"); + _addItemDialog(context, prefilledTitle: method[1]); + break; + } } - @override - void afterFirstLayout(BuildContext context) { + void scheduleIntent() async { try { // This is needed when app is already open and quicktile is clicked - platform.setMethodCallHandler((call) { - switch (call.method) { - case "open_add_task": - _addItemDialog(context); - break; - } - return Future.value(); - }); + List? method = (await platform.invokeMethod("isQuickTile", "")).map((val) => val.toString()).toList(); + + if(method != null) { + handleMethod(method); + } + } catch (e) { log(e.toString()); } + platform.setMethodCallHandler((call) async { + handleMethod([call.method.toString(), call.arguments.toString()]); + return Future.value(); + }); + } + + @override + void initState() { + super.initState(); + + Future.delayed(Duration.zero,() { + _updateDefaultList().then((_) { + scheduleIntent(); + } + ); + }); } @override @@ -166,7 +174,7 @@ class LandingPageState extends State ); } - _addItemDialog(BuildContext context) { + _addItemDialog(BuildContext context, {String? prefilledTitle}) { if (defaultList == null) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text('Please select a default list in the settings'), @@ -175,6 +183,7 @@ class LandingPageState extends State showDialog( context: context, builder: (_) => AddDialog( + prefilledTitle: prefilledTitle, onAddTask: (title, dueDate) => _addTask(title, dueDate, context), decoration: new InputDecoration( labelText: 'Task Name', hintText: 'eg. Milk'))); diff --git a/lib/pages/project/project_task_list.dart b/lib/pages/project/project_task_list.dart index 9596f48..1b1a66b 100644 --- a/lib/pages/project/project_task_list.dart +++ b/lib/pages/project/project_task_list.dart @@ -346,7 +346,7 @@ class _ListPageState extends State { displayDoneTasks: displayDoneTasks); } - Future _addItemDialog(BuildContext context, [Bucket? bucket]) { + Future _addItemDialog(BuildContext context, [Bucket? bucket, String? taskName]) { return showDialog( context: context, builder: (_) => AddDialog(