Skip to content

Add configurable full Add Torrent dialogue with settings and per-field visibility#71

Merged
taylorcox75 merged 1 commit into
taylorcox75:feature/v3.0.0from
qstyler:feature/add-full-dialogue-v3
Mar 28, 2026
Merged

Add configurable full Add Torrent dialogue with settings and per-field visibility#71
taylorcox75 merged 1 commit into
taylorcox75:feature/v3.0.0from
qstyler:feature/add-full-dialogue-v3

Conversation

@qstyler
Copy link
Copy Markdown
Contributor

@qstyler qstyler commented Mar 16, 2026

Summary

This PR adds an optional full Add Torrent dialogue and a matching settings screen so users can control which torrent options appear when adding new torrents.

When Use full dialogue is off, the existing quick add-torrent modal behaves exactly as before. When it’s on, the + button opens a full-screen Add Torrent flow that respects per-field visibility toggles and existing categories/tags.

Changes

types/preferences.ts

  • Add AddTorrentDialogField and two new preferences:
    • useFullAddTorrentDialogue: when enabled, the + button opens the full add-torrent screen.
    • addTorrentDialogueFields: per-field booleans controlling which inputs appear in the full dialogue.
  • Extend DEFAULT_PREFERENCES with defaults for all add-torrent fields (source, save path, category, tags, limits, etc.).
    • Source (link or file) is always enabled and cannot be turned off.

Settings: appearance and add-torrent configuration

  • app/settings/appearance.tsx

    • Add an “Add torrent dialogue” row under Appearance, linking to the new configuration screen.
    • Text is fully localized via screens.settings.addTorrentDialogue* keys.
  • app/settings/add-torrent-dialogue.tsx (new)

    • New screen under Settings → Appearance:
      • Top-level Use full dialogue switch (backed by useFullAddTorrentDialogue).
      • Full dialogue fields list with per-field toggles backed by addTorrentDialogueFields.
    • Loads/saves preferences through storageService.
    • Normalizes stored preferences so source is always true, and if any older data has source: false, it is corrected and re-saved.
    • Uses existing theming, typography, spacing, shadows, and SafeArea header pattern consistent with other settings screens.

Full Add Torrent screen

  • app/torrents/add.tsx (new)
    • New full-screen Add Torrent route used when useFullAddTorrentDialogue is enabled.
    • Layout:
      • Uses SafeAreaView + KeyboardAvoidingView with edges={['top']} and bottom padding from useSafeAreaInsets() so content and primary button respect iOS notch / Dynamic Island / home indicator.
      • Sections: Source, Destination, Options, Limits, with labels and copy from i18n.
    • Source
      • URL/magnet TextInput plus .torrent file picker (via expo-document-picker), mutually exclusive.
      • Uses the same validation as the existing modal; shows an error if no URL/magnet or file is provided.
    • Destination
      • Category: single-select dropdown powered by existing categories from useTorrents():
        • Options: None, existing categories, and a Create New Category pseudo-option.
        • Picking Create New Category opens a two-step InputModal flow (name → optional save path) and calls categoriesApi.addCategory.
        • When a category is selected, the save path is auto-updated from the category’s savePath (if present).
      • Tags: multi-select dropdown with existing tags from useTorrents():
        • Uses a new MultiSelectPicker component for a consistent modal checkbox UI.
        • Create New Tag button opens InputModal and calls tagsApi.createTags, then selects the new tag.
    • Options & Limits
      • Exposes the expected torrent options mapped to the qBittorrent WebUI API:
        • Booleans backed by switches: stopped (Start Paused), skip_checking, root_folder, autoTMM, sequentialDownload, firstLastPiecePrio.
        • Text inputs (numeric) for dlLimit, upLimit, ratioLimit, seedingTimeLimit.
        • Optional rename and cookie fields.
      • The Submit handler builds a single options object and calls:
        • torrentsApi.addTorrent() when using a URL/magnet.
        • torrentsApi.addTorrentFile() when using a .torrent file.
      • Uses toast messaging and existing error keys for failure/success, then navigates back on success.
    • Field visibility
      • The screen reads addTorrentDialogueFields from preferences and only renders enabled inputs.
      • Normalizes preferences on load to enforce source: true and updates stored preferences if an older value had source: false.

Multi-select picker component

  • components/MultiSelectPicker.tsx (new)
    • Generic modal for multi-select lists (used for tags):
      • Checkbox-style options with Ionicons, optional per-option icon, and a “selected” visual state.
      • Centers itself on screen and adjusts within safe-area insets, mirroring the existing OptionPicker UX.
    • Reuses existing theme colors, spacing, typography, and card shadows.

Wire up the Add button

  • app/(tabs)/index.tsx
    • Preserve existing behavior when full dialogue is disabled:
      • If useFullAddTorrentDialogue is not set or false, + still opens the legacy quick add-torrent modal.
    • When useFullAddTorrentDialogue is true, tapping + now navigates to /torrents/add instead of showing the modal.
    • If reading preferences throws (e.g. first launch / storage issue), we gracefully fall back to the existing modal.

Localization

  • locales/en, es, fr, de, zh/translation.json
    • Add screens.addTorrent.* keys for all new labels/placeholders in the full add dialogue.
    • Add screens.settings.addTorrentDialogue, addTorrentDialogueDescription, useFullDialogue, useFullDialogueHint,
      fullDialogueFields, and nested addTorrentDialogueFields.* keys for each field.
    • Updated a few existing strings (urlOrMagnet, selectTorrentFile, yourServers, etc.) to localized equivalents in non-English locales.

Testing

  • iOS simulator / device
    • Verified the header and primary button respect safe areas (Dynamic Island / home indicator) on the Add Torrent screen.
    • With Use full dialogue OFF:
      • + opens the existing quick add-torrent modal; adding via magnet or file still works.
    • With Use full dialogue ON:
      • + navigates to the full Add Torrent screen.
      • Toggling individual fields in Settings shows/hides the corresponding inputs.
      • Category single-select:
        • Existing categories appear; selecting one updates the save path when the category has a savePath.
        • “Create New Category” flow creates a category via the API and selects it.
      • Tags multi-select:
        • Existing tags can be selected/deselected via the multi-select modal.
        • “Create New Tag” creates and auto-selects the new tag.
      • Submit succeeds for:
        • Magnet-only, file-only, and with various combinations of optional fields (limits, rename, cookie).
      • Validation error when trying to submit without URL/magnet or file.

Screenshots

@qstyler qstyler marked this pull request as ready for review March 16, 2026 10:31
@taylorcox75 taylorcox75 merged commit 21a8143 into taylorcox75:feature/v3.0.0 Mar 28, 2026
taylorcox75 added a commit that referenced this pull request Mar 28, 2026
* Add comprehensive codebase improvement plan

Covers 5 categories across 40+ actionable items:
- Architectural improvements (feature-based structure, TanStack Query, API client)
- Maintainability (mega-component decomposition, i18n, tests, linting, error handling)
- Performance (memoization, FlashList, Reanimated migration, context optimization)
- Design gaps (7 critical bugs, accessibility, Android compat, type safety)
- Missing features (RSS, search, scheduling, notifications, API key auth, widgets)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Add v3 redesign vision document

Apollo/Things 3-inspired redesign plan covering:
- Honest critique of current UI (rainbow buttons, mixed design languages, no hierarchy)
- New design system (4 semantic colors, SF Pro typography, grouped inset lists)
- Screen-by-screen redesign for all 6 screens
- Interaction & motion design (springs, haptics, swipe gestures, native context menus)
- 7 specific 'wow factor' moments (shared element transitions, completion celebration, etc.)
- Phased implementation roadmap (4 phases, ~10 weeks)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Add v3 implementation risk register

Identifies specific landmines in the redesign plan:
- Onboarding is dead code (not wired up, no route gate)
- Color reduction would break the color picker contract + user overrides
- SF Symbols swap requires native deps (kills Expo Go workflow)
- 180+ relative imports make file restructuring high-risk
- Alert.prompt is used in 13 places (all broken on Android)
- FlashList + TorrentCard local state = recycling bugs
- Proposes safe 5-wave implementation order with golden rule

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Add AI agent maintainability guide

Identifies 9 problems that slow down AI coding agents:
- 10 files over 900 lines (settings.tsx is 1957 lines)
- No AGENTS.md or .cursorrules
- Untyped preferences bag (Record<string, any>)
- Zero tests (no verification loop)
- 7 duplicated code patterns
- Implicit contracts (string keys, no enums)
- No file-level documentation
- No path aliases (relative import errors)
- 15 dead/unused files wasting context window

Proposes top 5 actions ordered by impact-per-effort

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Consolidate into single PLAN.md for parallel agent execution

Replaces plan.md, v3-redesign.md, v3-risks.md, ai-maintainability.md
with a single PLAN.md organized into:

Phase 1 (AI infrastructure): 9 parallelizable tasks
  - AGENTS.md, typed preferences, path aliases, bug fixes,
    Alert.prompt→InputModal, deduplication, file headers, tests, linting

Phase 2 (UI redesign): 7 parallelizable tasks
  - Design system, TorrentCard, torrent detail, swipe actions,
    FAB removal, transfer screen, settings sub-screens

Phase 3 (architecture): 5 tasks
  - Import migration, type safety, i18n, TanStack Query, dead code

Each task includes: files to read, files to modify, risks, acceptance criteria.
Appendices cover future features and risk quick-reference.

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* PLAN.md: delete dead code (not move), enforce naming conventions

- Dead code files are deleted outright, not moved to _unused/. Git history preserves them.
- Added naming conventions section: PascalCase components, camelCase utils, kebab-case services, tests/ at root (not __tests__/)
- Explained (tabs) is Expo Router framework syntax, not a naming choice
- Updated AGENTS.md template and test task to match conventions

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Fix 10 gaps in PLAN.md that would break agent execution

Critical fixes:
1. Task 2.2 removed context menu with NO replacement — now specifies ActionMenu.tsx
   (a bottom-anchored modal, no native modules needed)
2. Task 1.5 / 2.2 conflict — skip TorrentCard Alert.prompt fix (2.2 rewrites it)
3. Added missing Confetti hooks-in-loop fix (Task 1.4e)
4. Added missing ActionSheetIOS Android fix (Task 1.4f)
5. Added missing react-native-gesture-handler install (Task 1.4g)
6. Phase 2 tasks are NOT independent — added dependency graph
7. New code must use @/ aliases immediately (not wait for Task 3.1)
8. Settings sub-screens may need _layout.tsx for Expo Router
9. Task 1.7 scoped to files >200 lines only (was all 70 files)
10. Added QuickConnectPanel to Task 1.6 dedup (was only utility functions)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* PLAN.md: document Expo Router naming conventions ([hash], _layout)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Refine PLAN.md to resolve functional planning gaps

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Add PLAN.md review with 4 errors, 5 warnings, and 7 suggestions

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Simplify PLAN_REVIEW.md: remove items already fixed by prior agent

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Merge review findings: correct isNetworkError count, add 3 missing items

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* PLAN.md review: iOS-first scope + factual corrections

- iOS-first clarification:
  - Task 1.4c removed (haptics iOS guard is intentional)
  - Task 1.4f removed (ActionSheetIOS acceptable; also dead code)
  - Alert.prompt critical rule softened to preference for InputModal
  - expo-* packages (incl. expo-symbols) explicitly approved
  - Native module risk updated: expo-* OK, third-party need approval
  - Task 2.2 context menu note updated (no longer blocked)
  - AGENTS.md Cursor Cloud instructions updated for iOS-first

- Factual corrections from codebase grep:
  - Alert.prompt: 14 total (TorrentDetails has 6, not 5); Task 1.5 = 13 callsites
  - react-native-gesture-handler: imported in 1 component, not 2
    (DraggableTorrentList does not import it directly)
  - ActionSheetIOS showTrackerMenu is dead code (never called from JSX)
    — moved cleanup to Task 3.5

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.1: Create AGENTS.md for AI agent guidance

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.3: Add TypeScript path aliases (@/ prefix)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.4a: Fix invalid backgroundColor string literal in _layout.tsx

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.4b: Fix usesCleartextTraffic to boolean and remove trailing space from app name

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.4d: Convert isRecoveringFromBackground from useRef to useState in TorrentContext

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.9: Add ESLint and Prettier configuration

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.4e: Fix Rules of Hooks violation in Confetti.tsx — replace useRef-in-loop with useMemo

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.4g: Add react-native-gesture-handler as explicit dependency

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.2: Add typed AppPreferences interface and update storage service

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.4h: Move @react-navigation/bottom-tabs from devDependencies to dependencies

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.5: Replace Alert.prompt with InputModal in [hash].tsx and TorrentDetails.tsx

- Added allowEmpty prop to InputModal to support '0' for unlimited values
- Replaced 7 Alert.prompt calls in app/torrent/[hash].tsx:
  handleSetDownloadLimit, handleSetUploadLimit, handleSetCategory,
  handleAddTags, handleRemoveTags, handleSetLocation, handleRenameTorrent
- Replaced 6 Alert.prompt calls in components/TorrentDetails.tsx:
  handleAddCategory, handleShareLimit, handleSetLocation,
  handleRenameTorrent (handleSetName), handleAddPeers, handleRenameFile
- Used keyboardType='numeric' for limit inputs
- Used allowEmpty for limit/category inputs that accept empty/zero
- Skipped TorrentCard.tsx (rewritten in Task 2.2)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.6: Create utils/server.ts with avatarColor, serverAddress, AVATAR_PALETTE

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.6: Create utils/torrent-state.ts with canonical getStateColor and getStateLabel

Reconciled from three diverged implementations:
- TorrentCard.tsx (switch-based, most complete — used as base)
- torrent/[hash].tsx (if-else chain, string-based matching)
- ExpandableTorrentCard.tsx (ternary chain, color only)

Colors passed as parameter to avoid hook dependency.

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.6: Create components/QuickConnectPanel.tsx

Extracted the 'not connected' server list UI duplicated in both
index.tsx and transfer.tsx. Uses useTranslation() for all strings
(transfer.tsx had hardcoded English). Takes onConnect and onAddServer
callbacks.

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.6: Extract isNetworkError helper in services/server-manager.ts

Replaced 3 duplicated inline network-error checks with a single
exported isNetworkError(error) function.

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.6: Replace inline copies with imports from shared utilities

- index.tsx: Replaced inline avatarColor/serverAddress/AVATAR_PALETTE
  and ~100 lines of quick-connect JSX with QuickConnectPanel
- transfer.tsx: Same — removed avatarColorT/serverAddressT and
  ~100 lines of quick-connect JSX
- [hash].tsx: Import getStateColor/getStateLabel from utils/torrent-state
- TorrentCard.tsx: Import getStateColor/getStateLabel from utils/torrent-state
- ExpandableTorrentCard.tsx: Import getStateColor from utils/torrent-state

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.8: Add unit tests for format utils, torrent state, and color theme manager

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 1.7: Add JSDoc file headers to complex source files

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.1: Update dark/light color defaults in ThemeContext

- Dark background: rgb(15,15,15) → #000000 (true black for OLED)
- Dark surface: #1C1C1E, surfaceOutline: #38383A
- Fix all invalid rgb() calls with alpha → proper rgba() format
- Map similar states to same visual color: stateMetadata/stateChecking/stateQueued → orange; statePaused/stateOther → gray
- Use iOS system colors (SF Symbols palette) for error/success/warning
- Update trueBlackColors to match new dark palette
- Clean up light mode: remove alpha from opaque colors, use iOS system colors
- Add hex passthrough to rgbaToHex for color picker compatibility

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.1: Add largeTitle and headline to typography scale

- largeTitle: 34pt Bold, lineHeight 41 (iOS large title style)
- headline: 17pt Semibold, lineHeight 22 (for torrent names, replaces 15pt)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.1: Simplify shadow presets

- Keep card and medium as active presets
- Zero out small, cardPressed, large (kept for backward compatibility)
- Keep filterActive, add TODO to source color from theme
- Document that shadows are invisible on dark backgrounds

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.2a: Create useTorrentActions hook and ActionMenu component

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.2b: Redesign TorrentCard with 4-line layout and React.memo

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.2c: Wire up ActionMenu and useTorrentActions in torrent list

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.6: Redesign transfer screen with grouped inset sections

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.3: Redesign torrent detail with grouped inset sections

Replace Quick Tools (5 colored buttons) + Advanced (16 rainbow buttons) layout
with iOS-style grouped inset list sections:

- Hero: torrent name (22pt), state dot + label, progress bar, ETA, size
- Actions: 3 outlined buttons (Pause/Resume, Recheck, Delete)
- GENERAL: Size, Downloaded, Uploaded, Ratio, Save Path, Category (OptionPicker),
  Tags (InputModal), Remove Tags (InputModal)
- TRANSFER: DL/UL Speed, ETA, DL/UL Limit (InputModal)
- NETWORK: Seeds, Peers (tappable → peers modal), Availability
- CONTENT: Files, Trackers (navigation rows)
- ADVANCED: Priority (OptionPicker), Sequential DL / F-L Piece / Super Seed /
  Force Start (toggles with Switch), Rename / Move to (InputModal), Reannounce
- DATES: Added, Completed, Last Activity

All 21 original actions remain accessible via toggle, picker, input, or nav rows.
Uses colors.surface/background/surfaceOutline for consistent theming.
No hardcoded colors. All modals use InputModal (not Alert.prompt).

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.7: Redesign top-level settings as navigation hub

Break 1957-line settings.tsx into a ~269-line navigation hub.
Add app/settings/_layout.tsx with nested Stack for sub-screen routing.
Top-level shows connection status card and navigation rows to:
Servers, Appearance, Torrent Defaults, Notifications, Advanced, What's New, About.
App version displayed at bottom.

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.7: Extract appearance settings sub-screen

New app/settings/appearance.tsx with:
- Language picker
- Theme & Colors navigation (links to existing theme.tsx)
- Compact card view toggle
- Refresh interval setting
Uses useFocusEffect for data reloading, useTheme() for styling.

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.7: Extract torrent defaults sub-screen

New app/settings/torrent-defaults.tsx with:
- Default sort by/direction/filter pickers
- Pause on add, default save path, auto-categorize, first/last piece priority
- Categories management (add/delete) when connected
- Tags management (add/delete) when connected
Categories and tags shown only when isConnected.

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.7: Extract notifications sub-screen

New app/settings/notifications.tsx with:
- Toast/notification duration setting
- Haptic feedback toggle (with setHapticsEnabled integration)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.7: Extract advanced settings sub-screen

New app/settings/advanced.tsx with:
- Connection timeout, API timeout, retry attempts
- Debug mode toggle with connectivity log integration
- View logs navigation
- Backup/restore (export/import settings)
- Danger zone: shutdown qBittorrent (when connected)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.7: Extract servers sub-screen

New app/settings/servers.tsx with:
- SwipeableServerItem local component (extracted from settings.tsx)
- Server list with add/edit/delete via swipe
- Connect/disconnect per server
- Auto-connect to last server toggle
- Add server button in header

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.7: Extract what's new and about sub-screens

New app/settings/whats-new.tsx:
- Full changelog from CHANGELOG constant
- Formatted release dates, grouped by version

New app/settings/about.tsx:
- App version, React Native version, platform info
- qBittorrent server info (version, API, libtorrent, arch) when connected
- Community links (GitHub, issues, donate)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Fix headlineSmall → headline reference in theme.tsx

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.4: Add swipe actions (pause/resume, delete, force start) to torrent list

- Import Swipeable and RectButton from react-native-gesture-handler
- Add GestureHandlerRootView wrapper in _layout.tsx (required for gestures)
- Wrap each torrent card in Swipeable with three actions:
  - Swipe left (short): Pause/Resume with amber/green background
  - Swipe left (full): Delete with red background and confirmation alert
  - Swipe right: Force start with blue background and lightning icon
- Add haptic feedback (medium) at swipe threshold via onSwipeableWillOpen
- Track open swipeable ref to auto-close previous when new one opens
- Swipe actions call torrentsApi directly (parameterized by torrent)
- Disable swipe in select mode

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 2.5: Replace FAB with header add button, remove scroll hide/show logic

- Remove Animated.View FAB element and its TouchableOpacity child
- Remove fabScale, isFabVisible refs and all Animated.timing calls for FAB
- Remove tab bar hide/show logic: isTabBarVisible ref, getTabBarStyle helper,
  navigation.setOptions calls that toggled tab bar visibility
- Remove useNavigation import (no longer needed)
- Simplify handleScroll to header show/hide only (removed FAB + tab bar parts)
- Add '+' button in header area next to sort button (calls setShowAddModal)
- Remove handleAddTorrent wrapper (inlined into button onPress)
- Remove stale FAB styles (fab, fabTouchable) from StyleSheet
- Clean up stale comments referencing FAB

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.5: Delete 13 dead/unused component and route files

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.1: Migrate imports to @/ aliases in app/torrent/

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: i18n coverage for logs screen

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.1: Migrate imports to @/ aliases in app/server/

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.1: Migrate imports to @/ aliases in app/settings/

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.1: Migrate imports to @/ aliases in app/_layout.tsx

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.5: Delete 13 dead code files and remove unused client fields

- csrfToken: removed property, setter (response interceptor), getter (getCsrfToken),
  and logging references in auth.ts — token was captured but never sent
- apiTimeout: removed field storage in updateSettings and caller references
  in _layout.tsx and advanced.tsx — value was stored but never read
- showTrackerMenu: removed dead function and ActionSheetIOS/Platform imports
  from manage-trackers.tsx — function was never called from rendered JSX
- Updated AGENTS.md to reflect dead code cleanup completion

Note: The 13 dead code files were already deleted in commit f0cc829.

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.1: Migrate imports to @/ aliases in components/

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.1: Migrate imports to @/ aliases in services/

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.1: Migrate all relative imports to @/ path aliases

Migrated remaining ../  imports in context/, hooks/, services/, i18n/,
and types/ directories to use @/ path aliases.

Directories completed in order:
  app/(tabs)/ → app/torrent/ → app/server/ → app/settings/ →
  app/ root → components/ → context/ → hooks/ → services/

16 files changed, 30 imports converted in this commit.
All relative ../ imports of shared modules are now eliminated.

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: i18n coverage for torrent detail and trackers

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: i18n coverage for torrents list screen

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Fix duplicate useTranslation import and add missing getErrorMessage import in [hash].tsx

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: i18n coverage for settings screen

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.1: Migrate remaining import to @/ alias in types/preferences.ts

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: i18n coverage for TorrentCard and torrent state labels

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: i18n coverage for theme, server add/edit, manage-trackers

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: i18n coverage for TorrentDetails component

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.2: Replace any types with proper TypeScript types across codebase

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: i18n coverage for server add/edit forms and new locale keys

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: Sync all i18n keys to es, zh, fr, de locale files with English placeholders

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.3: i18n coverage for server add/edit screens

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.4: Add TanStack Query infrastructure

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.4: Migrate TransferContext to TanStack Query

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.4: Migrate TorrentContext to TanStack Query with rid-based sync

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.4: Migrate ServerContext to TanStack Query

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Task 3.4: Update AGENTS.md to reflect TanStack Query architecture

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Upgrade ESLint v8 → v9 with flat config, fix deprecation warnings

- Removed deprecated eslint v8, @typescript-eslint/parser, @typescript-eslint/eslint-plugin,
  eslint-plugin-react (not needed for RN), eslint-plugin-react-hooks v4
- Installed eslint v9, @eslint/js, typescript-eslint, eslint-plugin-react-hooks v5,
  eslint-config-prettier (current versions)
- Converted .eslintrc.js to eslint.config.js (ESLint v9 flat config format)
- Pre-existing code patterns set to warn (not error): react-hooks/refs,
  immutability, purity, set-state-in-effect, preserve-caught-error
- 0 errors, 125 warnings (all pre-existing)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Add implementation plan for torrent display and controls improvements

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Update IMPLEMENTATION_PLAN with UI Fix Plan (post-refactor issues)

Co-authored-by: Taylor Cox <taylorcox75@gmail.com>

* Fix npm ERESOLVE conflict and consolidate planning docs (#58)

* Initial plan

* Implement all 6 issues from IMPLEMENTATION_PLAN.md

Issue 1: Alt speed limits shown in transfer screen with ALT badge
Issue 2: Pause/resume button on torrent cards
Issue 3: Full-width progress bar, percent+ETA in status line
Issue 4: Pause-on-add syncs with server preference
Issue 5: Expanded card view with detail rows
Issue 6: Search bar reordered (Sort | Search | Add)

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Address code review feedback: rename variable, extract helper, use async/await

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Update IMPLEMENTATION_PLAN.md with completion status and remaining gaps

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* fix: downgrade @eslint/js from ^10.0.1 to ^9.18.0 to resolve ERESOLVE conflict with eslint 9.x

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* fix: show verified bytes for "Downloaded" instead of raw wire bytes (#59)

* Initial plan

* fix: use torrent.completed instead of torrent.downloaded for Downloaded display

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* merge PLAN.md and IMPLEMENTATION_PLAN.md into single consolidated document

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* UX: state-colored progress bars, alt speed subtitle, Apple-style tags modal (#60)

* Initial plan

* Add TagsModal, show alt speed limits subtitle, progress bar already uses state colors

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Copilot/update torrent progress bar colors (#61)

* Initial plan

* Implement all 6 issues from IMPLEMENTATION_PLAN.md

Issue 1: Alt speed limits shown in transfer screen with ALT badge
Issue 2: Pause/resume button on torrent cards
Issue 3: Full-width progress bar, percent+ETA in status line
Issue 4: Pause-on-add syncs with server preference
Issue 5: Expanded card view with detail rows
Issue 6: Search bar reordered (Sort | Search | Add)

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Address code review feedback: rename variable, extract helper, use async/await

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Update IMPLEMENTATION_PLAN.md with completion status and remaining gaps

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* fix: downgrade @eslint/js from ^10.0.1 to ^9.18.0 to resolve ERESOLVE conflict with eslint 9.x

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Initial plan

* Add TagsModal, show alt speed limits subtitle, progress bar already uses state colors

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Fix merge conflict: remove IMPLEMENTATION_PLAN.md consolidated into PLAN.md (#62)

* Initial plan

* Fix merge conflict: delete IMPLEMENTATION_PLAN.md (consolidated into PLAN.md on base branch)

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Fix card view toggle semantics and resolve merge conflicts with cursor/codebase-improvement-plan-8686 (#63)

* Initial plan

* Initial plan for detailed torrent view fixes

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Fix detailed torrent view formatting and settings toggle logic

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Merge cursor/codebase-improvement-plan-8686 and resolve all conflicts

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Remove orphaned compactCardView locale keys

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Torrent detail: merge tag actions, category badge, reannounce icon, responsive toggles (#65)

* Initial plan

* Update torrent detail: merge tags UI, category badge, reannounce icon, optimistic toggles, toast on reannounce

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Fix toggle re-entry guards and remove dead handleRemoveTags handler

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Package update

* Fix alt-speed display, category/tags UI consistency, and reannounce animation feedback (#67)

* Initial plan

* Fix alt-speed display, category UI, and reannounce animation

- Issue 2: Fix alt-speed display showing Unlimited when a limit IS set.
  getEffectiveLimit now passes dl/up_rate_limit directly (already reflects
  alt limits when active). formatAltLimitLabel uses rate limits when alt
  speed is on, prefs values when off.
- Issue 1: Replace Category Alert.alert with OptionPicker (same custom-modal
  style as TagsModal). Both the Quick Actions button and the inline Category
  button in the General Info section now call handleSetCategory -> OptionPicker.
  Add New Category… is a special picker entry that opens InputModal.
- Issue 3: Add spinning Animated.View around the refresh icon on the
  Reannounce button so users see visual confirmation when the action fires.

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Fix alt speed limit display; expand detailed torrent card stats (#68)

* Initial plan

* Fix speed limit display when alt speed ON; add more stats to detailed card view

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Fix alt speed limit unit display and add editable alt speed limits (#69)

* Initial plan

* Fix alt speed limit display; add UI to edit alternative speed limit values

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Fix alt upload limit never reading back from preferences after save (#70)

* Initial plan

* Fix alt upload limit not updating: use correct preferences key alt_ul_limit

Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>

* Add configurable full Add Torrent dialogue with settings and per-field visibility (#71)

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: taylorcox75 <10939863+taylorcox75@users.noreply.github.com>
Co-authored-by: Konstantin Bodnia <konstantin@bodnia.net>
@taylorcox75
Copy link
Copy Markdown
Owner

Not all heroes wear capes. Thanks @qstyler

this will be in v3 which I know has a few minor bugs like setting upload limit. But I’ll be posting to TestFlight later today regardless with all those other changes in the branch.

@qstyler
Copy link
Copy Markdown
Contributor Author

qstyler commented Mar 29, 2026

@taylorcox75
thanks for merging my PR
there's another thing that I really miss: handling magnet link press
i'll make a PR for that later next week

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.

2 participants