fix: reclassify transient errors as non-fatal and fix top crashes

- main: record transient I/O, plugin-teardown, and non-crashing UI errors
  (network/websocket/timeout, MissingPluginException, image-load, layout
  overflow) as non-fatal, and add a grouping reason to async errors so
  distinct errors stop collapsing into one catch-all Crashlytics issue
- irc: guard IRCMessage.fromString against malformed/truncated lines that
  threw RangeError, with regression tests
- chat: wrap the emote menu in OverflowBox so it no longer overflows
  (RenderFlex) while the panel collapses
- chat: fix onBadgeError returning a List instead of a Map, which threw a
  Future.catchError type error during channel asset loads
- video: skip setAutoPipMode on Android < 12 where it isn't implemented

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tommy Chow 2026-06-21 15:04:11 -04:00
parent 6c969b0d97
commit ef1b1ded5d
6 changed files with 156 additions and 70 deletions

View file

@ -622,6 +622,24 @@ void main() {
expect(msg.localEmotes, isNotNull);
expect(msg.localEmotes!.containsKey('Kappa'), isTrue);
});
test('returns Command.none for a truncated line without a command', () {
// A malformed/truncated line (e.g. from the recent-messages history API)
// whose message section is a single token used to throw a RangeError on
// splitMessage[1]. It must now parse safely as a none command.
final msg = IRCMessage.fromString('@historical=1 :justaprefix');
expect(msg.command, Command.none);
expect(msg.tags['historical'], '1');
});
test('returns Command.none for a line with no separating space', () {
// No space means there are no tags to slice and no body to parse; must
// not throw on the substring/split calls.
final msg = IRCMessage.fromString('@onlytags');
expect(msg.command, Command.none);
});
});
group('USERSTATE', () {