iOS quick response (w.i.p)

This commit is contained in:
2024-12-21 21:06:14 +08:00
parent e458943f56
commit be98fe133d
11 changed files with 154 additions and 35 deletions

View File

@ -51,14 +51,29 @@ void appBackgroundDispatcher() {
case "WidgetUpdateRandomPost":
await widgetUpdateRandomPost();
return true;
case "ChatReplyMessage":
return true;
default:
return true;
}
});
}
@pragma("vm:entry-point")
FutureOr<void> appInteractiveBackgroundDispatcher(Uri? data) async {
print('Interactive background dispatcher called with $data');
switch (data?.path) {
case "/chat/reply":
final channelId = data?.queryParameters['channel_id'];
final eventId = data?.queryParameters['event_id'];
final message = data?.queryParameters['text'];
if (channelId != null && eventId != null && (message?.isNotEmpty ?? false)) {
await chatReplyMessage(channelId, eventId, message!);
}
break;
default:
break;
}
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
@ -90,13 +105,15 @@ void main() async {
appBackgroundDispatcher,
isInDebugMode: kDebugMode,
);
Workmanager().registerPeriodicTask(
"widget-update-random-post",
"WidgetUpdateRandomPost",
frequency: Duration(minutes: 1),
constraints: Constraints(networkType: NetworkType.connected),
tag: "widget-update",
);
if (Platform.isAndroid) {
Workmanager().registerPeriodicTask(
"widget-update-random-post",
"WidgetUpdateRandomPost",
frequency: Duration(minutes: 1),
constraints: Constraints(networkType: NetworkType.connected),
tag: "widget-update",
);
}
}
runApp(const SolianApp());

View File

@ -125,10 +125,8 @@ class ChatChannelProvider extends ChangeNotifier {
final channelBox = await Hive.openBox<SnChatMessage>(
'${ChatMessageController.kChatMessageBoxPrefix}${channel.id}',
);
final lastMessage = channelBox.isNotEmpty
? channelBox.values
.reduce((a, b) => a.createdAt.isAfter(b.createdAt) ? a : b)
: null;
final lastMessage =
channelBox.isNotEmpty ? channelBox.values.reduce((a, b) => a.createdAt.isAfter(b.createdAt) ? a : b) : null;
if (lastMessage != null) result.add(lastMessage);
channelBox.close();
}
@ -142,3 +140,19 @@ class ChatChannelProvider extends ChangeNotifier {
super.dispose();
}
}
Future<void> chatReplyMessage(channelId, eventId, String message) async {
print('Chat reply message called with $channelId $eventId $message');
try {
final snc = await SnNetworkProvider.createOffContextClient();
await snc.post('/cgi/im/quick/$channelId/reply/$eventId', data: {
'type': 'messages.new',
'body': {
'text': message,
'algorithm': 'plain',
},
});
} catch (err) {
print('Failed to send chat reply message: $err');
}
}

View File

@ -92,7 +92,7 @@ class SnNetworkProvider {
RequestOptions options,
RequestInterceptorHandler handler,
) async {
final atk = await _getFreshAtk(client, prefs.getString(kAtkStoreKey), (atk, rtk) {
final atk = await _getFreshAtk(client, prefs.getString(kAtkStoreKey), prefs.getString(kRtkStoreKey), (atk, rtk) {
prefs.setString(kAtkStoreKey, atk);
prefs.setString(kRtkStoreKey, rtk);
});
@ -145,12 +145,12 @@ class SnNetworkProvider {
final tkLock = Lock();
Future<String?> getFreshAtk() async {
return await _getFreshAtk(client, _prefs.getString(kAtkStoreKey), (atk, rtk) {
return await _getFreshAtk(client, _prefs.getString(kAtkStoreKey), _prefs.getString(kRtkStoreKey), (atk, rtk) {
setTokenPair(atk, rtk);
});
}
static Future<String?> _getFreshAtk(Dio client, String? atk, Function(String atk, String rtk)? onRefresh) async {
static Future<String?> _getFreshAtk(Dio client, String? atk, String? rtk, Function(String atk, String rtk)? onRefresh) async {
if (_refreshCompleter != null) {
return await _refreshCompleter!.future;
} else {
@ -183,7 +183,7 @@ class SnNetworkProvider {
final exp = jsonDecode(payload)['exp'];
if (exp <= DateTime.now().millisecondsSinceEpoch ~/ 1000) {
log('Access token need refresh, doing it at ${DateTime.now()}');
final result = await _refreshToken(client.options.baseUrl, atk);
final result = await _refreshToken(client.options.baseUrl, rtk);
if (result == null) {
atk = null;
} else {

View File

@ -1,9 +1,11 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:home_widget/home_widget.dart';
import 'package:surface/main.dart';
import 'package:surface/providers/sn_network.dart';
import 'package:surface/types/post.dart';
@ -15,6 +17,8 @@ class HomeWidgetProvider {
if (!kIsWeb && Platform.isIOS) {
await HomeWidget.setAppGroupId("group.solsynth.solian");
}
await HomeWidget.registerInteractivityCallback(appInteractiveBackgroundDispatcher);
}
Future<void> saveWidgetData(String id, dynamic data, {bool update = true}) async {