diff --git a/CLAUDE.md b/CLAUDE.md index 4240b75..1819569 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -297,4 +297,61 @@ When working on this project: 6. Test changes incrementally 7. Update documentation when architecture changes 8. Use the build commands above for compilation testing -9. When asked about Jira/Confluence, use the Atlassian resources defined above \ No newline at end of file +9. When asked about Jira/Confluence, use the Atlassian resources defined above + +## JIRA Management Guidelines + +### Task Status Updates +- **NEVER edit task descriptions** to update status or progress +- **ALWAYS use comments** to provide status updates instead +- **Preserve original task descriptions** - they document the original intent and requirements +- **Comments should include**: current progress, blockers, next steps, implementation notes + +### Task Completion Rules +- **NEVER mark tasks as "Done"** without explicit user approval +- **Code compilation ≠ task completion** - must be tested on actual device +- **Implementation complete ≠ task complete** - requires validation and testing +- **Always check with user** before transitioning tasks to "Done" status +- **Use "In Progress"** for actively worked tasks, even if implementation is complete + +### Progress Documentation +- **Use comments for progress updates**: + ``` + Progress Update: + ✅ Implementation complete - added close functionality to drawer + ✅ Compilation successful + 🔄 Next steps: Device testing required before marking complete + 📋 Files modified: ResultsBottomDrawer.kt, enhanced swipe-to-dismiss + ``` + +### Status Workflow +1. **To Do** → Start working +2. **In Progress** → Implementation and testing in progress +3. **Ready for Review** → Implementation complete, needs device testing/validation +4. **Done** → Only after user confirmation that feature works as expected + +### Implementation vs Completion +- **Implementation Complete**: Code written, compiles, logic appears correct +- **Task Complete**: Feature tested on device, user validated, works as intended +- **Always distinguish** between these two states in updates + +### Example Comment Format +``` +**Implementation Progress:** +- ✅ Added swipe-to-dismiss functionality +- ✅ Enhanced close buttons in both states +- ✅ Build compilation successful +- 🔄 **Pending**: Device testing to validate gesture behavior +- 🔄 **Pending**: User validation of close functionality + +**Technical Details:** +- Modified touch handling in ResultsBottomDrawer.kt +- Enhanced gesture detection for full dismiss vs collapse +- Added header close button for expanded state + +**Next Steps:** +- Device testing required +- User validation needed before marking Done +``` + +This preserves original task intent while providing clear progress visibility. \ No newline at end of file diff --git a/app/src/main/java/com/quillstudios/pokegoalshelper/ScreenCaptureService.kt b/app/src/main/java/com/quillstudios/pokegoalshelper/ScreenCaptureService.kt index d5b4d0b..944d81f 100644 --- a/app/src/main/java/com/quillstudios/pokegoalshelper/ScreenCaptureService.kt +++ b/app/src/main/java/com/quillstudios/pokegoalshelper/ScreenCaptureService.kt @@ -134,7 +134,7 @@ class ScreenCaptureService : Service() { private lateinit var screenCaptureManager: ScreenCaptureManager private var detectionOverlay: DetectionOverlay? = null - private var overlayEnabled = true // Track overlay visibility state + private var overlayEnabled = false // Track overlay visibility state private var lastDetections: List = emptyList() // Cache last detections for toggle // MVC Components @@ -558,6 +558,9 @@ class ScreenCaptureService : Service() { pokemonInfo = pokemonInfo, processingTimeMs = duration ) + + // Stop spinning animation - detection complete + enhancedFloatingFAB?.stopDetectionAnimation() } else { PGHLog.i(TAG, "❌ Could not extract complete Pokemon info") @@ -566,6 +569,9 @@ class ScreenCaptureService : Service() { detections = extractorDetections, processingTimeMs = duration ) + + // Stop spinning animation - detection complete (no results) + enhancedFloatingFAB?.stopDetectionAnimation() } } finally { // Analysis cycle complete, allow next one @@ -603,6 +609,9 @@ class ScreenCaptureService : Service() { errorMessage = "Processing error: ${e.message}", processingTimeMs = duration ) + + // Stop spinning animation - detection failed + enhancedFloatingFAB?.stopDetectionAnimation() } // Clear flag on error too @@ -1185,6 +1194,9 @@ class ScreenCaptureService : Service() { private fun triggerManualDetection() { PGHLog.d(TAG, "🔍 Manual detection triggered via MVC!") + // Start spinning animation to show detection is in progress + enhancedFloatingFAB?.startDetectionAnimation() + latestImage?.let { image -> try { // Convert image to Mat for processing @@ -1210,11 +1222,16 @@ class ScreenCaptureService : Service() { // Extract Pokemon info using YOLO detections with OCR extractPokemonInfoFromYOLOAsync(mat, detections) + } else { + // No detections found - stop animation + PGHLog.i(TAG, "No detections found") + enhancedFloatingFAB?.stopDetectionAnimation() } mat.release() } else { PGHLog.e(TAG, "❌ Failed to convert image to Mat") + enhancedFloatingFAB?.stopDetectionAnimation() } // Close the image after processing to free the buffer @@ -1223,9 +1240,11 @@ class ScreenCaptureService : Service() { } catch (e: Exception) { PGHLog.e(TAG, "❌ Error in manual detection", e) + enhancedFloatingFAB?.stopDetectionAnimation() } } ?: run { PGHLog.w(TAG, "⚠️ No image available for detection") + enhancedFloatingFAB?.stopDetectionAnimation() } } diff --git a/app/src/main/java/com/quillstudios/pokegoalshelper/ui/EnhancedFloatingFAB.kt b/app/src/main/java/com/quillstudios/pokegoalshelper/ui/EnhancedFloatingFAB.kt index 6fbfa88..db10064 100644 --- a/app/src/main/java/com/quillstudios/pokegoalshelper/ui/EnhancedFloatingFAB.kt +++ b/app/src/main/java/com/quillstudios/pokegoalshelper/ui/EnhancedFloatingFAB.kt @@ -53,6 +53,8 @@ class EnhancedFloatingFAB( private var isShowing = false private var isMenuExpanded = false private var isDragging = false + private var isDetecting = false + private var spinAnimator: ObjectAnimator? = null // Animation and positioning private var currentX = 0 @@ -565,6 +567,50 @@ class EnhancedFloatingFAB( ).toInt() } + /** + * Start spinning animation to indicate detection is in progress + */ + fun startDetectionAnimation() { + if (isDetecting) return // Already spinning + + isDetecting = true + mainFAB?.let { fab -> + spinAnimator = ObjectAnimator.ofFloat(fab, "rotation", 0f, 360f).apply { + duration = 1000L // 1 second per rotation + repeatCount = ObjectAnimator.INFINITE + repeatMode = ObjectAnimator.RESTART + interpolator = AccelerateDecelerateInterpolator() + start() + } + } + } + + /** + * Stop spinning animation when detection completes + */ + fun stopDetectionAnimation() { + if (!isDetecting) return // Not spinning + + isDetecting = false + spinAnimator?.let { animator -> + animator.cancel() + // Smoothly return to 0 rotation + mainFAB?.let { fab -> + ObjectAnimator.ofFloat(fab, "rotation", fab.rotation, 0f).apply { + duration = 200L + interpolator = AccelerateDecelerateInterpolator() + start() + } + } + } + spinAnimator = null + } + + /** + * Check if detection animation is currently running + */ + fun isDetectionAnimationRunning(): Boolean = isDetecting + private data class MenuItemData( val label: String, val iconRes: Int,