Wait for a keypress in Dart

Issue

I’d like to pause execution of my Dart script (in a webpage) until the user hits a key. The following code works, but I’m wondering if there’s any better way of doing it:

import 'dart:html';
import 'dart:async';

StreamSubscription sub;

Future main() async {
  KeyboardEvent k = await getkey();
  print(k.keyCode.toString());
}

Future<KeyboardEvent> getkey() async {
  Completer<KeyboardEvent> c = new Completer<KeyboardEvent>();
  sub = document.onKeyDown.listen((KeyboardEvent e){
    sub.cancel();
    c.complete(e);
  });
  return c.future;
}

Update: Gunter’s solution below is ideal. The code above shortens to:

import 'dart:html';
import 'dart:async';

StreamSubscription sub;

Future main() async {
  KeyboardEvent k = await getkey();
  print(k.keyCode.toString());
}

Future<KeyboardEvent> getkey() async {
  return document.onKeyDown.first;
}

However, if I want to filter the keypresses I think I’m back to the former style:

import 'dart:html';
import 'dart:async';

StreamSubscription sub;

Future main() async {
  KeyboardEvent k = await getkey([KeyCode.A,KeyCode.B,KeyCode.C,KeyCode.D]);
  print(k.keyCode.toString());
}

Future<KeyboardEvent> getkey([List<int> lst]) async {
  Completer<KeyboardEvent> c = new Completer<KeyboardEvent>();
  sub = document.onKeyDown.listen((KeyboardEvent e){
    if ((lst==null)||(lst.contains(e.keyCode))){
      sub.cancel();
      c.complete(e);
    }
  });
  return c.future;
}

Is that right?

Update Thanks again to Gunter! Result is:

Future<KeyboardEvent> getkey([List<int> lst]) async {
  return document.onKeyDown.firstWhere((KeyboardEvent e)=>((lst==null)||(lst.contains(e.keyCode))));
}

Used as follows:

import 'dart:html';
import 'dart:async';

Future main() async {
  KeyboardEvent k = await getkey();
  print(k.keyCode.toString());
  KeyboardEvent k = await getkey([KeyCode.A,KeyCode.B,KeyCode.C,KeyCode.D]);
  print(k.keyCode.toString());
}

Solution

Not tested, but as far as I remember changing

  Completer<KeyboardEvent> c = new Completer<KeyboardEvent>();
  sub = document.onKeyDown.listen((KeyboardEvent e){
    sub.cancel();
    c.complete(e);
  });
  return c.future;

to

  return document.onKeyDown.first;

should do the same.

Update

  return document.onKeyDown.firstWhere((KeyboardEvent e) => 1st.contains(e.keyCode));

(again not tested)

Answered By – Günter Zöchbauer

Answer Checked By – Terry (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *