native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Revert "perf(shelf): keep terminal out of spine layout animation"

This reverts commit 84f86c79ae73e5f24cd6cdec99be56a6f7b4527e.

onevcat f63a43b0 84f86c79

+5 -65
+5 -65
supacode/Features/Shelf/Views/ShelfView.swift
··· 37 37 books.firstIndex(where: { $0.id == id }) 38 38 } 39 39 40 - ZStack(alignment: .leading) { 41 - spineFlow(books: books, openBookID: openBookID, openIndex: openIndex) 42 - openBookOverlay(books: books, openIndex: openIndex, state: state) 43 - } 44 - .frame(maxWidth: .infinity, maxHeight: .infinity) 45 - .background(Color(nsColor: .windowBackgroundColor).opacity(surfaceBackgroundOpacity)) 46 - } 47 - 48 - @ViewBuilder 49 - private func spineFlow(books: [ShelfBook], openBookID: ShelfBook.ID?, openIndex: Int?) 50 - -> some View 51 - { 52 40 HStack(spacing: 0) { 53 41 ForEach(Array(books.enumerated()), id: \.element.id) { index, book in 54 42 spine(book: book, index: index, openIndex: openIndex) 55 43 if book.id == openBookID { 56 - terminalPlaceholder() 44 + openBookArea(for: book, state: state) 45 + .transition(.opacity) 57 46 } 58 47 } 59 48 if openBookID == nil { 60 - terminalPlaceholder() 49 + emptyOpenArea() 61 50 } 62 51 } 63 52 .frame(maxWidth: .infinity, maxHeight: .infinity) 53 + .background(Color(nsColor: .windowBackgroundColor).opacity(surfaceBackgroundOpacity)) 64 54 // Animate on every openBookID change — covers both Shelf-originated 65 55 // book switches (which also set their own TCA animation) and 66 56 // left-nav-originated switches, so the spine flow is consistent 67 - // regardless of entry point. The real terminal is rendered in a 68 - // non-layout overlay, so this animation only moves spines and the 69 - // lightweight placeholder. 57 + // regardless of entry point. 70 58 .animation(.easeInOut(duration: 0.2), value: openBookID) 71 - } 72 - 73 - @ViewBuilder 74 - private func terminalPlaceholder() -> some View { 75 - Color.clear 76 - .frame(maxWidth: .infinity, maxHeight: .infinity) 77 - .layoutPriority(1) 78 - .accessibilityHidden(true) 79 59 } 80 60 81 61 @ViewBuilder ··· 105 85 store.send(.repositoryManagement(.openRepositorySettings(book.repositoryID))) 106 86 } 107 87 ) 108 - } 109 - 110 - @ViewBuilder 111 - private func openBookOverlay( 112 - books: [ShelfBook], openIndex: Int?, state: RepositoriesFeature.State 113 - ) -> some View { 114 - GeometryReader { proxy in 115 - let frame = openBookOverlayFrame(in: proxy.size, bookCount: books.count, openIndex: openIndex) 116 - openBookOverlayContent(books: books, openIndex: openIndex, state: state) 117 - .frame(width: frame.width, height: proxy.size.height) 118 - .clipped() 119 - .offset(x: frame.minX) 120 - } 121 - } 122 - 123 - private func openBookOverlayFrame(in size: CGSize, bookCount: Int, openIndex: Int?) -> ( 124 - minX: CGFloat, width: CGFloat 125 - ) { 126 - let leftSpineCount = openIndex.map { $0 + 1 } ?? bookCount 127 - let rightSpineCount = openIndex.map { bookCount - $0 - 1 } ?? 0 128 - let minX = CGFloat(leftSpineCount) * ShelfMetrics.spineWidth 129 - let occupiedWidth = CGFloat(leftSpineCount + rightSpineCount) * ShelfMetrics.spineWidth 130 - return (minX, max(0, size.width - occupiedWidth)) 131 - } 132 - 133 - @ViewBuilder 134 - private func openBookOverlayContent( 135 - books: [ShelfBook], 136 - openIndex: Int?, 137 - state: RepositoriesFeature.State 138 - ) -> some View { 139 - if let openIndex { 140 - openBookArea(for: books[openIndex], state: state) 141 - .id(books[openIndex].id) 142 - .transition(.opacity.animation(.easeInOut(duration: 0.12))) 143 - } else { 144 - emptyOpenArea() 145 - .id("__empty__") 146 - .transition(.opacity.animation(.easeInOut(duration: 0.12))) 147 - } 148 88 } 149 89 150 90 /// Dispatch the open-book action only when `book` isn't already the open