Skip to content

Commit

Permalink
feat: add vikunja as text share intent receiver
Browse files Browse the repository at this point in the history
fix: qs tile add task for android api 34
  • Loading branch information
Benimautner committed Jun 2, 2024
1 parent fe5810c commit 9446e5f
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 43 deletions.
6 changes: 6 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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?) {
Expand All @@ -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"
}

}


Expand All @@ -51,7 +52,21 @@ class MainActivity : FlutterActivity() {
.setMethodCallHandler {
call, result ->
if (call.method!!.contentEquals("isQuickTile")) {
result.success(isQuickTile)
val list: MutableList<String> = mutableListOf<String>();
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
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
Expand Down
14 changes: 12 additions & 2 deletions lib/components/AddDialog.dart
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -17,18 +18,27 @@ class AddDialog extends StatefulWidget {
final ValueChanged<String>? 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<StatefulWidget> createState() => AddDialogState();
}

class AddDialogState extends State<AddDialog> {
class AddDialogState extends State<AddDialog> with AfterLayoutMixin<AddDialog> {
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)
Expand Down
69 changes: 39 additions & 30 deletions lib/pages/landing_page.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:after_layout/after_layout.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -28,8 +30,7 @@ class LandingPage extends HomeScreenWidget {
State<StatefulWidget> createState() => LandingPageState();
}

class LandingPageState extends State<LandingPage>
with AfterLayoutMixin<LandingPage> {
class LandingPageState extends State<LandingPage> {
int? defaultList;
bool onlyDueDate = true;
List<Task> _tasks = [];
Expand All @@ -44,40 +45,47 @@ class LandingPageState extends State<LandingPage>
);
}

@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<String> 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<String>? method = (await platform.invokeMethod("isQuickTile", "")).map<String>((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
Expand Down Expand Up @@ -166,7 +174,7 @@ class LandingPageState extends State<LandingPage>
);
}

_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'),
Expand All @@ -175,6 +183,7 @@ class LandingPageState extends State<LandingPage>
showDialog(
context: context,
builder: (_) => AddDialog(
prefilledTitle: prefilledTitle,
onAddTask: (title, dueDate) => _addTask(title, dueDate, context),
decoration: new InputDecoration(
labelText: 'Task Name', hintText: 'eg. Milk')));
Expand Down
2 changes: 1 addition & 1 deletion lib/pages/project/project_task_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ class _ListPageState extends State<ListPage> {
displayDoneTasks: displayDoneTasks);
}

Future<void> _addItemDialog(BuildContext context, [Bucket? bucket]) {
Future<void> _addItemDialog(BuildContext context, [Bucket? bucket, String? taskName]) {
return showDialog(
context: context,
builder: (_) => AddDialog(
Expand Down

0 comments on commit 9446e5f

Please sign in to comment.