Navigate pending SSD reviews without invalidating labels

ober

f726597559ae6ba421071eab233ff59e0b4d7ad1

diff --git a/templates/ssd-review-parts/SsdSession.ss b/templates/ssd-review-parts/SsdSession.ss
index 63ccff3..4028bde 100644
--- a/templates/ssd-review-parts/SsdSession.ss
+++ b/templates/ssd-review-parts/SsdSession.ss
@@ -17,6 +17,7 @@
            ssdSessionSuppressedGroupPresent? ssdSessionFindGroupById
            ssdSessionSelectedGroup ssdCurrentSelectedGroup
            ssdSessionSelectedGroupId ssdSessionRelativeGroupId
+           ssdGroupPendingReview ssdSessionPendingRelativeGroupId
            ssdCurrentRelativeGroupId ssdSessionCellIdsForGroupId
            ssdSessionGroupPresent ssdSessionGroupMissing
            ssdGroupMissing ssdGroupOrEmpty
@@ -590,6 +591,63 @@
                                (SsdSession-groups session)
                                (mod (+ (+ current delta) size)
                                     size)))))))))
+          (def (ssdGroupPendingReview (group : SsdGroup))
+               :
+               Bool
+               (and (not (equal? (SsdGroup-status group) "reviewed"))
+                    (and (not (equal? (SsdGroup-status group) "approved"))
+                         (string-ends-with?
+                           (string-trim (SsdGroup-label group))
+                           "?"))))
+          (def (ssdSessionPendingGroups (session : SsdSession))
+               :
+               (MutableList SsdGroup)
+               (for/fold
+                 ((pending (mutable-list-empty SsdGroup)))
+                 ((i (in-range (int32 0)
+                       (list-size (SsdSession-groups session)))))
+                 (let ([group (list-ref (SsdSession-groups session) i)])
+                   (begin
+                     (if (ssdGroupPendingReview group)
+                         (mutable-list-add! pending group)
+                         (begin))
+                     pending))))
+          (def (pendingGroupIndexById
+                 (groups : (List SsdGroup))
+                 (id : (Nullable String)))
+               :
+               Int32
+               (if (nullable-null? id)
+                   (int32 -1)
+                   (let ([wanted (nullable-get id)])
+                     (for/fold
+                       ((found (int32 -1)))
+                       ((i (in-range (int32 0) (list-size groups))))
+                       (if (>= found (int32 0))
+                           found
+                           (if (equal? (SsdGroup-id (list-ref groups i)) wanted)
+                               i
+                               found))))))
+          (def (ssdSessionPendingRelativeGroupId
+                 (session : SsdSession)
+                 (id : (Nullable String))
+                 (delta : Int32))
+               :
+               (Nullable String)
+               (let ([pending (ssdSessionPendingGroups session)])
+                 (let ([size (list-size pending)])
+                   (if (= size (int32 0))
+                       (nullable-none String)
+                       (let ([index (pendingGroupIndexById pending id)])
+                         (let ([current (if (< index (int32 0))
+                                            (if (< delta (int32 0))
+                                                (int32 0)
+                                                (int32 -1))
+                                            index)])
+                           (nullable-some
+                             (SsdGroup-id
+                               (list-ref pending
+                                 (mod (+ (+ current delta) size) size))))))))))
           (def (ssdCurrentRelativeGroupId
                  (session : (Nullable SsdSession))
                  (id : (Nullable String))
@@ -598,7 +656,7 @@
                (Nullable String)
                (if (nullable-null? session)
                    (nullable-none String)
-                   (ssdSessionRelativeGroupId
+                   (ssdSessionPendingRelativeGroupId
                      (nullable-get session)
                      id
                      delta)))
diff --git a/templates/ssd-review-parts/UiTextHelpers.ss b/templates/ssd-review-parts/UiTextHelpers.ss
index a8ea387..4534f2a 100644
--- a/templates/ssd-review-parts/UiTextHelpers.ss
+++ b/templates/ssd-review-parts/UiTextHelpers.ss
@@ -3217,7 +3217,9 @@
                      (mainActivitySelectGroup activity view session
                        (nullable-some (nullableTextOrEmpty next))
                        feedbackConstant)
-                     (begin))))
+                     (mainActivitySetStatusRaw
+                       activity
+                       "No unapproved ? groups remain"))))
           (def (mainActivityFinalizeGroupLabel
                  (activity : MainActivity)
                  (group : SsdGroup))
@@ -3992,9 +3994,6 @@
                :
                Unit
                (begin
-                 (mainActivityAdvanceLoadGeneration
-                   activity
-                   currentGeneration)
                  (reviewViewRotateClockwise view)
                  (begin)))
           (def (mainActivitySeedBundledTruthAsync