Skip to content

Refactor (packages/web/src/components/Share.tsx): Function with high complexity (count = 136): Share - #67

Open
EvuhLi wants to merge 6 commits into
CMU-313:mainfrom
EvuhLi:main
Open

Refactor (packages/web/src/components/Share.tsx): Function with high complexity (count = 136): Share#67
EvuhLi wants to merge 6 commits into
CMU-313:mainfrom
EvuhLi:main

Conversation

@EvuhLi

@EvuhLi EvuhLi commented Sep 5, 2026

Copy link
Copy Markdown

P1B: Starter Task: Refactoring PR

1. Issue

#44

/opencode/packages/web/src/components/Share.tsx

What do you think this file does?
Share.tsx opens up a socket to handle incoming messages using the OpenCode chat. When it receives an input from the user, it checks if the type is info, message, or part, and handles it accordingly. The file renders the connection and displays any content that is marked as isVisiblepart. It also handles closing the websocket.

What is the scope of your refactoring within that file?
My refactoring in this file is done within the Share component and the useScrollButton. I moved isVisiblePart, summarizeSessionInfo, shouldShowScrollButton, and disposeIfSet into their own independently testable functions, outside of the main Share component. This greatly reduced the complexity of the share component. All four of these have their behavior preserved.

Which Qlty‑reported issue did you address?
Function with high complexity (count = 136): Share

2. Refactoring

How did the specific issue you chose impact the codebase’s maintainability?

The specific issue I chose was impacting the codebases's maintainability because Share had high complexity. This was because there were four complex systems all within Share's own body, which could be extracted. This was an issue because none of these systems could be unit tested in isolation, since they were all bundled in the same function, and editing one of these could potentially break another function in the component. The body of the share function was also extremely long and difficult to step through.

What changes did you make to resolve the issue?

In order to resolve this issue, I extracted the four pieces into their own standalone functions. I preserved the behavior, but relocated the logic.

I moved isVisiblePart out of the callback inside Share's render loop into its own function. In Share, it now calls msg.parts.filter(isVisiblePart).

I moved summarizeSession out of the data() memo, which looped through messages in Share. Now, Share calls on summarizeSession(store.info, messages()) to achieve the same functionality.

I moved the show/hide logic in shouldShowScrollButton out of the component.

I also moved disposeIfSet, which was a method to cleanup any remaining components. Originally, this was five repeated if statements, and I extracted them into a single helper.

How do your changes improve maintainability? Did you consider alternatives?

Share's complexity dropped significantly, because the branching logic is now separated into 4 independent functions, promoting abstraction and clean code. All four of the functions have direct test coverage as well, which wasn't possible before because they were all nested within the main component. I considered splitting the Share component into sub components, like a MessageList component, isntead of extracting the functions. However, this could potentially impact styling and props, and required a much more significant change the could introduce bugs in the logic.

3. Validation

How did you validate that the change is correct?

I ran both bun lint and bun test. I also created tests for all of the extracted functions. The tests effectively covered every line of the four extracted functions and 29/29 tests passed.

Screenshot 2026-09-05 at 6 13 06 PM Screenshot 2026-09-05 at 6 13 19 PM

Attach a screenshot showing the tests that cover the change passing during CI
Screenshot 2026-09-05 at 6 40 05 PM

Attach a screenshot of qlty smells --no-snippets <full/path/to/file.ts> showing fewer reported issues after the changes.
Screenshot 2026-09-05 at 6 43 23 PM

EvuhLi added 6 commits August 30, 2026 22:02
The filteredParts predicate was an anonymous closure nested three
levels deep inside Share (For -> filter callback), which qlty
attributed to Share's own complexity/return-count score. Hoisting it
into a standalone function is behavior-preserving and lets the
smells report attribute its 8 early returns to the predicate itself.
The data() memo's cost/token/model reducer loop was inlined directly
inside Share, adding to its complexity score. Extracting it into a
standalone summarizeSession(info, msgs) function is behavior-
preserving (same accumulation logic, iterated with for-of instead of
an indexed loop since the index was never used).
…tton

The floating scroll-to-bottom button's signals, IntersectionObserver
sentinel, checkScrollNeed logic, and its onMount/onCleanup pair were
all inlined in Share, driving most of its remaining complexity.
useScrollButton() encapsulates the same logic unchanged and returns
{ visible, scrollToBottom, onMouseEnter, onMouseLeave } for the JSX
to wire up directly.
Exports the two functions extracted from Share out of Share.tsx and adds
unit tests exercising every branch: each isVisiblePart filter rule (plus
a realistic mixed-part integration case) and summarizeSession's cost/
token/model aggregation, last-write-wins fields, and edge cases around
missing session info or messages.
…seScrollButton

useScrollButton bundled its scroll-visibility decision and repeated
"clear this if it's set" cleanup checks inside one closure, which Qlty
flagged as high complexity (28) after the earlier Share extractions
moved it there. Pulling the pure show/hide predicate and a shared
disposeIfSet(value, dispose) helper out to top-level functions drops
useScrollButton out of the Qlty report entirely (file total complexity
144 -> 126) without introducing a new flagged function. Behavior is
unchanged; only where the branches live changed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant