feat(#43): flash Windows taskbar on new message when window unfocused

pull/46/head
Strycher 1 month ago
parent 54016b1d65
commit 9608336749

@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart';
import '../helpers/reaction_helper.dart';
import '../l10n/app_localizations.dart';
import '../utils/platform_info.dart';
import 'windows_taskbar_service.dart';
class NotificationService {
static final NotificationService _instance = NotificationService._internal();
@ -166,6 +167,7 @@ class NotificationService {
int? badgeCount,
}) async {
if (!await _ensureInitialized()) return;
await WindowsTaskbarService.flash();
final androidDetails = AndroidNotificationDetails(
'messages',
@ -266,6 +268,7 @@ class NotificationService {
int? badgeCount,
}) async {
if (!await _ensureInitialized()) return;
await WindowsTaskbarService.flash();
final androidDetails = AndroidNotificationDetails(
'channel_messages',

@ -0,0 +1,29 @@
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart' show debugPrint;
import 'package:flutter/services.dart';
/// Flashes the Windows taskbar button to draw attention e.g. a new message
/// arriving while the app window is not in the foreground.
///
/// The native side (`windows/runner/flutter_window.cpp`) only flashes when the
/// window is not already the foreground window, so callers don't need to track
/// focus themselves. No-op on every non-Windows platform.
class WindowsTaskbarService {
WindowsTaskbarService._();
static const MethodChannel _channel = MethodChannel(
'meshcore_open/windows_taskbar',
);
/// Flash the taskbar button if the window isn't focused. Safe on any platform
/// (no-op off Windows) and harmless if the native handler isn't registered.
static Future<void> flash() async {
if (!Platform.isWindows) return;
try {
await _channel.invokeMethod<void>('flash');
} catch (e) {
debugPrint('WindowsTaskbarService.flash failed: $e');
}
}
}

@ -1,5 +1,9 @@
#include "flutter_window.h"
#include <windows.h>
#include <flutter/standard_method_codec.h>
#include <optional>
#include "flutter/generated_plugin_registrant.h"
@ -25,6 +29,35 @@ bool FlutterWindow::OnCreate() {
return false;
}
RegisterPlugins(flutter_controller_->engine());
// Taskbar flash channel - Dart flashes the taskbar button on a new message
// when the window isn't focused (see lib/services/windows_taskbar_service.dart).
taskbar_channel_ =
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
flutter_controller_->engine()->messenger(),
"meshcore_open/windows_taskbar",
&flutter::StandardMethodCodec::GetInstance());
taskbar_channel_->SetMethodCallHandler(
[this](const flutter::MethodCall<flutter::EncodableValue>& call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>
result) {
if (call.method_name() == "flash") {
HWND hwnd = GetHandle();
if (hwnd != nullptr && GetForegroundWindow() != hwnd) {
FLASHWINFO info = {};
info.cbSize = static_cast<UINT>(sizeof(info));
info.hwnd = hwnd;
info.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
info.uCount = 0;
info.dwTimeout = 0;
FlashWindowEx(&info);
}
result->Success();
} else {
result->NotImplemented();
}
});
SetChildContent(flutter_controller_->view()->GetNativeWindow());
flutter_controller_->engine()->SetNextFrameCallback([&]() {

@ -3,6 +3,7 @@
#include <flutter/dart_project.h>
#include <flutter/flutter_view_controller.h>
#include <flutter/method_channel.h>
#include <memory>
@ -28,6 +29,10 @@ class FlutterWindow : public Win32Window {
// The Flutter instance hosted by this window.
std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
// Channel for native taskbar control (e.g. flash on new message).
std::unique_ptr<flutter::MethodChannel<flutter::EncodableValue>>
taskbar_channel_;
};
#endif // RUNNER_FLUTTER_WINDOW_H_

Loading…
Cancel
Save

Powered by TurnKey Linux.