From fb1750fc0df6033d726bcd8cdafef6c1c61059d6 Mon Sep 17 00:00:00 2001 From: Zero Liu Date: Thu, 1 Jan 2026 21:39:20 -0800 Subject: [PATCH] Add settings --- docs/projects-plus-phase6-development.md | 559 ++++++++++++++++++ src/components/projects-plus/ProjectCard.tsx | 49 +- .../projects-plus/ProjectDetail.tsx | 14 +- .../projects-plus/ProjectStatusBadge.tsx | 26 + src/constants.ts | 1 - src/main.ts | 10 +- src/settings/model.ts | 7 - .../v2/components/CopilotPlusSettings.tsx | 3 + .../v2/components/ProjectsPlusSettings.tsx | 30 + 9 files changed, 627 insertions(+), 72 deletions(-) create mode 100644 docs/projects-plus-phase6-development.md create mode 100644 src/components/projects-plus/ProjectStatusBadge.tsx create mode 100644 src/settings/v2/components/ProjectsPlusSettings.tsx diff --git a/docs/projects-plus-phase6-development.md b/docs/projects-plus-phase6-development.md new file mode 100644 index 00000000..543c9e6d --- /dev/null +++ b/docs/projects-plus-phase6-development.md @@ -0,0 +1,559 @@ +# Projects+ Phase 6: Goal Completion & Settings - Development Document + +## Overview + +Phase 6 completes the Projects+ MVP by implementing goal completion workflows with reflection, archived goal views, and a dedicated settings tab. This document provides detailed implementation guidance, edge cases, and UI specifications. + +--- + +## Table of Contents + +1. [Goal Completion Flow](#1-goal-completion-flow) +2. [Archived Goals View](#2-archived-goals-view) +3. [Projects+ Settings Tab](#3-projects-settings-tab) +4. [Implementation Details](#4-implementation-details) +5. [Edge Cases & Error Handling](#5-edge-cases--error-handling) +6. [Testing Checklist](#6-testing-checklist) + +--- + +## 1. Goal Completion Flow + +### 1.1 Triggering the Completion Modal + +The completion modal can be triggered from multiple locations: + +#### Entry Points + +| Location | UI Element | Action | +| ---------------------------- | --------------------------- | ---------------------------------------------------- | +| **ProjectDetail Footer** | "Complete" button (primary) | Opens `ProjectStatusDialog` with `action="complete"` | +| **ProjectCard Context Menu** | "Complete" menu item | Opens `ProjectStatusDialog` with `action="complete"` | +| **ProjectCard Quick Action** | Checkmark icon button | Opens `ProjectStatusDialog` with `action="complete"` | + +#### Current Implementation + +The completion flow is already wired in `ProjectDetail.tsx`: + +```typescript +// ProjectDetail.tsx:430-431 + +``` + +This triggers `handleStatusAction("complete")` which opens `ProjectStatusDialog`: + +```typescript +// ProjectDetail.tsx:135-138 +const handleStatusAction = useCallback((action: StatusAction) => { + setStatusAction(action); + setStatusDialogOpen(true); +}, []); +``` + +### 1.2 Completion Modal UI Specification + +The `ProjectStatusDialog` renders different content based on the action type. For completion: + +``` +┌─────────────────────────────────────────────────────────┐ +│ Complete Project [X] │ +├─────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ You've been working on this project for **5 days** │ │ +│ │ with **12 notes** and **3 conversations**. │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ Reflection (optional) │ +│ ┌─────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ What did you learn or accomplish? │ │ +│ │ │ │ +│ │ │ │ +│ └─────────────────────────────────────────────────────┘ │ +│ │ +│ [Cancel] [Complete Project] │ +└─────────────────────────────────────────────────────────┘ +``` + +#### Journey Summary Component + +The journey summary uses `calculateJourneySummary()` from `utils.ts`: + +```typescript +// utils.ts +export function calculateJourneySummary(project: Project) { + const now = Date.now(); + const daysActive = Math.ceil((now - project.createdAt) / (1000 * 60 * 60 * 24)); + + return { + daysActive, + notesCount: project.notes.length, + conversationsCount: project.conversations.length, + }; +} +``` + +### 1.3 Completion Confirmation Handler + +```typescript +// ProjectDetail.tsx:140-155 +const handleConfirmStatus = useCallback( + async (reflection?: string) => { + switch (statusAction) { + case "complete": + await plugin.projectsPlusManager.completeProject(projectId, reflection); + break; + case "archive": + await plugin.projectsPlusManager.archiveProject(projectId); + break; + case "reactivate": + await plugin.projectsPlusManager.reactivateProject(projectId); + break; + } + }, + [plugin.projectsPlusManager, projectId, statusAction] +); +``` + +### 1.4 Project Status Transitions + +``` + ┌──────────────┐ + │ active │ + └──────────────┘ + │ + ┌─────────┴─────────┐ + ▼ ▼ +┌──────────────┐ ┌──────────────┐ +│ completed │ │ archived │ +└──────────────┘ └──────────────┘ + │ │ + └─────────┬─────────┘ + ▼ + ┌──────────────┐ + │ active │ (reactivate) + └──────────────┘ +``` + +--- + +## 2. Archived Goals View + +### 2.1 Goal List Filtering Behavior + +**Design Decision:** Completed goals are NOT shown in the main list by default. Users must use the status filter dropdown to view them. + +The `ProjectsPanel` already implements this via a status filter: + +```typescript +// ProjectsPanel.tsx:167-176 + +``` + +### 2.2 Default Filter Behavior + +The default filter is `"all"` which shows all projects. However, projects are sorted by `updatedAt` descending, so active projects with recent activity appear first. + +**Implementation Note:** There is no separate setting for "show completed in list" - the filter dropdown provides this functionality directly. + +### 2.3 Completed/Archived Project Detail View + +When viewing a completed or archived project, the UI should reflect the read-only nature: + +#### Visual Indicators + +1. **Status Badge** - Shows "Completed" or "Archived" with appropriate styling +2. **Reflection Section** - Displays the reflection text (if provided) +3. **Disabled Actions** - "Add Notes", "Suggest Notes" buttons hidden for non-active projects + +Current implementation in `ProjectDetail.tsx`: + +```typescript +// Notes section actions - only shown for active projects +{project.status === "active" && ( +
+ + +
+)} +``` + +#### Footer Actions by Status + +| Status | Available Actions | +| ----------- | ------------------------- | +| `active` | Edit, Archive, Complete | +| `completed` | Edit, Archive, Reactivate | +| `archived` | Edit, Reactivate | + +### 2.4 ProjectStatusBadge Component + +Create a reusable badge component for consistent status display: + +```typescript +// src/components/projects-plus/ProjectStatusBadge.tsx +interface ProjectStatusBadgeProps { + status: ProjectStatus; + className?: string; +} + +export function ProjectStatusBadge({ status, className }: ProjectStatusBadgeProps) { + return ( + + {status} + + ); +} +``` + +The `getStatusBadgeStyles` function from `utils.ts`: + +```typescript +export function getStatusBadgeStyles(status: ProjectStatus): string { + switch (status) { + case "active": + return "tw-bg-modifier-success-rgb/20 tw-text-success"; + case "completed": + return "tw-bg-blue-rgb/20 tw-text-context-manager-blue"; + case "archived": + return "tw-bg-modifier-hover tw-text-muted"; + default: + return ""; + } +} +``` + +--- + +## 3. Projects+ Settings Tab + +### 3.1 Settings Tab Location + +Add a new tab to `SettingsMainV2.tsx` OR integrate into an existing tab. + +**Recommended Approach:** Integrate into the existing settings structure rather than adding a new tab. Projects+ settings should be part of the "Plus" or "Advanced" tab since Projects+ is a premium feature. + +### 3.2 Settings Interface + +Based on the design decisions: + +```typescript +// Settings that will be added to CopilotSettings +interface ProjectsPlusSettings { + /** Folder path for Projects+ data */ + projectsPlusFolder: string; // Already exists, default: "copilot/projects" + + // REMOVED SETTINGS: + // projectsPlusEnabled: boolean; - REMOVED (feature always enabled) + // autoSaveEnabled: boolean; - REMOVED (always enabled) + // defaultDiscussModel: string; - REMOVED (uses main model) + // showCompletedInList: boolean; - REMOVED (use filter dropdown instead) + // noteSuggestionCount: number; - REMOVED (handled by search system) + // excludedFolders: string[]; - REMOVED (follows main qaExclusions setting) +} +``` + +### 3.3 Settings Tab UI Design + +Since most settings have been consolidated, the Projects+ settings section is minimal: + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Projects+ │ +├─────────────────────────────────────────────────────────────────┤ +│ │ +│ Projects Folder │ +│ Folder where project data is stored. │ +│ ┌─────────────────────────────────────────────────────────────┐│ +│ │ copilot/projects ││ +│ └─────────────────────────────────────────────────────────────┘│ +│ │ +│ ───────────────────────────────────────────────────────────── │ +│ │ +│ ℹ️ Note: Projects+ uses the same inclusion/exclusion │ +│ settings as QA Mode for note suggestions. │ +│ Configure them in the "QA" settings tab. │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 3.4 ProjectsPlusSettings Component Implementation + +```typescript +// src/settings/v2/components/ProjectsPlusSettings.tsx + +import { SettingItem } from "@/components/ui/setting-item"; +import { updateSetting, useSettingsValue } from "@/settings/model"; +import React from "react"; + +export const ProjectsPlusSettings: React.FC = () => { + const settings = useSettingsValue(); + + return ( +
+
+
Projects+
+
+ {/* Projects Folder */} + updateSetting("projectsPlusFolder", value)} + placeholder="copilot/projects" + /> + + {/* Info about shared settings */} +
+

+ Note: Projects+ uses the same inclusion/exclusion settings as QA Mode + for note suggestions. Configure them in the QA settings tab. +

+
+
+
+
+ ); +}; +``` + +### 3.5 Integrating into Settings + +**Option A: Add to CopilotPlusSettings.tsx** + +Since Projects+ is a Plus feature, add it to the existing Plus settings tab: + +```typescript +// In CopilotPlusSettings.tsx, add: +import { ProjectsPlusSettings } from "./ProjectsPlusSettings"; + +// In the component render: + +``` + +**Option B: Add to AdvancedSettings.tsx** + +Alternatively, add to Advanced settings as a separate section. + +### 3.6 Note Suggestion Configuration + +**Key Design Decision:** Note suggestions follow the main QA inclusion/exclusion settings. + +The `NoteAssignmentService` should use `qaExclusions` and `qaInclusions` from the main settings: + +```typescript +// In NoteAssignmentService.ts +import { getSettings } from "@/settings/model"; + +class NoteAssignmentService { + async suggestNotes(projectDescription: string, options?: NoteAssignmentOptions) { + const settings = getSettings(); + + // Apply the same exclusions as QA mode + const exclusions = settings.qaExclusions; + const inclusions = settings.qaInclusions; + + // ... use these for filtering note suggestions + } +} +``` + +--- + +## 4. Implementation Details + +### 4.1 Naming Convention Update + +**Important:** The original design document (`projects-plus-technical-design.md`) uses "Goal" terminology (e.g., `GoalStatusBadge.tsx`, `GoalCompletion.tsx`). However, the actual implementation uses "Project" terminology throughout. This phase should continue using "Project" naming: + +| Original Design Name | Actual Implementation Name | +| --------------------- | ----------------------------------------------------- | +| `GoalStatusBadge.tsx` | `ProjectStatusBadge.tsx` | +| `GoalCompletion.tsx` | `ProjectStatusDialog.tsx` (already exists) | +| `ArchivedGoals.tsx` | Not needed (handled by filter in `ProjectsPanel.tsx`) | + +### 4.2 Files to Create + +| File | Purpose | +| ----------------------------------------------------- | ------------------------------- | +| `src/settings/v2/components/ProjectsPlusSettings.tsx` | Settings tab component | +| `src/components/projects-plus/ProjectStatusBadge.tsx` | Reusable status badge component | + +### 4.3 Files to Modify + +| File | Changes | +| ---------------------------------------------------- | ------------------------------------------------------------- | +| `src/settings/model.ts` | Remove `projectsPlusEnabled` from `CopilotSettings` interface | +| `src/constants.ts` | Remove `projectsPlusEnabled` from `DEFAULT_SETTINGS` | +| `src/main.ts` | Remove any conditional checks for `projectsPlusEnabled` | +| `src/settings/v2/components/CopilotPlusSettings.tsx` | Import and render `ProjectsPlusSettings` | +| `src/core/projects-plus/NoteAssignmentService.ts` | Use `qaExclusions`/`qaInclusions` for filtering | +| `src/components/projects-plus/ProjectDetail.tsx` | Replace inline badge with `ProjectStatusBadge` component | +| `src/components/projects-plus/ProjectCard.tsx` | Replace inline badge with `ProjectStatusBadge` component | + +### 4.4 Conversation Auto-Save Behavior + +Conversations are auto-saved per message exchange. This is NOT configurable - it's always enabled. + +The save happens in `ConversationPersistence.ts`: + +```typescript +// After each message exchange: +await conversationPersistence.saveConversation(project, conversation); +``` + +### 4.5 Model Configuration for Discuss + +The Discuss feature uses the default chat model (`defaultModelKey`) rather than a separate model setting. This simplifies configuration and ensures consistency. + +--- + +## 5. Edge Cases & Error Handling + +### 5.1 Completion Edge Cases + +| Scenario | Handling | +| ---------------------------------- | ------------------------------------------------------------ | +| **Empty reflection** | Allow completion - reflection is optional | +| **Very long reflection** | No limit, but consider adding a soft warning for >1000 chars | +| **Completion fails** | Show error notice, keep dialog open | +| **Project already completed** | Button should not be visible; if API called, return silently | +| **Concurrent completion attempts** | Use loading state to prevent double-submission | + +### 5.2 Settings Edge Cases + +| Scenario | Handling | +| -------------------------------------- | -------------------------------------------------------- | +| **Invalid folder path** | Validate path, show error if contains illegal characters | +| **Folder doesn't exist** | Create folder on first project creation, not on save | +| **Empty folder path** | Fall back to default `copilot/projects` | +| **Path with leading/trailing slashes** | Normalize path on save | + +### 5.3 Filter Edge Cases + +| Scenario | Handling | +| --------------------------------------------- | ----------------------------------------------------------- | +| **Filter shows no results** | Show empty state with helpful message | +| **Search + filter combination** | Apply both filters, show combined empty state if no results | +| **Project status changes while viewing list** | Reactive update via subscription | + +### 5.4 Archived Goal View Edge Cases + +| Scenario | Handling | +| -------------------------------------------- | -------------------------------------------------- | +| **Viewing archived goal with deleted notes** | Show warning icon next to missing notes | +| **Attempting to discuss archived goal** | "Discuss" button hidden for archived status | +| **Reactivating a goal** | Status changes to "active", all actions re-enabled | + +--- + +## 6. Testing Checklist + +### 6.1 Goal Completion Flow + +- [ ] Click "Complete" from ProjectDetail footer opens dialog +- [ ] Journey summary shows correct days, notes, conversations counts +- [ ] Empty reflection is accepted +- [ ] Reflection with text is saved to project +- [ ] Cancel closes dialog without changes +- [ ] Completing updates project status to "completed" +- [ ] Completed project shows in list when filter is "All" or "Completed" +- [ ] Completed project does NOT appear when filter is "Active" +- [ ] `goal.md` file contains `status: "completed"` and `completedAt` timestamp +- [ ] `goal.md` file contains reflection text + +### 6.2 Archived Goals View + +- [ ] Archived projects appear in list when filter is "All" or "Archived" +- [ ] Archived project detail shows "Archived" badge +- [ ] "Add Notes" and "Suggest" buttons hidden for archived projects +- [ ] Footer shows only "Edit" and "Reactivate" for archived projects +- [ ] Reactivating changes status back to "active" +- [ ] All actions re-enabled after reactivation + +### 6.3 Settings Tab + +- [ ] Projects+ settings appear in Plus/Advanced tab +- [ ] Folder path input accepts valid paths +- [ ] Info message about shared QA settings is visible +- [ ] Settings persist after Obsidian reload +- [ ] Changing folder path affects new project creation + +### 6.4 Note Suggestions with Exclusions + +- [ ] Notes in excluded folders (from QA settings) don't appear in suggestions +- [ ] Notes matching inclusion patterns appear in suggestions +- [ ] Exclusions take precedence over inclusions +- [ ] Suggestions work correctly with empty exclusions/inclusions + +### 6.5 Persistence + +- [ ] Create project, complete it, reload Obsidian - project still completed +- [ ] Reflection text persists after reload +- [ ] Settings persist after reload +- [ ] Projects folder setting affects file storage location + +--- + +## Appendix A: ProjectStatusBadge Styles Reference + +```typescript +// Current implementation in utils.ts (used by ProjectStatusBadge) +export function getStatusBadgeStyles(status: ProjectStatus): string { + switch (status) { + case "active": + return "tw-bg-modifier-success-rgb/20 tw-text-success"; + case "completed": + return "tw-bg-blue-rgb/20 tw-text-context-manager-blue"; + case "archived": + return "tw-bg-modifier-hover tw-text-muted"; + default: + return ""; + } +} +``` + +## Appendix B: Default Settings Values + +```typescript +// From constants.ts +export const DEFAULT_PROJECTS_FOLDER = "copilot/projects"; + +// From DEFAULT_SETTINGS +projectsPlusFolder: DEFAULT_PROJECTS_FOLDER, + +// Note: projectsPlusEnabled has been removed - feature is always enabled +``` + +## Appendix C: Removed Settings Rationale + +| Removed Setting | Reason | +| --------------------- | ----------------------------------------------------- | +| `projectsPlusEnabled` | Feature is always enabled, no toggle needed | +| `showCompletedInList` | Filter dropdown provides this functionality directly | +| `noteSuggestionCount` | Handled by search system, no user-facing limit needed | +| `excludedFolders` | Consolidated with main `qaExclusions` setting | +| `autoSaveEnabled` | Always enabled per design decision | +| `defaultDiscussModel` | Uses main `defaultModelKey` for consistency | + +This consolidation reduces settings complexity and ensures consistent behavior across the plugin. diff --git a/src/components/projects-plus/ProjectCard.tsx b/src/components/projects-plus/ProjectCard.tsx index 7877db00..ca9b2490 100644 --- a/src/components/projects-plus/ProjectCard.tsx +++ b/src/components/projects-plus/ProjectCard.tsx @@ -1,7 +1,9 @@ -import { Project, ProjectStatus } from "@/types/projects-plus"; +import { Project } from "@/types/projects-plus"; import { Check, Edit, FileText, MessageSquare, MoreVertical, Trash2 } from "lucide-react"; import * as React from "react"; import { useState } from "react"; +import { ProjectStatusBadge } from "./ProjectStatusBadge"; +import { formatRelativeTime } from "./utils"; interface ProjectCardProps { project: Project; @@ -11,45 +13,6 @@ interface ProjectCardProps { onDelete: () => void; } -/** - * Get badge styling based on project status - */ -function getStatusBadgeStyles(status: ProjectStatus): string { - switch (status) { - case "active": - return "tw-bg-interactive-accent-hsl/20 tw-text-accent"; - case "completed": - return "tw-bg-success tw-text-success"; - case "archived": - return "tw-bg-secondary tw-text-muted"; - default: - return "tw-bg-secondary tw-text-muted"; - } -} - -/** - * Format a timestamp to relative time - */ -function formatRelativeTime(timestamp: number): string { - const now = Date.now(); - const diff = now - timestamp; - const seconds = Math.floor(diff / 1000); - const minutes = Math.floor(seconds / 60); - const hours = Math.floor(minutes / 60); - const days = Math.floor(hours / 24); - - if (days > 0) { - return days === 1 ? "1 day ago" : `${days} days ago`; - } - if (hours > 0) { - return hours === 1 ? "1 hour ago" : `${hours} hours ago`; - } - if (minutes > 0) { - return minutes === 1 ? "1 minute ago" : `${minutes} minutes ago`; - } - return "just now"; -} - /** * ProjectCard - Individual project card with actions */ @@ -86,11 +49,7 @@ export default function ProjectCard({ {project.title}
- - {project.status} - + {/* Menu button */}
diff --git a/src/components/projects-plus/ProjectDetail.tsx b/src/components/projects-plus/ProjectDetail.tsx index c6dd9feb..46946500 100644 --- a/src/components/projects-plus/ProjectDetail.tsx +++ b/src/components/projects-plus/ProjectDetail.tsx @@ -25,12 +25,8 @@ import { NoteSuggestionsDialog } from "./NoteSuggestionsDialog"; import { ProjectStatusDialog, StatusAction } from "./ProjectStatusDialog"; import { DiscussView } from "./discuss/DiscussView"; import { ConversationPersistence } from "@/core/projects-plus/ConversationPersistence"; -import { - getStatusBadgeStyles, - formatRelativeTime, - formatDate, - calculateJourneySummary, -} from "./utils"; +import { formatRelativeTime, formatDate, calculateJourneySummary } from "./utils"; +import { ProjectStatusBadge } from "./ProjectStatusBadge"; interface ProjectDetailProps { projectId: string; @@ -220,11 +216,7 @@ export function ProjectDetail({ projectId, plugin, onBack }: ProjectDetailProps)

{project.title}

- - {project.status} - +
{/* Scrollable content */} diff --git a/src/components/projects-plus/ProjectStatusBadge.tsx b/src/components/projects-plus/ProjectStatusBadge.tsx new file mode 100644 index 00000000..4aacb7a5 --- /dev/null +++ b/src/components/projects-plus/ProjectStatusBadge.tsx @@ -0,0 +1,26 @@ +import { ProjectStatus } from "@/types/projects-plus"; +import { cn } from "@/lib/utils"; +import { getStatusBadgeStyles } from "./utils"; +import * as React from "react"; + +interface ProjectStatusBadgeProps { + status: ProjectStatus; + className?: string; +} + +/** + * Reusable status badge component for projects + */ +export function ProjectStatusBadge({ status, className }: ProjectStatusBadgeProps) { + return ( + + {status} + + ); +} diff --git a/src/constants.ts b/src/constants.ts index 3caa5be9..a3e1a39c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -824,7 +824,6 @@ export const DEFAULT_SETTINGS: CopilotSettings = { quickCommandModelKey: undefined, quickCommandIncludeNoteContext: true, autoIncludeTextSelection: false, - projectsPlusEnabled: false, projectsPlusFolder: DEFAULT_PROJECTS_FOLDER, }; diff --git a/src/main.ts b/src/main.ts index 25e67eb5..938a3688 100644 --- a/src/main.ts +++ b/src/main.ts @@ -123,11 +123,8 @@ export default class CopilotPlugin extends Plugin { // Initialize UserMemoryManager this.userMemoryManager = new UserMemoryManager(this.app); - // Initialize ProjectManager for Projects+ + // Initialize ProjectManager for Projects+ (full initialization happens when view opens) this.projectsPlusManager = new ProjectManager(this.app); - if (getSettings().projectsPlusEnabled) { - await this.projectsPlusManager.initialize(); - } // Initialize NoteAssignmentService for Projects+ this.noteAssignmentService = new NoteAssignmentService(this.app, () => { @@ -456,10 +453,7 @@ export default class CopilotPlugin extends Plugin { * Open the Projects+ panel */ async activateProjectsView(): Promise { - // Initialize ProjectManager if not already done - if (!this.projectsPlusManager) { - this.projectsPlusManager = new ProjectManager(this.app); - } + // Initialize ProjectManager before opening the view await this.projectsPlusManager.initialize(); const leaves = this.app.workspace.getLeavesOfType(PROJECTS_PLUS_VIEWTYPE); diff --git a/src/settings/model.ts b/src/settings/model.ts index add27be3..b39b482d 100644 --- a/src/settings/model.ts +++ b/src/settings/model.ts @@ -153,8 +153,6 @@ export interface CopilotSettings { quickCommandIncludeNoteContext: boolean; /** Automatically add text selections to chat context */ autoIncludeTextSelection: boolean; - /** Enable Projects+ feature */ - projectsPlusEnabled: boolean; /** Folder path for Projects+ data */ projectsPlusFolder: string; } @@ -428,11 +426,6 @@ export function sanitizeSettings(settings: CopilotSettings): CopilotSettings { sanitizedSettings.qaExclusions = sanitizeQaExclusions(settingsToSanitize.qaExclusions); - // Ensure projectsPlusEnabled has a default value - if (typeof sanitizedSettings.projectsPlusEnabled !== "boolean") { - sanitizedSettings.projectsPlusEnabled = DEFAULT_SETTINGS.projectsPlusEnabled; - } - // Ensure projectsPlusFolder has a valid value const projectsFolder = (settingsToSanitize.projectsPlusFolder || "").trim(); sanitizedSettings.projectsPlusFolder = diff --git a/src/settings/v2/components/CopilotPlusSettings.tsx b/src/settings/v2/components/CopilotPlusSettings.tsx index d46ef182..aebd21ff 100644 --- a/src/settings/v2/components/CopilotPlusSettings.tsx +++ b/src/settings/v2/components/CopilotPlusSettings.tsx @@ -3,6 +3,7 @@ import { SettingItem } from "@/components/ui/setting-item"; import { updateSetting, useSettingsValue } from "@/settings/model"; import React from "react"; import { ToolSettingsSection } from "./ToolSettingsSection"; +import { ProjectsPlusSettings } from "./ProjectsPlusSettings"; export const CopilotPlusSettings: React.FC = () => { const settings = useSettingsValue(); @@ -79,6 +80,8 @@ export const CopilotPlusSettings: React.FC = () => { updateSetting("enableSavedMemory", checked); }} /> + +
diff --git a/src/settings/v2/components/ProjectsPlusSettings.tsx b/src/settings/v2/components/ProjectsPlusSettings.tsx new file mode 100644 index 00000000..ef6d4f74 --- /dev/null +++ b/src/settings/v2/components/ProjectsPlusSettings.tsx @@ -0,0 +1,30 @@ +import { SettingItem } from "@/components/ui/setting-item"; +import { updateSetting, useSettingsValue } from "@/settings/model"; +import React from "react"; + +/** + * Settings section for Projects+ feature configuration + */ +export const ProjectsPlusSettings: React.FC = () => { + const settings = useSettingsValue(); + + return ( + <> +
Projects+
+ + updateSetting("projectsPlusFolder", value)} + placeholder="copilot/projects" + /> + +
+ Note: Projects+ uses the same inclusion/exclusion settings as QA Mode for + note suggestions. Configure them in the QA settings tab. +
+ + ); +};