From 9f026a57eb08d3cae65993d8d9af0040a9607467 Mon Sep 17 00:00:00 2001 From: Markus Wageringel Date: Thu, 11 Aug 2022 21:44:42 +0200 Subject: [PATCH] fix an issue in which level 1 does not immediately unlock This happened when the cursor is moved back to level 0 before navigating to the subpage of level 1. The selector for rebuilding questions was too restrictive, so that the level 1 questions would never rebuild (and thus not become visible) in this case. A workaround for this problem in 1.1.2 is to solve level 0 again, or to change the theme or reset the progress. --- CHANGELOG.md | 3 +++ lib/main.dart | 13 ++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef65789..96e6ca1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog ## [Unreleased] +### Fixed +- an issue in which level 1 did not unlock + (Workaround for version 1.1.2: Solve the very first question again or change the theme.) ## [1.1.2] - 2022-07-22 ### Added diff --git a/lib/main.dart b/lib/main.dart index 1cce19a..9eaac01 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -533,11 +533,18 @@ class ExamsScreen extends StatelessWidget { padding: listPadding, itemCount: Provider.of(context, listen: false).levels.length, // as number of levels is constant, not listening avoids unnecessary rebuilds itemBuilder: (context, levelIdx) => Selector( - selector: (context, game) => levelIdx == game.activeLevel && game.inExamScreen, // isActive - shouldRebuild: (bool oldIsActive, bool isActive) => oldIsActive || isActive, - builder: (_, isActive, child) { // we do not use the inner context since world changes (such as theme) would not trigger a rebuild + selector: (context, game) { + // Rendering exam questions is only relevant when in the exam screen. + // This deliberately covers a broad range of questions to avoid missing important rebuilds. + // Fortunately, Flutter only renders the questions that are visible on screen. + final isRelevant = game.inExamScreen; + return isRelevant; + }, + shouldRebuild: (bool oldIsRelevant, bool newIsRelevant) => oldIsRelevant || newIsRelevant, + builder: (_, isRelevant, child) { // we do not use the inner context since world changes (such as theme) would not trigger a rebuild final game = Provider.of(context, listen: false); // listening not needed, since selector already does assert((levelIdx > 0) ^ game.levels[levelIdx].exercise.questions.isEmpty); + final isActive = levelIdx == game.activeLevel && game.inExamScreen; final level = game.levels[levelIdx]; final label = 'Level $levelIdx'; final unlocked = levelIdx <= game.levelsUnlocked || debugUnlockAll;