Start exactly the merged item
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file-length / file length <= 250 lines (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
release-apk / release (APK) (push) Waiting to run
repo-contract / repo contract (push) Waiting to run

The board orders cards by column, so a cancelled older item with the
same title could be listed last and was started instead of the item
the merge added (T1866). Start now targets <id8>-<sections - 1> only.

Todo: 64d39ab5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Krzysztof Rudnicki 2026-11-09 18:28:17 +01:00
parent 135f3f07ea
commit cc9789f530
3 changed files with 24 additions and 4 deletions

View File

@ -73,8 +73,8 @@ class BoardClient {
}
/// Clicks Start on the note's last startable item titled [title]. With
/// [sections], first waits until the board shows the note's last section
/// (`<id8>-<sections - 1>`), since a merge just added it.
/// [sections], that is the note's last section (`<id8>-<sections - 1>`),
/// which a merge just added: waits until the board shows it.
Future<StartResult> start(
String noteId,
String title, {
@ -85,9 +85,11 @@ class BoardClient {
bool seen(List<Map<String, dynamic>> cs) =>
last == null || cs.any((c) => c['id'] == last);
final cards = await _until(noteId, seen);
// Never an older same-titled item in place of the merged one.
// Exactly the merged item: never an older same-titled one, which the
// board may list last (it orders by column, T1866).
final card = seen(cards)
? cards.reversed
.where((c) => last == null || c['id'] == last)
.where((c) => c['title'] == title && _startable(c))
.firstOrNull
: null;

View File

@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.64+1
version: 1.0.65+1
environment:
sdk: ^3.12.2

View File

@ -158,6 +158,24 @@ void main() {
expect(b.posts, isEmpty);
});
test('T1866: starts the merged item, not a re-startable older one', () async {
// The board lists by column: a cancelled older item may come last.
final b = _Board([
_card('cccccccc-0', 'Młody'),
_card('cccccccc-2', 'Młody'),
_card('cccccccc-1', 'Młody', column: 'done'),
]);
final r = await b.client().start(_id, 'Młody', sections: 3);
expect(r, (ok: true, reason: null, item: 'cccccccc-2'));
final other = _Board([
_card('cccccccc-1', 'Młody', column: 'done'),
_card('cccccccc-0', 'Młody', start: false),
]);
final none = await other.client().start(_id, 'Młody', sections: 1);
expect(none.reason, 'no startable item');
expect(other.posts, isEmpty);
});
test('T1864: a slow Start that took effect is ok, not unreachable', () async {
final b = _Board([_card('cccccccc-0', 'Młody')])
..postDelay = const Duration(milliseconds: 200);