Skip to content

refactor(ios): extract row detail logic into RowDetailViewModel#1166

Merged
datlechin merged 1 commit intomainfrom
refactor/row-detail-viewmodel
May 9, 2026
Merged

refactor(ios): extract row detail logic into RowDetailViewModel#1166
datlechin merged 1 commit intomainfrom
refactor/row-detail-viewmodel

Conversation

@datlechin
Copy link
Copy Markdown
Member

Summary

P1 #5 step 3 of 3: lift business logic out of RowDetailView (514 LOC) into a new RowDetailViewModel. The View drops to 360 LOC and now owns only sheet state (fkPreviewItem, showShareSheet, shareText) and haptic triggers; the ViewModel owns row data, edit lifecycle, save, and lazy cell loading.

What moves into the ViewModel:

  • All row state: rows, currentIndex, isEditing, editedValues, loadingCell, fullValueOverrides, isSaving, operationError, showSaveSuccess
  • Domain context (let constants): columns, columnDetails, foreignKeys, table, session, databaseType, safeModeLevel, onSaved, loadFullValueProvider
  • Methods: startEditing(), cancelEditing(), saveChanges() -> Bool, loadFullValue(ref:cellIndex:), setEditedValue(_:at:), toggleNull(at:), row(at:), cells(at:), columnDetail(for:), isPrimaryKey(at:), hasOverride(forRow:cellIndex:)
  • Computed properties: isView, canEdit, supportsLazyLoading, currentRow, currentRowCells
  • Auto-dismiss success toast logic (the 2-second Task.sleep + withAnimation cancellation) lives in the VM as scheduleSuccessDismiss(), with dismissSuccessTask cancelled in deinit

What stays in the View:

  • fkPreviewItem, showShareSheet, shareText (UI sheet state)
  • hapticSuccess, hapticError, hapticSelection (sensory feedback triggers)
  • Body composition, toolbar buttons, share menu, row content rendering, editable field rendering
  • The operation-error alert binds to viewModel.operationError != nil via a derived Binding<Bool> (no parallel @State flag)

Test plan

  • Open a row from DataBrowser: paged TabView swipe between rows updates currentIndex, selection haptic fires
  • Tap "Edit" on a row that has a primary key column: editable mode shows TextFields for non-PK fields, PK fields display as read-only with an orange key
  • Toggle NULL on a field: text disappears, "NULL" capsule turns accent. Toggle off: empty text returns
  • Save with changes: SQL UPDATE runs, success toast appears for 2 seconds, success haptic, parent's onSaved fires, list reloads
  • Save with no changes: just exits edit mode (no SQL fired, no error)
  • Save error (e.g. constraint violation): operation error alert shows, error haptic, edit mode stays
  • Tap "Cancel" while editing: edits discarded, exits edit mode
  • BLOB column with cell.isLoadable: "Load full value" button fires, progress shows on that cell, value populates
  • FK column tap: opens FKPreviewView sheet
  • Share / Copy via toolbar menu, all formats

@datlechin datlechin merged commit 5cad8f4 into main May 9, 2026
1 check passed
@datlechin datlechin deleted the refactor/row-detail-viewmodel branch May 9, 2026 18:59
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