Skip to content

feat 723 : Multiple views for each board#727

Merged
tu2-atmanand merged 34 commits into
feat-591/fileForBoardfrom
feat-723/multipleViews
Apr 19, 2026
Merged

feat 723 : Multiple views for each board#727
tu2-atmanand merged 34 commits into
feat-591/fileForBoardfrom
feat-723/multipleViews

Conversation

@tu2-atmanand
Copy link
Copy Markdown
Owner

This is a part of the feature #698 . Both this and the PR 698 will be combined together and will be released in the next major version 2.0.0.

Will mostly going to release this branch with the PR 698 if everything goes well. Otherwise, as a fallback plan, PR 698 is the only feature which will be available in the major release.

This PR will going to successfully implement all the features and functionalities discussed in the following tickets :

@qodo-code-review

This comment was marked as outdated.

@tu2-atmanand tu2-atmanand marked this pull request as draft March 7, 2026 18:53
@qodo-code-review

This comment was marked as outdated.

@tu2-atmanand tu2-atmanand added feature New feature request enhancement An existing feature can be enhanced/improved. optimization The algorithm/code can be optimized. A better approach labels Mar 7, 2026
@github-project-automation github-project-automation Bot moved this to Backlogs in Task Board Dev Mar 7, 2026
@tu2-atmanand tu2-atmanand added the brainstorm These issue/feat needs to be discussed and have to find the solution label Mar 7, 2026
Comment thread src/managers/TaskBoardFileManager.ts
Comment thread main.ts
Comment thread src/managers/TaskBoardFileManager.ts
Comment thread src/settings/SettingSynchronizer.ts
@tu2-atmanand tu2-atmanand changed the base branch from release-v2.0.0 to feat-591/fileForBoard April 19, 2026 17:58
@tu2-atmanand tu2-atmanand marked this pull request as ready for review April 19, 2026 18:02
@tu2-atmanand tu2-atmanand merged commit e72f82d into feat-591/fileForBoard Apr 19, 2026
@github-project-automation github-project-automation Bot moved this from Important Backlog to Ready to Review in Task Board Dev Apr 19, 2026
@qodo-code-review
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Multiple Views Per Board with Enhanced Architecture and Date Handling Modernization

✨ Enhancement

Grey Divider

Walkthroughs

Description
• **Major architectural refactor**: Transformed board structure from single board to multiple views
  per board, enabling users to have different Kanban and Map views within the same board
• **View management system**: Added comprehensive view utilities for creating, duplicating,
  deleting, and reordering views with persistent state management
• **Auto-scroll drag support**: Implemented configurable auto-scroll functionality during drag
  operations with edge detection and adjustable scroll speed
• **Board persistence improvements**: Added debounced save functionality and migration system for
  v2.0.0 with automatic data migration on load
• **Enhanced date handling**: Modernized date parsing from moment.js to date-fns, centralized date
  extraction functions, and improved date formatting utilities
• **Improved task validation**: Added validation to prevent marking tasks complete if
  child/sub-tasks are incomplete, with sanitized reminder handling
• **Filter system refactoring**: Refactored scanning filters to return explicit mention status and
  improved filter validation with comprehensive error handling
• **UI enhancements**: Added new modals for view management (AddViewModal, DateTimePickerModal),
  boards explorer with scan functionality, and resizable views panel drawer
• **Settings reorganization**: Reordered UI settings, added support for new swimlane UI types, and
  improved date format validation
• **Translation updates**: Added comprehensive translations for multiple views, view management,
  swimlane configurations, and enhanced features
• **Bug fixes**: Fixed diff comparison logic, checkbox validation, filter state corruption, and
  improved error handling throughout
Diagram
flowchart LR
  A["Single Board<br/>Structure"] -- "Refactor to<br/>Multiple Views" --> B["Board with<br/>Views Array"]
  B -- "View Management<br/>Utilities" --> C["Add/Delete/<br/>Duplicate Views"]
  D["Moment.js<br/>Date Parsing"] -- "Modernize to<br/>date-fns" --> E["Improved Date<br/>Handling"]
  F["Drag Operations"] -- "Add Auto-scroll<br/>Support" --> G["Enhanced UX<br/>with Scroll"]
  H["Board File<br/>Manager"] -- "Add Debouncing<br/>& Migration" --> I["Persistent<br/>State v2.0.0"]
  C --> J["New Modals:<br/>AddViewModal"]
  E --> J
  G --> J
  I --> J
Loading

Grey Divider

File Changes

1. src/managers/DragDropTasksManager.ts ✨ Enhancement +325/-182

Auto-scroll drag support and multi-view board refactoring

• Added auto-scroll functionality during drag operations with configurable edge detection and scroll
 speed
• Updated swimlane data type from swimlaneDataProp | null | undefined to `swimlaneDataProp |
 undefined` throughout
• Changed currentBoardIndex to currentViewIndex in drag payload interface to support multiple
 views
• Refactored swimlane change handling to remove null checks and simplify logic flow
• Updated task update function calls to pass both oldTask and newTask parameters for better
 tracking
• Replaced DatePickerModal instantiation with openDateInputModal service function
• Removed tag sanitization from task move operations and fixed tag list source in tag-based column
 moves

src/managers/DragDropTasksManager.ts


2. src/managers/TaskBoardFileManager.ts ✨ Enhancement +374/-170

Board persistence with debouncing and migration system

• Added debounced save functionality to prevent rapid successive saves with configurable delay
• Implemented board data migration system with version checking and migration functions for v2.0.0
• Added scanAllTaskBoardFiles() method to discover and register all taskboard files in vault
• Refactored board file validation to clean up orphaned registry entries during plugin load
• Moved deprecated functions to end of file and added migration for new viewsPanel property
• Added currentPluginVersion tracking and automatic board data migration on load
• Improved documentation for registry management and file operations

src/managers/TaskBoardFileManager.ts


3. src/utils/taskLine/TaskContentFormatter.ts Refactoring +142/-120

Centralized date handling and improved property extraction

• Refactored date extraction to use centralized extractor functions from VaultScanner instead of
 inline regex
• Added date formatting using formatDateStringAsPerSettings and formatDateTimeAsPerSettings
 utilities
• Updated sanitizeTags function signature to remove oldTagsList parameter, simplifying tag
 handling
• Changed extractPriority return type to object with parsedString and value properties for
 better tracking
• Fixed task ID extraction logic to properly handle null returns and check for valid ID presence
• Improved regex patterns for date and time cleaning in legacy title cleanup

src/utils/taskLine/TaskContentFormatter.ts


View more (58)
4. src/managers/VaultScanner.ts Refactoring +169/-140

Date parsing modernization and extraction function refactoring

• Changed all date/time extraction functions to return RegExpMatchArray | null instead of strings
 for better match tracking
• Updated extractPriority and extractReminder to return objects with parsedString and value
 properties
• Added support for filtering unsupported checkbox symbols during task scanning
• Replaced moment.js date validation with date-fns parse and isValid functions
• Added testDate and supportedChecklistSymbols properties to VaultScanner class
• Updated task building logic to extract values from regex match arrays with proper null handling
• Improved file type filtering logic for archived notes folder detection

src/managers/VaultScanner.ts


5. src/settings/SettingConstructUI.ts ✨ Enhancement +129/-119

Settings UI reorganization and validation improvements

• Commented out experimental features toggle setting to hide it from UI
• Reordered scan filter types to prioritize tags and frontmatter before files and folders
• Moved hidden task properties settings section to appear after frontmatter tags setting
• Updated custom status display to include styling for IN_PROGRESS and ON_HOLD status types
• Added reload notice triggers when custom statuses are modified
• Changed date format validation button text from "verify" to "validate"
• Added taskBoard-settings-wide-input CSS class to date and date-time format settings
• Added duration parameter (0) to Notice calls for date format validation messages

src/settings/SettingConstructUI.ts


6. src/interfaces/BoardConfigs.ts ✨ Enhancement +338/-266

Refactor board structure to support multiple views per board

• Restructured board data model to support multiple views per board, replacing single board with
 views array containing TaskBoardView objects
• Added new interfaces KanbanView and MapView to encapsulate view-specific configurations
• Changed swimlaneConfigs from interface to type and replaced verticalHeaderUI boolean with
 headerUIType string property
• Updated DEFAULT_BOARDS to DEFAULT_BOARD (single board) with multiple pre-configured views and
 added pluginVersion, lastViewId, and viewsPanel properties
• Added swimlaneEnabled optional property to ColumnData type

src/interfaces/BoardConfigs.ts


7. src/utils/UserTaskEvents.ts ✨ Enhancement +109/-68

Enhance task update functions with validation and dual task parameters

• Added imports for Notice, sanitizeReminder, verifySubtasksAndChildtasksAreComplete, and
 translation helper
• Updated function signatures to accept both taskOld (original) and taskUpdated (potentially
 modified) parameters for task update functions
• Made updateTaskItemStatus async and added validation to prevent marking tasks complete if
 child/sub-tasks are incomplete
• Added sanitizeReminder call when updating reminder for inline-tasks
• Refactored updateTaskItemProperty to remove oldValue parameter and improve documentation
• Updated EditButtonMode.View to EditButtonMode.ViewInSplitTab and added new
 EditButtonMode.ViewInWindow case

src/utils/UserTaskEvents.ts


8. src/utils/DateTimeCalculations.ts ✨ Enhancement +104/-141

Simplify date parsing and refactor date utility functions

• Removed unused imports (TaskBoard, parseISO) and simplified date parsing logic
• Added formatToday utility function to get today's date in custom format
• Commented out complex ISO format detection and separator-based format detection in
 robustDateParser
• Simplified robustDateParser to use preferred format directly with fallback to native Date
 parsing
• Renamed formatDateAsPerSettings to formatDateStringAsPerSettings and simplified implementation
• Updated getUniversalDateFromTask and getUniversalDateEmoji to accept date type parameter
 instead of plugin instance
• Added deprecation notice for legacy getCurrentLocalDateTimeStringLegacy function

src/utils/DateTimeCalculations.ts


9. src/utils/algorithms/ScanningFilterer.ts ✨ Enhancement +136/-113

Refactor scanning filters to return explicit mention status

• Updated filter check functions (checkFileFilters, checkFrontMatterFilters,
 checkFolderFilters) to return boolean arrays [explicitelyMentioned, isAllowedToScan] instead of
 single boolean
• Improved regex pattern parsing to handle /pattern/flags format with proper flag extraction
• Added error handling with bug reporter for invalid regex patterns
• Refactored scanFilterForFilesNFoldersNFrontmatter to use explicit mention precedence logic
• Added verifySubtasksAndChildtasksAreComplete function to check if all child/sub-tasks are
 complete before allowing parent task completion

src/utils/algorithms/ScanningFilterer.ts


10. main.ts ✨ Enhancement +154/-51

Add board explorer modal and refactor board initialization

• Added debounce import from obsidian and new modal import openBoardsExplorerModal
• Updated activateView method to accept duplicate parameter and optional filePath to support
 opening specific board files
• Added event listener for OPEN_BOARD event to handle board opening from modals
• Replaced checkAndCreateBoardFiles with createTemplateBoard that creates a single default board
 on fresh install
• Updated command callbacks to pass false for duplicate parameter
• Added validateBoardFiles call during initialization
• Moved registerTaskBoardView call earlier in initialization sequence

main.ts


11. src/utils/lang/locale/en.ts ✨ Enhancement +45/-10

Add translations for multiple views and enhanced features

• Updated translation keys for edit button modes: added task-editor-tab and renamed existing modes
 for clarity
• Changed scan-tasks-from-the-vault to vault-scanner and updated related descriptions
• Added new translation keys for swimlane UI types, view management, and board operations
• Updated descriptions for date format settings with additional notes about inline-task limitations
• Added translations for new features: multiple views, view duplication, custom swimlanes, and task
 completion validation
• Improved wording in various descriptions for clarity and user guidance

src/utils/lang/locale/en.ts


12. src/modals/DiffContentCompareModal.ts 🐞 Bug fix +23/-23

Fix diff content comparison logic and improve clarity

• Fixed comparison logic in getHighlightedDiff method by correcting the order of content
 parameters
• Updated debug info section labels to correctly identify which content is being compared
• Improved explanatory text in debug info section to clarify the purpose of the Safe Guard feature
• Fixed formatting and trailing comma issues in code

src/modals/DiffContentCompareModal.ts


13. src/modals/BoardsExplorer.ts ✨ Enhancement +168/-18

Enhance boards explorer with scan and loading features

• Refactored modal structure to separate board grid rendering into renderBoardGrid method for
 better maintainability
• Added scan functionality with loading bar animation to refresh board registry
• Changed onBoardSelect callback parameter from boardName to filePath for proper board file
 handling
• Added openBoard method to load board data before opening
• Implemented loading bar with CSS animations during board scanning
• Added error handling and user notifications for scan and open operations

src/modals/BoardsExplorer.ts


14. src/utils/ViewUtils.ts ✨ Enhancement +251/-0

Add view management utility functions

• New utility file providing functions for managing multiple views within a board
• Includes functions to get, add, delete, duplicate, and reorder views
• Provides view type checking and filtering utilities
• Includes helper functions for creating default kanban columns and checking view existence

src/utils/ViewUtils.ts


15. src/utils/algorithms/ColumnSegregator.ts ✨ Enhancement +42/-40

Refactor column segregator for view-based architecture

• Updated function signature to accept TaskBoardView instead of Board for better separation of
 concerns
• Changed import from BoardFilterer to AdvancedFilterer
• Updated column filtering logic for otherTags case to work with view-specific columns
• Modified completed tasks handling to slice from 1000 items instead of applying limit immediately
• Updated manual ordering logic to work with view data structure
• Applied limit to completed tasks after filtering and sorting

src/utils/algorithms/ColumnSegregator.ts


16. src/utils/CheckBoxUtils.ts 🐞 Bug fix +27/-13

Fix checkbox utilities and improve indentation handling

• Fixed grammar in notice message: "customStatuses is" to "customStatuses are"
• Improved isTaskLine regex validation to check for exactly 5 capture groups instead of just
 length > 0
• Enhanced getObsidianIndentationSetting to handle undefined vault config settings with proper
 fallback logic
• Added explicit handling for uninitialized Obsidian settings

src/utils/CheckBoxUtils.ts


17. src/regularExpressions/TasksPluginRegularExpr.ts Formatting +6/-6

Fix regex formatting and add trailing commas

• Added missing trailing commas to regex constructor calls for consistency
• Fixed formatting in listItemRegex definition

src/regularExpressions/TasksPluginRegularExpr.ts


18. src/modals/date_time_picker/DateTimePickerComponent.ts ✨ Enhancement +210/-0

New DateTimePickerComponent for combined date-time selection

• New component for selecting both date and time with separate pickers
• Includes quick time options (morning, noon, afternoon, evening, night)
• Supports clearing time and combining date/time selections
• Provides callback handlers for apply and cancel actions

src/modals/date_time_picker/DateTimePickerComponent.ts


19. src/modals/AddViewModal.ts ✨ Enhancement +154/-0

New AddViewModal for creating board views

• New modal for adding views to a board with configurable name and type
• Supports selecting between kanban and map view types
• Includes form validation and keyboard shortcuts (Enter to submit, Escape to cancel)
• Integrates with addViewToBoard utility function

src/modals/AddViewModal.ts


20. src/interfaces/GlobalSettings.ts ⚙️ Configuration changes +7/-22

Settings updates for view management and drag behavior

• Added dragAutoScrollEdgePercent setting for drag-and-drop auto-scroll behavior
• Removed viewedType and boardIndex from lastViewHistory tracking
• Updated default board registry to use single board configuration
• Simplified board registry structure with fewer default boards

src/interfaces/GlobalSettings.ts


21. src/services/OpenModals.ts ✨ Enhancement +25/-19

Modal service updates for view-based architecture

• Updated openBoardConfigModal to accept currentViewIndex parameter
• Changed openBoardsExplorerModal callback to emit OPEN_BOARD event with file path
• Commented out openTaskBoardActionsModal function (deprecated)
• Updated openDateInputModal parameter order for initialValue

src/services/OpenModals.ts


22. src/utils/algorithms/AdvancedFilterer.ts 🐞 Bug fix +36/-10

Enhanced filter validation and error handling

• Added validation to filter out null/undefined filter groups before processing
• Improved error handling with safety checks for group structure
• Fixed formatting and added proper null checks in filter evaluation
• Prevents corruption from invalid filter state data

src/utils/algorithms/AdvancedFilterer.ts


23. src/components/AdvancedFilterer/TaskFilterComponent.ts 🐞 Bug fix +50/-3

Improved filter component state validation

• Removed activeBoardIndex parameter from constructor
• Added cleanup logic for invalid filter groups in initial state
• Enhanced validation when loading filter state from storage
• Prevents filter state corruption with comprehensive group validation

src/components/AdvancedFilterer/TaskFilterComponent.ts


24. src/utils/TaskItemUtils.ts 🐞 Bug fix +5/-6

Task ID extraction and documentation improvements

• Fixed JSDoc comment formatting (removed trailing spaces)
• Improved applyIdToTaskItem to properly extract and return task IDs
• Changed from checking empty string to using optional chaining for ID extraction

src/utils/TaskItemUtils.ts


25. src/components/AdvancedFilterer/TaskFilterPopover.ts ✨ Enhancement +5/-9

Refactored filter popover with simplified parameters

• Renamed class from ViewTaskFilterPopover to TaskFilterPopover
• Removed activeBoardIndex parameter from constructor and usage
• Updated import path from ViewTaskFilter to TaskFilterComponent
• Updated error logging references in bug reporter calls

src/components/AdvancedFilterer/TaskFilterPopover.ts


26. src/components/AdvancedFilterer/TaskFilterModal.ts ✨ Enhancement +4/-8

Refactored filter modal with simplified parameters

• Renamed class from ViewTaskFilterModal to TaskFilterModal
• Removed activeBoardIndex property and parameter
• Updated import path from ViewTaskFilter to TaskFilterComponent
• Updated error logging file references

src/components/AdvancedFilterer/TaskFilterModal.ts


27. src/modals/date_time_picker/DateTimePickerModal.ts ✨ Enhancement +60/-0

New DateTimePickerModal for date-time selection

• New modal wrapper for DateTimePickerComponent
• Handles date-time selection with apply/cancel callbacks
• Sets modal title dynamically based on date-time name parameter
• Properly manages component lifecycle with onload/onunload

src/modals/date_time_picker/DateTimePickerModal.ts


28. src/utils/taskNote/FrontmatterOperations.ts ✨ Enhancement +11/-7

Updated date formatting for task frontmatter

• Updated imports to include formatToday function
• Changed completion and cancelled date updates to use formatToday instead of
 getCurrentLocalDateTimeString
• Commented out moment.js based date formatting code

src/utils/taskNote/FrontmatterOperations.ts


29. src/services/tasks-plugin/helpers.ts 🐞 Bug fix +5/-6

Improved error handling for tasks plugin integration

• Fixed code formatting and line wrapping for better readability
• Changed error logging from addToLogs to showNotice with descriptive message
• Improved error handling for tasks plugin custom status imports

src/services/tasks-plugin/helpers.ts


30. src/interfaces/Enums.ts ✨ Enhancement +21/-1

Extended enums for new view types and UI options

• Updated EditButtonMode.View to ViewInSplitTab and added ViewInWindow option
• Added upcoming view types: list, table, inbox, gantt
• Added new enums: HeaderUITypeOptions and viewsPanelPropertiesToShow

src/interfaces/Enums.ts


31. src/settings/SettingSynchronizer.ts ✨ Enhancement +3/-3

Updated settings synchronizer imports and documentation

• Updated import path from BoardFilters/ViewTaskFilter to AdvancedFilterer/TaskFilterComponent
• Improved JSDoc comments for settings migration function
• Enhanced documentation for parameter descriptions

src/settings/SettingSynchronizer.ts


32. src/components/AdvancedFilterer/index.ts ✨ Enhancement +5/-5

Updated filter component exports and imports

• Renamed exports from ViewTaskFilter* to TaskFilter* classes
• Updated import paths to match new file names
• Fixed typo in comment: "safetly" to "safety"

src/components/AdvancedFilterer/index.ts


33. src/utils/taskNote/TaskNoteEventHandlers.ts ✨ Enhancement +6/-4

Updated date formatting in task note handlers

• Updated imports to include formatToday function
• Changed date value assignment to use formatToday instead of getCurrentLocalDateTimeString
• Commented out moment.js based date formatting code

src/utils/taskNote/TaskNoteEventHandlers.ts


34. src/interfaces/Constants.ts ⚙️ Configuration changes +2/-1

Version bump and new constant for mandatory scan

• Updated version from "1.9.5" to "2.0.0-beta-1"
• Added new constant MANDATORY_SCAN_KEY for mandatory scan tracking

src/interfaces/Constants.ts


35. src/modals/ConfigureColumnSortingModal.ts ✨ Enhancement +4/-10

Enabled manual order sorting by default

• Removed experimental feature flag check for manual order sorting option
• Manual order is now always available as a sorting option

src/modals/ConfigureColumnSortingModal.ts


36. src/modals/date_picker/DatePickerComponent.ts ✨ Enhancement +4/-4

Removed heading from date picker component

• Commented out the heading element creation in date picker
• Heading will be managed by parent modal instead

src/modals/date_picker/DatePickerComponent.ts


37. src/managers/BugReporter.ts Miscellaneous +1/-1

Updated maximum bug report ID tracker

• Updated MAX_USED_ID constant from 186 to 187
• Tracks the latest bug report ID used in the system

src/managers/BugReporter.ts


38. src/utils/taskLine/TaskItemEventHandlers.ts 📝 Documentation +1/-1

Fixed property name reference in comments

• Fixed comment reference from taskCompletionDateTimePattern to dateTimeFormat
• Corrected property name in commented code section

src/utils/taskLine/TaskItemEventHandlers.ts


39. src/modals/date_picker/DatePickerModal.ts ✨ Enhancement +1/-0

Added dynamic title to date picker modal

• Added setTitle call to set modal title dynamically
• Title displays "Change [dateName] Date" format

src/modals/date_picker/DatePickerModal.ts


40. src/components/TaskBoardViewContainer.tsx ✨ Enhancement +535/-371

Major refactor to view-centric board architecture

• Major refactor from board-centric to view-centric architecture
• Replaced activeBoardIndex with currentViewIndex and currentView state
• Implemented resizable views panel drawer with width persistence
• Updated filter logic to use view-specific filters instead of board filters
• Added view selection UI with properties display (description, progress)
• Removed deprecated handleViewChangeDropdownClick function
• Updated all modal and popover calls to use new view-based parameters

src/components/TaskBoardViewContainer.tsx


41. src/components/KanbanView/KanbanSwimlanesContainer.tsx ✨ Enhancement +213/-129

Updated swimlanes container for view-based architecture

• Updated to use currentViewIndex instead of currentBoardIndex
• Added kanbanViewData parameter for view-specific configuration
• Implemented swimlane-enabled column filtering
• Added support for columns excluded from swimlanes
• Changed verticalHeaderUI to headerUIType enum
• Updated swimlane minimization to persist to view data
• Enhanced column rendering with proper type annotations

src/components/KanbanView/KanbanSwimlanesContainer.tsx


42. src/components/MapView/TasksImporterPanel.tsx ✨ Enhancement +11/-7

Updated tasks importer panel for view-based architecture

• Updated props to use activeViewData and activeViewIndex instead of activeBoardIndex
• Changed import path from KanbanView/TaskItem to TaskCard/TaskItem
• Added viewTypeNames import for view type checking
• Updated task item props to use view-based parameters
• Added event emission for newly imported tasks

src/components/MapView/TasksImporterPanel.tsx


43. src/obsidian_views/AddOrEditTaskView.tsx ✨ Enhancement +2/-2

Improved task view display and ID generation

• Updated display text to include task ID with separator
• Removed isTaskNote check from auto ID generation condition
• Simplified auto ID logic to apply to all task types

src/obsidian_views/AddOrEditTaskView.tsx


44. manifest.json ⚙️ Configuration changes +1/-1

Version bump to 2.0.0-beta-1

• Updated version from "1.9.5" to "2.0.0-beta-1"
• Reflects major version release with multiple views feature

manifest.json


45. .github/copilot-instructions.md Additional files +1/-1

...

.github/copilot-instructions.md


46. data.json Additional files +21/-30

...

data.json


47. package.json Additional files +1/-1

...

package.json


48. src/components/AddOrEditTaskRC.tsx Additional files +58/-15

...

src/components/AddOrEditTaskRC.tsx


49. src/components/AdvancedFilterer/FilterConfigModal.ts Additional files +0/-0

...

src/components/AdvancedFilterer/FilterConfigModal.ts


50. src/components/KanbanView/KanbanBoardView.tsx Additional files +107/-64

...

src/components/KanbanView/KanbanBoardView.tsx


51. src/components/KanbanView/LazyColumn.tsx Additional files +105/-55

...

src/components/KanbanView/LazyColumn.tsx


52. src/components/MapView/MapView.tsx Additional files +23/-17

...

src/components/MapView/MapView.tsx


53. src/components/TaskCard/TaskItem.tsx Additional files +112/-116

...

src/components/TaskCard/TaskItem.tsx


54. src/components/TaskCard/TaskItemV2.tsx Additional files +126/-146

...

src/components/TaskCard/TaskItemV2.tsx


55. src/modals/BoardConfigModal.tsx Additional files +951/-749

...

src/modals/BoardConfigModal.tsx


56. src/modals/ScanVaultModal.tsx Additional files +16/-5

...

src/modals/ScanVaultModal.tsx


57. src/modals/SwimlanesConfigModal.tsx Additional files +341/-357

...

src/modals/SwimlanesConfigModal.tsx


58. src/obsidian_views/TaskBoardView.tsx Additional files +391/-0

...

src/obsidian_views/TaskBoardView.tsx


59. src/views/TaskBoardView.tsx Additional files +0/-278

...

src/views/TaskBoardView.tsx


60. styles.css Additional files +865/-790

...

styles.css


61. versions.json Additional files +2/-1

...

versions.json


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown
Contributor

qodo-code-review Bot commented Apr 19, 2026

Code Review by Qodo

🐞 Bugs (9) 📘 Rule violations (0) 📎 Requirement gaps (1)

Grey Divider


Action required

1. Array.contains crashes drawer 🐞 Bug ≡ Correctness ⭐ New
Description
TaskBoardViewContainer calls propertiesToShow.contains(...) even though propertiesToShow is a
string[], so opening/rendering the views drawer will throw contains is not a function. This
breaks the views drawer and can prevent the board UI from rendering correctly after the drawer is
opened.
Code

src/components/TaskBoardViewContainer.tsx[R982-985]

+											item.setChecked(boardData.viewsPanel.propertiesToShow.contains(viewsPanelPropertiesToShow.Description))
+											item.onClick(async () => {
+												if (boardData.viewsPanel.propertiesToShow.contains(viewsPanelPropertiesToShow.Description)) {
+													boardData.viewsPanel.propertiesToShow = boardData.viewsPanel.propertiesToShow.filter(prop => prop !== viewsPanelPropertiesToShow.Description);
Evidence
Board.viewsPanel.propertiesToShow is defined as string[], but the drawer code calls
.contains(...) in multiple places; JavaScript arrays do not implement contains, so this will
throw at runtime when executed.

src/interfaces/BoardConfigs.ts[188-201]
src/components/TaskBoardViewContainer.tsx[979-1005]
src/components/TaskBoardViewContainer.tsx[1041-1050]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`boardData.viewsPanel.propertiesToShow` is a `string[]`, but the code calls `.contains(...)`, which is not a valid Array method in JS/TS. This throws at runtime when the views drawer renders.

## Issue Context
This occurs in the views drawer options menu and in the conditional rendering of view description/progress.

## Fix Focus Areas
- src/components/TaskBoardViewContainer.tsx[979-1063]
- src/interfaces/BoardConfigs.ts[188-201]

## Suggested fix
- Replace all `propertiesToShow.contains(x)` with `propertiesToShow.includes(x)`.
- (Optional) Consider normalizing `propertiesToShow` to a `Set<string>` at runtime if membership checks become frequent.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. SWITCH_VIEW payload mismatch 🐞 Bug ≡ Correctness ⭐ New
Description
The SWITCH_VIEW handler now treats the event payload as a viewId and calls `getViewById(boardData,
viewId), but multiple emitters still send view type strings like 'map'/'kanban'`. This can set
currentView to undefined and break later code paths that assume currentView is non-null.
Code

src/components/TaskBoardViewContainer.tsx[R243-245]

+		const refreshView = (viewId: string) => {
+			setCurrentView(getViewById(boardData, viewId)!);
+			currentBoardData!.lastViewId = viewId;
Evidence
getViewById searches by viewId and returns undefined if not found. The SWITCH_VIEW listener
passes the event payload to getViewById, while other code emits SWITCH_VIEW with
viewTypeNames.map/string view types (not actual IDs), which will not match any viewId and can
result in currentView being set to undefined.

src/components/TaskBoardViewContainer.tsx[242-251]
src/utils/ViewUtils.ts[25-33]
src/components/TaskBoardViewContainer.tsx[802-820]
src/components/AddOrEditTaskRC.tsx[638-653]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`SWITCH_VIEW` is handled as though the payload is a `viewId`, but several emitters pass a view *type* (e.g., `'map'`, `'kanban'`). This can set `currentView` to `undefined` and cause runtime failures.

## Issue Context
- Listener: `setCurrentView(getViewById(boardData, viewId)!)`
- Emitters: `eventEmitter.emit('SWITCH_VIEW', viewTypeNames.map)` and similar

## Fix Focus Areas
- src/components/TaskBoardViewContainer.tsx[242-251]
- src/components/TaskBoardViewContainer.tsx[802-820]
- src/components/AddOrEditTaskRC.tsx[638-653]
- src/utils/ViewUtils.ts[25-46]

## Suggested fix
Choose one of these and apply consistently:
1) **ID-based switching**: emit `view.viewId` everywhere, and update menus/actions to look up the correct viewId to emit.
2) **Type-based switching**: rename the event to `SWITCH_VIEW_TYPE` and update the handler to resolve a view by type (e.g., via `getViewByType`) and then set both `currentViewIndex` and `currentView`.

Also add a guard in the handler:
- If the view cannot be resolved, do not update state; optionally log/report via bugReporter.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Empty registry dereference 🐞 Bug ☼ Reliability ⭐ New
Description
TaskBoardFileManager.getLastOpenedBoard assumes there is at least one registry entry and
dereferences firstItemFromRegistry.filePath without checking firstItemFromRegistry exists. If
the registry is empty (fresh install or after registry cleanup), this will throw and prevent
TaskBoardView from loading.
Code

src/managers/TaskBoardFileManager.ts[R686-689]

		const firstItemFromRegistry = Object.values(taskBoardFilesRegistry)[0];

-		if (!firstItemFromRegistry?.filePath) {
+		if (!firstItemFromRegistry.filePath) {
			console.error(
Evidence
TaskBoardView calls getLastOpenedBoard() when no filePath is available. getLastOpenedBoard()
reads Object.values(taskBoardFilesRegistry)[0] and then immediately accesses .filePath even when
the registry is empty, producing a TypeError.

src/obsidian_views/TaskBoardView.tsx[157-182]
src/managers/TaskBoardFileManager.ts[671-693]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`getLastOpenedBoard()` can throw when `taskBoardFilesRegistry` is empty because it dereferences `firstItemFromRegistry.filePath` without checking `firstItemFromRegistry`.

## Issue Context
This path is hit from `TaskBoardView.setState()` when there is no `filePath` in the view state.

## Fix Focus Areas
- src/managers/TaskBoardFileManager.ts[671-713]
- src/obsidian_views/TaskBoardView.tsx[157-203]

## Suggested fix
- Add an early return:
 - If `Object.keys(taskBoardFilesRegistry).length === 0`, return `undefined`.
 - Or check `if (!firstItemFromRegistry || !firstItemFromRegistry.filePath)` before accessing `filePath`.
- Keep the error log, but avoid throwing and let `TaskBoardView` fall back to `renderNoBoard()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (4)
4. Single Board per .taskboard 📎 Requirement gap ≡ Correctness
Description
The new .taskboard persistence layer reads/writes a single Board object per file, rather than
supporting multiple independently selectable views inside one .taskboard file. This fails the
requirement to create and switch between at least two distinct views within the same .taskboard
file.
Code

src/managers/TaskBoardFileManager.ts[R269-305]

+	async saveBoardToDisk(
+		filePath: string,
+		boardData: Board,
+	): Promise<boolean> {
+		try {
+			// Check if file exists, if not create it
+			const fileExists = await this.app.vault.adapter.exists(filePath);
+
+			// Convert board data to JSON string, then to Uint8Array for binary storage
+			const jsonString = JSON.stringify(boardData);
+			const uint8Array = new TextEncoder().encode(jsonString);
+			const arrayBuffer = uint8Array.buffer.slice(
+				uint8Array.byteOffset,
+				uint8Array.byteOffset + uint8Array.byteLength,
+			);
+
+			if (!fileExists) {
+				// Create new file with binary data
+				await this.app.vault.createBinary(
+					filePath,
+					arrayBuffer as ArrayBuffer,
+				);
+				console.log(`Created new TaskBoard file: ${filePath}`);
+			} else {
+				// Update existing file with binary data
+				const file = this.app.vault.getAbstractFileByPath(filePath);
+				if (!file || !(file instanceof TFile)) {
+					console.error(`Cannot find file to update: ${filePath}`);
+					return false;
+				}
+				await this.app.vault.modifyBinary(
+					file,
+					arrayBuffer as ArrayBuffer,
+				);
+				console.log(`Updated TaskBoard file: ${filePath}`);
+			}
+
Evidence
PR Compliance ID 1 requires multiple views to coexist and be selectable within a single .taskboard
file. The PR code explicitly parses the entire file into a single Board and serializes a single
Board back to disk, which structurally enforces 1 view per .taskboard file.

Support multiple views within a single .taskboard file
src/managers/TaskBoardFileManager.ts[50-76]
src/managers/TaskBoardFileManager.ts[269-309]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `.taskboard` file load/save logic currently treats each `.taskboard` file as a single `Board` JSON payload, which prevents supporting multiple independently selectable views inside a single `.taskboard` file.
## Issue Context
Compliance requires that a user can create at least two distinct views within the same `.taskboard` file and switch between them via a selector, without creating separate board/files.
## Fix Focus Areas
- src/managers/TaskBoardFileManager.ts[50-99]
- src/managers/TaskBoardFileManager.ts[263-311]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Delete queue never reschedules 🐞 Bug ≡ Correctness
Description
deleteProcessingTimer is set once and never reset, but new logic only schedules delete processing
when the timer is null. After the first delete batch, subsequent delete events may never be
processed, leaving stale cache entries for deleted files.
Code

main.ts[R821-828]

+			if (!this.deleteProcessingTimer) {
+				this.deleteProcessingTimer = setTimeout(() => {
+					this.processDeleteQueue();
+				}, this.QUEUE_DELAY);
+			} else {
+				// NOTE : I think there is no need to remove the Timout created, in 2 seconds, all the Obsidians triggers should finish, for the Task Board's processing to start.
+				// clearTimeout(this.deleteProcessingTimer);
  		}
-
-			this.deleteProcessingTimer = setTimeout(() => {
-				this.processDeleteQueue();
-			}, this.QUEUE_DELAY);
Evidence
The queue scheduling now only sets a timeout when deleteProcessingTimer is falsy, but
processDeleteQueue never clears/resets the timer (or empties deleteQueue), so future delete events
will not schedule processing.

main.ts[815-829]
main.ts[835-894]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`queueFileForDeletion` now only schedules `processDeleteQueue()` when `deleteProcessingTimer` is null, but `deleteProcessingTimer` is never reset to null after processing. This can permanently disable delete processing after the first run.
### Issue Context
This breaks correctness of the tasks cache because deleted files may remain in cache indefinitely.
### Fix Focus Areas
- main.ts[815-894]
### Suggested approach
- In `processDeleteQueue()`:
- Snapshot and clear the queue at the start (e.g., `const queued = this.deleteQueue; this.deleteQueue = [];`).
- Wrap processing in `try/finally` and in `finally` clear the timeout handle and set `this.deleteProcessingTimer = null`.
- In `queueFileForDeletion()`:
- Prefer the previous behavior: `clearTimeout(this.deleteProcessingTimer)` (when set) and always set a new timeout, OR keep the “only schedule once” approach but ensure the timer gets reset to `null` after processing completes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Startup crash on JSON.parse 🐞 Bug ≡ Correctness
Description
TaskBoardFileManager constructor unconditionally JSON.parse()s the localStorage value for
LEAFID_FILEPATH_MAPPING_KEY. On fresh installs or cleared storage this can be null/empty and will
throw, preventing plugin load.
Code

src/managers/TaskBoardFileManager.ts[R35-38]

+		const mappingData: leafIdFilePathMapType = JSON.parse(
+			this.app.loadLocalStorage(LEAFID_FILEPATH_MAPPING_KEY),
+		);
+		this.leafIdFilePathMapping = mappingData;
Evidence
app.loadLocalStorage(...) is used without any fallback or try/catch around JSON.parse in the
constructor, so malformed/missing data crashes initialization before any recovery logic can run.

src/managers/TaskBoardFileManager.ts[31-39]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`JSON.parse(this.app.loadLocalStorage(...))` can throw when the storage key is missing or corrupted, crashing plugin startup.
### Issue Context
This is especially likely on fresh installs or when users clear Obsidian/plugin local storage.
### Fix Focus Areas
- src/managers/TaskBoardFileManager.ts[31-39]
### Suggested approach
- Replace with safe parsing:
- `const raw = this.app.loadLocalStorage(KEY);`
- `const mappingData = raw ? JSON.parse(raw) : {};`
- Wrap parse in try/catch and fall back to `{}` on error.
- Optionally, if parse fails, overwrite the stored value with a known-good `{}` to self-heal.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Migrations lose old settings 🐞 Bug ≡ Correctness
Description
The settings schema was flattened (PluginDataJson.data is now globalSettingsData), but
migrateSettings only adds missing keys and never maps values from the previous nested structure
(e.g., data.globalSettings.*). Upgrading users can silently lose their configured settings/behavior.
Code

src/settings/SettingSynchronizer.ts[R23-31]

export function migrateSettings(defaults: any, settings: any): PluginDataJson {
-	for (const key in defaults) {
-		if (!(key in settings)) {
-			// This is a cumpulsory migration which will be required in every new version update, since a new field should be added into the users settings.
-			settings[key] = defaults[key];
-		} else if (
-			!Array.isArray(settings[key]) &&
-			key === "tagColors" &&
-			typeof settings[key] === "object" &&
-			settings[key] !== null
-		) {
-			// This is a temporary migration applied since version 1.2.0. Can be removed, after around 6 months.
-			settings[key] = Object.entries(
-				settings[key] as Record<string, string>
-			).map(
-				([name, color], idx) =>
-					({
-						name,
-						color,
-						priority: idx + 1,
-					} as any)
-			);
-		} else if (key === "boardConfigs" && Array.isArray(settings[key])) {
-			// This is a temporary solution to sync the boardConfigs. Will need to replace the range object with the new 'datedBasedColumn', which will have three values 'dateType', 'from' and 'to'. So, basically I want to copy `range.rangedata.from` value to `datedBasedColumn.from` and similarly for `range.rangedatato`. And for `datedBasedColumn.dateType`, put the value this.settings.data.globalSettings.universalDate
-			// This migration was applied since version 1.5.0.
-			settings[key].forEach((boardConfig: Board) => {
-				boardConfig.columns.forEach((column: ColumnData) => {
-					if (!column.id) {
-						column.id = Math.floor(Math.random() * 1000000);
-					}
-					if (
-						column.colType === colTypeNames.dated ||
-						(column.colType === colTypeNames.undated &&
-							!column.datedBasedColumn)
-					) {
-						column.datedBasedColumn = {
-							dateType:
-								column.datedBasedColumn?.dateType ??
-								defaults.universalDate,
-							from: column.datedBasedColumn?.from || 0,
-							to: column.datedBasedColumn?.to || 0,
-						};
-						delete column.range;
-					}
-				});
+	try {
+		if (settings == undefined) return defaults;

-				// Migration applied since version 1.4.0
-				if (!boardConfig.hideEmptyColumns) {
-					boardConfig.hideEmptyColumns = false;
-				}
+		for (const key in defaults) {
+			if (!(key in settings)) {
+				// This is a cumpulsory migration which will be required in every new version update, since a new field should be added into the users settings.
+				settings[key] = defaults[key];
+			}
Evidence
The new schema expects flattened fields under settings.data, and runtime code reads them directly.
The migration function only fills missing keys and recurses, but has no transformation step that
would copy user values from an older nested shape into the flattened fields; additionally,
loadSettings shallowly merges and saves immediately.

src/interfaces/GlobalSettings.ts[158-162]
main.ts[273-281]
main.ts[619-623]
src/settings/SettingSynchronizer.ts[23-31]
src/settings/SettingSynchronizer.ts[141-147]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Runtime code now reads settings from `settings.data.&lt;field&gt;` (flattened), but migration only adds missing keys. If an existing user’s stored data uses an older nested shape (e.g., `settings.data.globalSettings.&lt;field&gt;`), their values won’t be used and will effectively reset to defaults.
### Issue Context
This PR introduces a major schema change: boards are moving out of settings into `.taskboard` files and global settings are flattened.
### Fix Focus Areas
- src/settings/SettingSynchronizer.ts[23-160]
- main.ts[273-281]
- src/interfaces/GlobalSettings.ts[158-162]
### Suggested approach
1. In `migrateSettings` (or a dedicated `migrateTo2xSchema` called from `runOnPluginUpdate`):
 - Detect old schema shapes, e.g.:
   - `settings.data?.globalSettings` exists
   - `settings.data?.boardConfigs` exists
 - If present:
   - Create `settings.data = { ...DEFAULT_SETTINGS.data, ...settings.data.globalSettings }`
   - Remove `globalSettings` key after copying.
2. Board migration:
 - For each board in old `boardConfigs`, create a corresponding `.taskboard` file (or reuse existing) and build `taskBoardFilesRegistry`.
 - Ensure migration is idempotent and doesn’t overwrite existing board files unexpectedly.
3. Only call `saveSettings()` after successful transformation, and consider adding a one-time backup export before destructive migrations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

8. Unawaited migration save 🐞 Bug ☼ Reliability ⭐ New
Description
applyMigrationIfNeeded calls async saveBoard(boardData) without awaiting or catching the Promise,
so save failures can become unhandled rejections and migrations may not persist reliably. The method
returns migrated data even if the save later fails.
Code

src/managers/TaskBoardFileManager.ts[R807-812]

+			// After applying necessary migrations, update the pluginVersion in the board data
+			boardData.pluginVersion = this.currentPluginVersion;
+
+			this.saveBoard(boardData);
+
+			return boardData;
Evidence
saveBoard is an async method returning Promise<boolean>, but applyMigrationIfNeeded is
synchronous and invokes this.saveBoard(boardData); without await/.catch(...), which can lead
to unhandled promise rejections and non-deterministic persistence behavior.

src/managers/TaskBoardFileManager.ts[790-816]
src/managers/TaskBoardFileManager.ts[289-305]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`applyMigrationIfNeeded()` triggers a background `saveBoard()` without awaiting/handling the promise. This can cause unhandled promise rejections and makes persistence of migrated data unreliable.

## Issue Context
Migrations run during board load; persistence should be deterministic and errors should be surfaced (log/notice).

## Fix Focus Areas
- src/managers/TaskBoardFileManager.ts[790-816]
- src/managers/TaskBoardFileManager.ts[289-340]

## Suggested fix
Option A (preferred):
- Make `applyMigrationIfNeeded` `async` and `await this.saveBoard(boardData)`.
- Update call sites (e.g., `loadBoardFromDisk`) to await it.

Option B:
- Keep it sync but explicitly handle the promise:
 - `void this.saveBoard(boardData).catch(err => console.error(...))`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. NaN progress width 🐞 Bug ≡ Correctness ⭐ New
Description
The views drawer progress bar width divides by (pending + completed) which is 0 for new views,
producing NaN% CSS widths. This causes incorrect/undefined progress bar rendering for newly
created views.
Code

src/components/TaskBoardViewContainer.tsx[R1053-1055]

+														style={{
+															width: `${((view.taskCount.completed) / (view.taskCount.pending + view.taskCount.completed)) * 100}%`,
+														}}
Evidence
New views initialize taskCount to { pending: 0, completed: 0 }. The progress bar computes
completed / (pending + completed) so the denominator can be 0, yielding NaN and invalid CSS width.

src/components/TaskBoardViewContainer.tsx[1048-1056]
src/utils/ViewUtils.ts[70-86]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Progress width is computed with a denominator that can be 0, producing `NaN%`.

## Issue Context
Newly created views start with pending=0 and completed=0.

## Fix Focus Areas
- src/components/TaskBoardViewContainer.tsx[1048-1061]
- src/utils/ViewUtils.ts[70-86]

## Suggested fix
- Compute `total = pending + completed` and set width to `0` when `total === 0`:
 - `const pct = total === 0 ? 0 : (completed / total) * 100;`

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Board ID conflict not persisted 🐞 Bug ≡ Correctness
Description
When a .taskboard file’s board ID collides with an existing registry entry at a different path, the
code generates a new ID in-memory but does not persist it back to the file. Reopening the same file
can repeatedly generate new IDs and keep adding registry entries, destabilizing board identity.
Code

src/managers/TaskBoardFileManager.ts[R71-92]

+			// Check if board with this ID already exists in registry
+			const taskBoardFilesRegistry =
+				this.plugin.settings.data.taskBoardFilesRegistry || {};
+			const existingRegistryEntry = Object.entries(
+				taskBoardFilesRegistry,
+			).find(([, entry]) => entry.boardId === boardData.id);
+
+			if (existingRegistryEntry) {
+				const [, registryEntry] = existingRegistryEntry;
+				if (registryEntry.filePath === filePath) {
+					// Same boardID and same filePath - no action needed
+					console.log(
+						`Board "${boardData.name}" with ID "${boardData.id}" already registered at: ${filePath}`,
+					);
+				} else {
+					// Same boardID but different filePath - generate new ID
+					const oldId = boardData.id;
+					boardData.id = generateRandomTempTaskId();
+					console.log(
+						`Board ID conflict detected. Changed board ID from "${oldId}" to "${boardData.id}" for file: ${filePath}`,
+					);
+				}
Evidence
On conflict, boardData.id is changed but the function returns without writing the updated ID to
disk. loadBoardUsingPath then registers the (new) in-memory ID in settings; on next open, the file
still contains the old ID, so the conflict repeats.

src/managers/TaskBoardFileManager.ts[71-95]
src/managers/TaskBoardFileManager.ts[187-199]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Board ID conflicts are resolved by mutating `boardData.id` only in memory. Because the file still contains the old ID, the same conflict will recur on every load, potentially creating many registry entries for the same underlying file.
### Issue Context
This can happen when users duplicate/copy `.taskboard` files or sync across devices.
### Fix Focus Areas
- src/managers/TaskBoardFileManager.ts[55-99]
- src/managers/TaskBoardFileManager.ts[172-205]
### Suggested approach
- When a conflict is detected and you generate a new ID:
1. Immediately write the updated board JSON back to `filePath` (e.g., call an internal `saveBoardToDisk(filePath, boardData)`), so subsequent loads see the new ID.
2. Ensure registry updates are awaited (consider `await this.addNewBoardToRegistry(...)`) to keep ordering consistent.
- Consider a safer strategy:
- Treat file path as the primary key and store `boardId` as metadata, or generate ID deterministically from file path to prevent repeated conflicts.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +982 to +985
item.setChecked(boardData.viewsPanel.propertiesToShow.contains(viewsPanelPropertiesToShow.Description))
item.onClick(async () => {
if (boardData.viewsPanel.propertiesToShow.contains(viewsPanelPropertiesToShow.Description)) {
boardData.viewsPanel.propertiesToShow = boardData.viewsPanel.propertiesToShow.filter(prop => prop !== viewsPanelPropertiesToShow.Description);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Array.contains crashes drawer 🐞 Bug ≡ Correctness

TaskBoardViewContainer calls propertiesToShow.contains(...) even though propertiesToShow is a
string[], so opening/rendering the views drawer will throw contains is not a function. This
breaks the views drawer and can prevent the board UI from rendering correctly after the drawer is
opened.
Agent Prompt
## Issue description
`boardData.viewsPanel.propertiesToShow` is a `string[]`, but the code calls `.contains(...)`, which is not a valid Array method in JS/TS. This throws at runtime when the views drawer renders.

## Issue Context
This occurs in the views drawer options menu and in the conditional rendering of view description/progress.

## Fix Focus Areas
- src/components/TaskBoardViewContainer.tsx[979-1063]
- src/interfaces/BoardConfigs.ts[188-201]

## Suggested fix
- Replace all `propertiesToShow.contains(x)` with `propertiesToShow.includes(x)`.
- (Optional) Consider normalizing `propertiesToShow` to a `Set<string>` at runtime if membership checks become frequent.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +243 to +245
const refreshView = (viewId: string) => {
setCurrentView(getViewById(boardData, viewId)!);
currentBoardData!.lastViewId = viewId;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Switch_view payload mismatch 🐞 Bug ≡ Correctness

The SWITCH_VIEW handler now treats the event payload as a viewId and calls `getViewById(boardData,
viewId), but multiple emitters still send view type strings like 'map'/'kanban'`. This can set
currentView to undefined and break later code paths that assume currentView is non-null.
Agent Prompt
## Issue description
`SWITCH_VIEW` is handled as though the payload is a `viewId`, but several emitters pass a view *type* (e.g., `'map'`, `'kanban'`). This can set `currentView` to `undefined` and cause runtime failures.

## Issue Context
- Listener: `setCurrentView(getViewById(boardData, viewId)!)`
- Emitters: `eventEmitter.emit('SWITCH_VIEW', viewTypeNames.map)` and similar

## Fix Focus Areas
- src/components/TaskBoardViewContainer.tsx[242-251]
- src/components/TaskBoardViewContainer.tsx[802-820]
- src/components/AddOrEditTaskRC.tsx[638-653]
- src/utils/ViewUtils.ts[25-46]

## Suggested fix
Choose one of these and apply consistently:
1) **ID-based switching**: emit `view.viewId` everywhere, and update menus/actions to look up the correct viewId to emit.
2) **Type-based switching**: rename the event to `SWITCH_VIEW_TYPE` and update the handler to resolve a view by type (e.g., via `getViewByType`) and then set both `currentViewIndex` and `currentView`.

Also add a guard in the handler:
- If the view cannot be resolved, do not update state; optionally log/report via bugReporter.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 686 to 689
const firstItemFromRegistry = Object.values(taskBoardFilesRegistry)[0];

if (!firstItemFromRegistry?.filePath) {
if (!firstItemFromRegistry.filePath) {
console.error(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Empty registry dereference 🐞 Bug ☼ Reliability

TaskBoardFileManager.getLastOpenedBoard assumes there is at least one registry entry and
dereferences firstItemFromRegistry.filePath without checking firstItemFromRegistry exists. If
the registry is empty (fresh install or after registry cleanup), this will throw and prevent
TaskBoardView from loading.
Agent Prompt
## Issue description
`getLastOpenedBoard()` can throw when `taskBoardFilesRegistry` is empty because it dereferences `firstItemFromRegistry.filePath` without checking `firstItemFromRegistry`.

## Issue Context
This path is hit from `TaskBoardView.setState()` when there is no `filePath` in the view state.

## Fix Focus Areas
- src/managers/TaskBoardFileManager.ts[671-713]
- src/obsidian_views/TaskBoardView.tsx[157-203]

## Suggested fix
- Add an early return:
  - If `Object.keys(taskBoardFilesRegistry).length === 0`, return `undefined`.
  - Or check `if (!firstItemFromRegistry || !firstItemFromRegistry.filePath)` before accessing `filePath`.
- Keep the error log, but avoid throwing and let `TaskBoardView` fall back to `renderNoBoard()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@tu2-atmanand tu2-atmanand mentioned this pull request Apr 20, 2026
9 tasks
@tu2-atmanand tu2-atmanand added this to the 2.0.0 milestone May 1, 2026
@tu2-atmanand tu2-atmanand removed the brainstorm These issue/feat needs to be discussed and have to find the solution label May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement An existing feature can be enhanced/improved. feature New feature request optimization The algorithm/code can be optimized. A better approach

Projects

Status: Ready to Review

Development

Successfully merging this pull request may close these issues.

1 participant