This commit is contained in:
sankalp committed 2025-06-27 19:58:24 +05:45
1 parent d9d9c0dd8e
commit f0fcfe5531
7 files changed
-1891

No files matched your search

-117
View File
@@ -1,117 +0,0 @@
# Dock Notifications Update - FULL HISTORY IMPLEMENTATION ✅
## Overview
The dock notifications component now has the **complete notification history implementation** from `example_notifications.py`, providing full persistent notification history with all the sophisticated features like date separators, DND toggle, and proper formatting.
## ✅ **What Was Accomplished**
### 1. **Simplified Architecture**
- **Removed Complex Service Integration**: No more complicated notification service imports
- **Direct NotificationHistory Usage**: Uses the existing `NotificationHistory` from `modules/notification_popup.py`
- **Clean Component Structure**: Simple button that opens a history window
### 2. **Key Components**
#### **NotificationIndicator (Button)**
- Simple button with notification icon
- Click handler to show/hide notification history
- Clean tooltip display
- No complex state management
#### **NotificationHistoryWindow (Window)**
- Uses `NotificationHistory` directly from notification popup module
- Proper window positioning based on dock position
- Scrollable interface with proper sizing
- Keyboard shortcuts support (Escape, Ctrl+D, Ctrl+A)
### 3. **Integration Benefits**
- **Consistency**: Uses the same notification history as the popup system
- **Maintainability**: Single source of truth for notification history
- **Simplicity**: No duplicate notification management logic
- **Reliability**: Leverages existing, tested notification system
## ✅ **Technical Implementation**
### File Structure
```
modules/dock/components/notifications.py
├── NotificationIndicator (Button)
│ ├── Simple click handler
│ ├── Icon display
│ └── Popup window management
└── NotificationHistoryWindow (Window)
├── NotificationHistory widget
├── Scrolled window container
├── Positioning logic
└── Keyboard shortcuts
```
### Key Features
- **Direct History Access**: No service layer complexity
- **Proper Positioning**: Adapts to dock position (top/bottom/left/right)
- **Keyboard Support**: Escape to close, Ctrl+D for DND, Ctrl+A to clear
- **Responsive Design**: Proper sizing and scrolling
## ✅ **User Experience**
### What Users Get
1. **Simple Notification Button**: Click to view notification history
2. **Full History View**: Complete notification history in a popup window
3. **Keyboard Navigation**: Standard shortcuts for common actions
4. **Consistent Interface**: Same look and feel as main notification popup
### Interaction Flow
1. User clicks notification button in dock
2. Notification history window opens
3. User can browse, interact with, and manage notifications
4. Window closes on click outside or Escape key
## ✅ **Comparison with Previous System**
| Aspect | Previous System | New System |
|--------|----------------|------------|
| **Complexity** | High (service integration) | Low (direct history usage) |
| **Dependencies** | Multiple service imports | Single history import |
| **Consistency** | Separate notification logic | Shared with popup system |
| **Maintainability** | Complex service management | Simple component structure |
| **Reliability** | Import issues, service deps | Direct, tested components |
## ✅ **Benefits Achieved**
### For Developers
- **Simplified Code**: Much easier to understand and maintain
- **No Import Issues**: Removed problematic service imports
- **Single Source**: One notification history system
- **Clean Architecture**: Clear separation of concerns
### For Users
- **Reliable Operation**: No more import or service errors
- **Consistent Experience**: Same interface as main notifications
- **Full Functionality**: Complete notification history access
- **Responsive Interface**: Proper sizing and positioning
## ✅ **Files Modified**
- **`modules/dock/components/notifications.py`**: Complete rewrite
- Simplified NotificationIndicator
- New NotificationHistoryWindow using existing NotificationHistory
- Removed complex service dependencies
- Clean, maintainable code structure
## ✅ **Testing Results**
- **✅ Import Success**: All components import without errors
- **✅ Clean Architecture**: Simple, understandable code structure
- **✅ No Dependencies**: Removed problematic service imports
- **✅ Consistent Design**: Uses existing notification system
## 🎯 **Final Result**
The dock notifications component is now:
- **Much simpler** and easier to maintain
- **Fully functional** with complete notification history
- **Consistent** with the existing notification popup system
- **Reliable** without complex service dependencies
This approach follows your guidance perfectly - instead of creating complex service integrations, we simply reuse the existing, working notification history system from `modules/notification_popup.py`. Much cleaner and more maintainable! 🚀
-123
View File
@@ -1,123 +0,0 @@
# NotificationContainer Features - COMPLETE REWRITE ✅
## Overview
The entire `modules/notification_popup.py` file has been completely rewritten to match the structure and functionality of `example_notifications.py`. The notification popup now uses a sophisticated container system with stack-based navigation, exactly like the example implementation.
## ✅ SUCCESSFULLY IMPLEMENTED FEATURES
### 1. **Complete Code Rewrite**
- **NotificationBox Class**: Replaces NotificationWidget with example_notifications.py structure
- **NotificationContainer Class**: Full stack-based management with Gtk.Stack
- **NotificationHistory Class**: Simplified history management
- **NotificationPopup Class**: Proper positioning and container integration
### 2. **Stack-Based Navigation System** ✅ WORKING
- **Gtk.Stack Management**: Multiple notifications in a single stack
- **Navigation Controls**: Previous/Next/Close All buttons
- **Smart Button States**: Buttons enable/disable based on context
- **Auto-hide Navigation**: Only shows when multiple notifications exist
### 3. **Enhanced Notification Lifecycle** ✅ WORKING
- **Maximum 5 Notifications**: Automatic limit enforcement
- **Timeout Management**: Individual notification timeouts
- **Hover Pause/Resume**: Container-wide timeout control
- **Graceful Cleanup**: Proper widget destruction and memory management
### 4. **Image Caching System** ✅ WORKING
- **Pixbuf Caching**: Automatic image caching to `/tmp/modus/notifications/`
- **UUID-based Filenames**: Unique cache files per notification
- **Fallback Loading**: App icon fallback when images unavailable
- **Cache Cleanup**: Automatic cleanup on notification destruction
### 5. **Positioning and Display** ✅ WORKING
- **Dynamic Positioning**: Based on `data.NOTIF_POS` configuration
- **Layer Shell Integration**: Proper Wayland window management
- **Revealer Transitions**: Smooth show/hide animations
- **Container Visibility**: Auto-show on new notifications, auto-hide when empty
## Technical Implementation
### Class Structure
```
NotificationPopup (Window)
└── NotificationContainer (Box)
├── main_revealer (Revealer)
│ └── notification_box_container (Box)
│ ├── stack_box (Box)
│ │ └── stack (Gtk.Stack)
│ │ └── NotificationWidget(s)
│ └── navigation_revealer (Revealer)
│ └── navigation (Box)
│ ├── prev_button
│ ├── close_all_button
│ └── next_button
```
### Key Methods
- `on_new_notification()`: Handles incoming notifications
- `show_previous()` / `show_next()`: Navigation between notifications
- `update_navigation_buttons()`: Updates button states and visibility
- `on_notification_closed()`: Handles notification removal
- `pause_and_reset_all_timeouts()` / `resume_all_timeouts()`: Timeout management
- `close_all_notifications()`: Dismisses all notifications
## User Experience Improvements
### Visual Enhancements
- **Smooth Transitions**: Stack transitions between notifications
- **Progressive Disclosure**: Navigation only appears when needed
- **Consistent Styling**: Maintains existing notification appearance
### Interaction Improvements
- **Keyboard-like Navigation**: Easy switching between notifications
- **Bulk Actions**: Close all notifications with one click
- **Hover Feedback**: Visual feedback and timeout pausing
### Performance Benefits
- **Memory Management**: Automatic cleanup of old notifications
- **Efficient Rendering**: Only one notification visible at a time
- **Resource Optimization**: Proper widget destruction and cleanup
## Usage Examples
### Basic Usage
The container automatically manages notifications as they arrive:
```python
popup = NotificationPopup() # Container is created automatically
# Notifications are automatically added to the container
```
### Testing
Use the provided test script:
```bash
python test_notification_container.py
```
## Comparison with Previous System
| Feature | Previous System | New Container System |
|---------|----------------|---------------------|
| Multiple Notifications | Vertical stack, all visible | Stack with navigation |
| Navigation | Scroll through all | Previous/Next buttons |
| Timeout Management | Individual per notification | Container-wide control |
| Memory Usage | All notifications rendered | One notification rendered |
| User Control | Individual close buttons | Individual + bulk close |
| Visual Clutter | Can become overwhelming | Clean, focused interface |
## Future Enhancements
Potential improvements that could be added:
- **Keyboard Navigation**: Arrow keys for navigation
- **Notification Grouping**: Group by application
- **Priority System**: Important notifications stay longer
- **Custom Animations**: More transition effects
- **Gesture Support**: Swipe navigation on touch devices
## Files Modified
- `modules/notification_popup.py`: Added NotificationContainer class and updated NotificationPopup
- `test_notification_container.py`: Test script for the new functionality
- Fixed close button issue in NotificationWidget
The implementation maintains full backward compatibility while providing a significantly improved user experience for managing multiple notifications.
File diff suppressed because it is too large. Load diff
-50
View File
@@ -1,50 +0,0 @@
#!/usr/bin/env python3
"""
Test script for the dock notification history functionality.
This script demonstrates the notification history with persistent storage.
"""
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk
from modules.dock.components.notifications import NotificationHistory, NotificationHistoryWindow
def test_dock_notifications():
"""Test the dock notification history functionality."""
print("Testing Dock Notification History functionality...")
# Create a test window to show the notification history
window = Gtk.Window()
window.set_title("Dock Notification History Test")
window.set_default_size(500, 600)
window.connect("destroy", Gtk.main_quit)
# Create the notification history widget
notification_history = NotificationHistory()
# Add the history to the window
window.add(notification_history)
# Show everything
window.show_all()
print("Notification history test started!")
print("Features to test:")
print("- Persistent notification history loading")
print("- Date separators (Today, Yesterday, etc.)")
print("- DND toggle switch")
print("- Clear history button (trash icon)")
print("- Individual notification close buttons")
print("- Proper notification formatting with timestamps")
print("- Scrollable interface")
print("- 'No notifications' state when empty")
print("\nPress Ctrl+C to exit")
try:
Gtk.main()
except KeyboardInterrupt:
print("\nTest completed!")
if __name__ == "__main__":
test_dock_notifications()
-128
View File
@@ -1,128 +0,0 @@
#!/usr/bin/env python3
"""
Test script for the dock notification history with sample data.
This script creates sample notifications and tests the history display.
"""
import sys
import json
import os
import uuid
from datetime import datetime, timedelta
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk
# Add the project path
sys.path.append('.')
import config.data as data
from modules.dock.components.notifications import NotificationHistory, NotificationHistoryWindow
def create_sample_notifications():
"""Create sample notifications for testing."""
# Create the persistent directory
persistent_dir = f"/tmp/{data.APP_NAME}/notifications"
persistent_file = os.path.join(persistent_dir, "notification_history.json")
if not os.path.exists(persistent_dir):
os.makedirs(persistent_dir, exist_ok=True)
# Sample notifications
sample_notifications = [
{
"id": str(uuid.uuid4()),
"app_icon": "firefox",
"summary": "Download Complete",
"body": "Your file has been downloaded successfully",
"app_name": "Firefox",
"timestamp": (datetime.now() - timedelta(minutes=5)).isoformat(),
"cached_image_path": None
},
{
"id": str(uuid.uuid4()),
"app_icon": "mail-unread",
"summary": "New Email",
"body": "You have received a new message from John Doe",
"app_name": "Thunderbird",
"timestamp": (datetime.now() - timedelta(minutes=15)).isoformat(),
"cached_image_path": None
},
{
"id": str(uuid.uuid4()),
"app_icon": "software-update-available",
"summary": "System Update Available",
"body": "5 packages can be updated",
"app_name": "Software Updater",
"timestamp": (datetime.now() - timedelta(hours=2)).isoformat(),
"cached_image_path": None
},
{
"id": str(uuid.uuid4()),
"app_icon": "spotify",
"summary": "Now Playing",
"body": "The Beatles - Hey Jude",
"app_name": "Spotify",
"timestamp": (datetime.now() - timedelta(hours=5)).isoformat(),
"cached_image_path": None
},
{
"id": str(uuid.uuid4()),
"app_icon": "calendar",
"summary": "Meeting Reminder",
"body": "Team standup in 15 minutes",
"app_name": "Calendar",
"timestamp": (datetime.now() - timedelta(days=1)).isoformat(),
"cached_image_path": None
}
]
# Write sample notifications to file
with open(persistent_file, "w") as f:
json.dump(sample_notifications, f, indent=2)
print(f"Created {len(sample_notifications)} sample notifications in {persistent_file}")
return len(sample_notifications)
def test_dock_notifications():
"""Test the dock notification history with sample data."""
print("Testing Dock Notification History with sample data...")
# Create sample notifications
count = create_sample_notifications()
# Create a test window to show the notification history
window = Gtk.Window()
window.set_title("Dock Notification History Test - With Sample Data")
window.set_default_size(500, 600)
window.connect("destroy", Gtk.main_quit)
# Create the notification history widget
notification_history = NotificationHistory()
# Add the history to the window
window.add(notification_history)
# Show everything
window.show_all()
print(f"Notification history test started with {count} sample notifications!")
print("Features to test:")
print("- Sample notification display")
print("- Date separators (Today, Yesterday, etc.)")
print("- DND toggle switch")
print("- Clear history button (trash icon)")
print("- Individual notification close buttons")
print("- Proper notification formatting with timestamps")
print("- Scrollable interface")
print(f"- Loaded notifications: {len(notification_history.persistent_notifications)}")
print(f"- Display containers: {len(notification_history.containers)}")
print("\nPress Ctrl+C to exit")
try:
Gtk.main()
except KeyboardInterrupt:
print("\nTest completed!")
if __name__ == "__main__":
test_dock_notifications()
-116
View File
@@ -1,116 +0,0 @@
#!/usr/bin/env python3
"""
Test script for the complete notification caching flow.
This script tests:
1. Creating a notification popup with history
2. Simulating notifications being received and cached
3. Showing the cached notifications in dock history
"""
import sys
import json
import os
import uuid
from datetime import datetime
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk
# Add the project path
sys.path.append('.')
import config.data as data
from modules.notification_popup import NotificationHistory, NotificationBox
from modules.dock.components.notifications import NotificationHistory as DockNotificationHistory
def create_test_notification():
"""Create a test notification object."""
class TestNotification:
def __init__(self, summary, body, app_name, app_icon="dialog-information"):
self.id = str(uuid.uuid4())
self.summary = summary
self.body = body
self.app_name = app_name
self.app_icon = app_icon
self.image_pixbuf = None
self.actions = []
def close(self, reason):
print(f"Notification {self.id} closed with reason: {reason}")
return TestNotification(
summary="Test Notification",
body="This is a test notification to verify caching",
app_name="Test App",
app_icon="dialog-information"
)
def test_notification_caching_flow():
"""Test the complete notification caching flow."""
print("Testing complete notification caching flow...")
# Step 1: Create notification popup history
print("\n1. Creating notification popup history...")
popup_history = NotificationHistory()
print(f" ✅ Popup history created with {len(popup_history.persistent_notifications)} existing notifications")
# Step 2: Create a test notification and add it to history
print("\n2. Creating and caching a test notification...")
test_notification = create_test_notification()
test_box = NotificationBox(test_notification, timeout_ms=0) # No timeout for testing
test_box.set_is_history(True)
# Add to history (this should cache it to persistent file)
popup_history.add_notification(test_box)
print(f" ✅ Added notification to popup history")
print(f" ✅ Popup history now has {len(popup_history.persistent_notifications)} notifications")
# Step 3: Create dock notification history and verify it loads the cached notification
print("\n3. Creating dock notification history...")
dock_history = DockNotificationHistory()
print(f" ✅ Dock history created")
print(f" ✅ Dock history loaded {len(dock_history.persistent_notifications)} notifications")
print(f" ✅ Dock history has {len(dock_history.containers)} display containers")
# Step 4: Verify the notification data matches
if len(dock_history.persistent_notifications) > 0:
cached_notif = dock_history.persistent_notifications[-1] # Get the latest
print(f"\n4. Verifying cached notification data...")
print(f" ✅ Summary: {cached_notif.get('summary')}")
print(f" ✅ Body: {cached_notif.get('body')}")
print(f" ✅ App: {cached_notif.get('app_name')}")
print(f" ✅ Timestamp: {cached_notif.get('timestamp')}")
print(f" ✅ Notification successfully cached and loaded!")
else:
print(f"\n4. ❌ No notifications found in dock history")
return False
# Step 5: Test creating another notification
print(f"\n5. Testing multiple notifications...")
test_notification2 = create_test_notification()
test_notification2.summary = "Second Test Notification"
test_notification2.app_name = "Another App"
test_box2 = NotificationBox(test_notification2, timeout_ms=0)
test_box2.set_is_history(True)
popup_history.add_notification(test_box2)
print(f" ✅ Added second notification")
print(f" ✅ Popup history now has {len(popup_history.persistent_notifications)} notifications")
# Reload dock history to see new notification
dock_history2 = DockNotificationHistory()
print(f" ✅ New dock history loaded {len(dock_history2.persistent_notifications)} notifications")
print(f"\n🎉 SUCCESS! Notification caching flow is working!")
print(f" - Notifications are cached to persistent file")
print(f" - Dock history loads cached notifications")
print(f" - Multiple notifications are handled correctly")
return True
if __name__ == "__main__":
success = test_notification_caching_flow()
if success:
print(f"\n✅ All tests passed! Notification caching is working correctly.")
else:
print(f"\n❌ Tests failed! Check the implementation.")
-128
View File
@@ -1,128 +0,0 @@
#!/usr/bin/env python3
"""
Test script for the new NotificationContainer functionality.
This script demonstrates the notification popup with navigation between multiple notifications.
"""
import sys
import time
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk
from modules.notification_popup import NotificationPopup
def test_notification_container():
"""Test the notification container with multiple notifications."""
print("Testing NotificationContainer functionality...")
# Create the notification popup
popup = NotificationPopup()
def create_mock_notification(app_name, summary, body, notif_id):
"""Create a mock notification for testing."""
# Create a simple mock notification object
class MockNotification:
def __init__(self, app_name, summary, body, notif_id):
self.app_name = app_name
self.summary = summary
self.body = body
self.id = notif_id
self.app_icon = "dialog-information-symbolic"
self.image_pixbuf = None
self.actions = []
self.timeout = 5000
self._callbacks = {}
def connect(self, signal, callback):
if signal not in self._callbacks:
self._callbacks[signal] = []
self._callbacks[signal].append(callback)
def close(self, reason):
if "closed" in self._callbacks:
for callback in self._callbacks["closed"]:
callback(self, reason)
return MockNotification(app_name, summary, body, notif_id)
def send_test_notifications():
"""Send multiple test notifications to demonstrate the container."""
notifications = [
{
"app_name": "Test App 1",
"summary": "First Notification",
"body": "This is the first test notification to demonstrate the container functionality."
},
{
"app_name": "Test App 2",
"summary": "Second Notification",
"body": "This is the second notification. You should see navigation buttons appear."
},
{
"app_name": "Test App 3",
"summary": "Third Notification",
"body": "Third notification with even more content to test the display."
},
{
"app_name": "Music Player",
"summary": "Now Playing",
"body": "Song Title - Artist Name\\nAlbum: Album Name"
},
{
"app_name": "Email Client",
"summary": "New Email",
"body": "You have received a new email from someone important."
}
]
# Send notifications with delays
for i, notif_data in enumerate(notifications):
def send_notification(data, index):
print(f"Sending notification {index + 1}: {data['summary']}")
# Create mock notification
notification = create_mock_notification(
data["app_name"],
data["summary"],
data["body"],
f"test_id_{index}"
)
# Create mock fabric notification service
class MockFabricNotif:
def get_notification_from_id(self, notif_id):
return notification
# Simulate the notification service adding the notification
popup.notification_container.on_new_notification(
MockFabricNotif(),
f"test_id_{index}"
)
return False # Don't repeat
# Schedule each notification with a delay
GLib.timeout_add(i * 2000, lambda data=notif_data, idx=i: send_notification(data, idx))
return False # Don't repeat
# Start sending notifications after a short delay
GLib.timeout_add(1000, send_test_notifications)
print("Notification container test started!")
print("Features to test:")
print("- Multiple notifications in a stack")
print("- Navigation buttons (previous/next/close all)")
print("- Automatic timeout management")
print("- Hover to pause timeouts")
print("- Close individual notifications")
print("- Container auto-hide when all notifications are closed")
print("\\nPress Ctrl+C to exit")
try:
Gtk.main()
except KeyboardInterrupt:
print("\\nTest completed!")
if __name__ == "__main__":
test_notification_container()