@@ -42,12 +42,18 @@ public extension TKUIRoutingResultsCard {
4242 public let identifier : String
4343 public let title : String
4444 public let subtitle : String ?
45+ /// Insert this custom mode after the mode with the matching identifier.
46+ ///
47+ /// If `nil`, the mode is inserted at the beginning of the picker. If the
48+ /// identifier cannot be found, the mode is appended at the end.
49+ public let after : String ?
4550 public let icon : TKImage
4651
47- public init ( identifier: String , title: String , subtitle: String ? = nil , icon: TKImage ) {
52+ public init ( identifier: String , title: String , subtitle: String ? = nil , icon: TKImage , after : String ? = nil ) {
4853 self . identifier = identifier
4954 self . title = title
5055 self . subtitle = subtitle
56+ self . after = after
5157 self . icon = icon
5258 }
5359
@@ -71,6 +77,11 @@ public extension TKUIRoutingResultsCard {
7177 public var limitToModes : Set < String > ? = nil
7278
7379 /// Additional routing modes to inject into the runtime mode picker.
80+ ///
81+ /// Custom modes with `after == nil` are inserted at the beginning in the
82+ /// order they are listed. Custom modes with `after` set are inserted after
83+ /// the matching mode identifier when present, or appended if that anchor
84+ /// does not exist.
7485 public var customModes : [ CustomMode ] = [ ]
7586
7687 /// Adjust the grouped backend routing requests derived from the current
@@ -190,14 +201,47 @@ extension TKUIRoutingResultsCard.Configuration {
190201 }
191202
192203 func routingModes( in regions: [ TKRegion ] ) -> [ TKRegion . RoutingMode ] {
193- let regionModes = TKRegionManager . sortedModes ( in: regions)
194- guard !customModes. isEmpty else { return regionModes }
195-
196- var seen = Set ( regionModes. map ( \. identifier) )
197- let injected = customModes
198- . map ( \. routingMode)
199- . filter { seen. insert ( $0. identifier) . inserted }
200- return regionModes + injected
204+ mergeCustomModes ( into: TKRegionManager . sortedModes ( in: regions) )
205+ }
206+
207+ func mergeCustomModes( into routingModes: [ TKRegion . RoutingMode ] ) -> [ TKRegion . RoutingMode ] {
208+ var routingModes = routingModes
209+ guard !customModes. isEmpty else { return routingModes }
210+
211+ var seen = Set ( routingModes. map ( \. identifier) )
212+ let injectedModes = customModes. filter { seen. insert ( $0. identifier) . inserted }
213+
214+ var insertionIndexAtStart = 0
215+ for mode in injectedModes where mode. after == nil {
216+ routingModes. insert ( mode. routingMode, at: insertionIndexAtStart)
217+ insertionIndexAtStart += 1
218+ }
219+
220+ var pendingAnchoredModes = injectedModes. filter { $0. after != nil }
221+ while !pendingAnchoredModes. isEmpty {
222+ var nextPending : [ CustomMode ] = [ ]
223+ var insertedAny = false
224+
225+ for mode in pendingAnchoredModes {
226+ guard let after = mode. after else { continue }
227+
228+ if let anchorIndex = routingModes. lastIndex ( where: { $0. identifier == after } ) {
229+ routingModes. insert ( mode. routingMode, at: routingModes. index ( after: anchorIndex) )
230+ insertedAny = true
231+ } else {
232+ nextPending. append ( mode)
233+ }
234+ }
235+
236+ if !insertedAny {
237+ routingModes. append ( contentsOf: nextPending. map ( \. routingMode) )
238+ break
239+ }
240+
241+ pendingAnchoredModes = nextPending
242+ }
243+
244+ return routingModes
201245 }
202246
203247 func routingModeIdentifiers( for selectedModeIdentifiers: Set < String > ) -> Set < String > {
0 commit comments