mirror of
https://github.com/go-vikunja/app
synced 2025-01-18 13:46:06 +00:00
feat: add vikunja as text share intent receiver
fix: qs tile add task for android api 34
This commit is contained in:
parent
fe5810cc13
commit
9446e5f174
@ -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" />
|
||||
|
@ -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<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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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<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)
|
||||
|
@ -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<StatefulWidget> createState() => LandingPageState();
|
||||
}
|
||||
|
||||
class LandingPageState extends State<LandingPage>
|
||||
with AfterLayoutMixin<LandingPage> {
|
||||
class LandingPageState extends State<LandingPage> {
|
||||
int? defaultList;
|
||||
bool onlyDueDate = true;
|
||||
List<Task> _tasks = [];
|
||||
@ -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
|
||||
@ -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'),
|
||||
@ -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')));
|
||||
|
@ -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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user