No description
Find a file
Jonas SNK 0a8ee86996 cc
2025-10-27 21:35:19 +01:00
_backup Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
app Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
lib cc 2025-10-27 21:35:19 +01:00
Study cc- 2025-10-27 21:11:21 +01:00
tab-tracker-extension Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
test cc 2025-10-23 03:49:28 +02:00
web Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
.gitignore Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
.metadata Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
analysis_options.yaml Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
Dockerfile Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
nginx.conf Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
package.sh Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
pubspec.lock Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
pubspec.yaml Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
README.md cc 2025-10-26 19:10:23 +01:00
requirements.txt Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
setup-extension.sh Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00
setup.sh Initial commit: Browser Tab Manager Flutter app 2025-10-19 21:02:06 +02:00

Main Commands

flutter run -d chrome

flutter run -d web-server --web-port=8080

flutter devices

flutter run -d chrome --release

flutter run -d chrome --debug

flutter build web

flutter clean flutter pub get flutter run -d chrome

browser_tab_manager

Extension

https://drive.google.com/drive/folders/1pAniw90J-cWrH7nMVaxY0pl0TMG63AJA?usp=sharing

Add this folder in developer mode: Go To: chrome://extensions/

showDialog( context: context, builder: (context) => AlertDialog( title: Text('Manage Extensions'), content: Text( 'To manage your Chrome extensions:\n\n' '1. Open Chrome browser\n' '2. Type chrome://extensions/ in the address bar\n' '3. Or click the three dots menu > Extensions > Manage Extensions' ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text('OK'), ), ], ), );

Start Developer mode: In right corner. Load Unpacked: Add entire folder in left corner.

Start Extension in right corner

Getting Started

🧠 Browser Tab Manager - Complete Code Study Guide

📋 Table of Contents

  1. App Architecture Overview
  2. Entry Point - main.dart
  3. Data Layer - Models
  4. Service Layer
  5. UI Layer - Screens
  6. Component Layer - Widgets
  7. Utilities & Constants
  8. Data Flow & State Management
  9. Browser API Integration
  10. Extension Communication

🏗️ App Architecture Overview

┌─────────────────────────────────────────┐
│                main.dart                │
│           (App Entry Point)             │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│          TabManagerHome                 │
│        (Main Screen State)              │
└─────┬─────────────────────────────┬─────┘
      │                             │
┌─────▼─────┐                 ┌─────▼─────┐
│ Services  │                 │ Widgets   │
│ Layer     │                 │ Layer     │
└─────┬─────┘                 └─────┬─────┘
      │                             │
┌─────▼─────┐                 ┌─────▼─────┐
│ Models    │                 │ Utils &   │
│ Layer     │                 │ Constants │
└───────────┘                 └───────────┘

Key Concepts:

  • Separation of Concerns: Each layer has specific responsibilities
  • Unidirectional Data Flow: Data flows down, events flow up
  • State Management: Centralized in TabManagerHome using setState()
  • Service Communication: Browser APIs and Extension messaging

🚀 Entry Point - main.dart

void main() {
  runApp(const BrowserTabManagerApp());
}

WHAT HAPPENS HERE:

  1. main() is the entry point of every Dart/Flutter app
  2. runApp() tells Flutter to start the app with our root widget
  3. Creates the widget tree and starts the rendering engine
class BrowserTabManagerApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Browser Tab Manager',
      theme: ThemeData(...),
      home: const TabManagerHome(),
    );
  }
}

BREAKDOWN:

  • StatelessWidget: Never changes its appearance based on internal state
  • MaterialApp: Root widget that provides Material Design theming
  • theme & darkTheme: Define app-wide visual styling
  • home: The first screen users see (TabManagerHome)

📊 Data Layer - Models

TabData Model (models/tab_data.dart)

class TabData {
  String id;        // Unique identifier
  String title;     // Display name
  String url;       // Web address
  String favicon;   // Icon URL
  DateTime lastAccessed;  // When last used
  bool isPinned;    // Pinned status
  String type;      // 'tab', 'bookmark', or 'history'
  int? visitCount;  // Number of visits (nullable)
  String? folder;   // Bookmark folder (nullable)
}

PURPOSE:

  • Data Structure: Represents all types of browser items uniformly
  • Type Safety: Dart ensures correct data types
  • Nullable Fields: ? means the field can be null

Factory Constructor:

factory TabData.fromJson(Map<String, dynamic> json) => TabData(
  id: json['id'].toString(),
  title: json['title'] ?? 'Untitled',  // ?? means "if null, use default"
  // ... more fields
);

WHAT IT DOES:

  • Converts JSON data from browser APIs into TabData objects
  • Handles missing/null values gracefully with defaults
  • Standardizes different API response formats

🔧 Service Layer

BrowserApiService (services/browser_api_service.dart)

class BrowserApiService {
  Future<List<TabData>> getTabs() async {
    final result = await _callBrowserAPI('getTabs');
    // Convert raw data to TabData objects
  }
}

KEY CONCEPTS:

  • async/await: Handles asynchronous operations
  • Future<T>: Represents a value that will be available later
  • Abstraction: Hides complex browser API details

ExtensionService (services/extension_service.dart)

void setupListener() {
  html.window.onMessage.listen((event) => {
    // Handle messages from browser extension
  });
}

PURPOSE:

  • Communication Bridge: Between web app and browser extension
  • Event-Driven: Responds to messages from extension
  • Callback Pattern: Uses function pointers for responses

🎨 UI Layer - Screens

TabManagerHome (screens/tab_manager_home.dart)

This is the BRAIN of the application - it manages all state and coordinates everything.

State Variables:

class _TabManagerHomeState extends State<TabManagerHome> {
  List<TabData> allItems = [];        // ALL data from browser
  List<TabData> filteredItems = [];   // DISPLAYED data (after search/filter)
  bool isGridView = true;             // View mode toggle
  String sortBy = 'recent';           // Current sort method
  String filterType = 'all';          // Current filter
  bool isLoading = true;              // Loading spinner state
  bool extensionMode = false;         // Extension tracking mode
}

Key Methods:

initState() - Runs when widget is created:

@override
void initState() {
  super.initState();                    // Call parent setup
  _setupExtensionService();             // Start listening for extension
  _loadAllData();                       // Load browser data
  searchController.addListener(_filterItems);  // Watch search input
}

setState() - The magic that updates UI:

setState(() {
  allItems = newData;     // Change state
  _filterItems();         // Update filtered view
});
// Flutter automatically rebuilds UI after setState finishes

🧩 Component Layer - Widgets

ItemCard (widgets/item_card.dart)

STATELESS WIDGET - Displays data, doesn't manage state:

class ItemCard extends StatelessWidget {
  final TabData item;           // Data from parent
  final VoidCallback onTap;     // Function to call when tapped
  
  @override
  Widget build(BuildContext context) {
    return Card(
      child: InkWell(
        onTap: onTap,           // Call parent's function
        child: // ... UI layout
      ),
    );
  }
}

DATA FLOW:

  1. Parent passes data and callback functions
  2. Widget displays the data
  3. User interaction calls parent's functions
  4. Parent updates state and rebuilds widget with new data

SearchBar (widgets/search_bar.dart)

TextField(
  controller: controller,     // Links to parent's TextEditingController
  onChanged: (text) => {      // Calls parent when text changes
    // Parent handles the search logic
  },
)

🛠️ Utilities & Constants

Helpers (utils/helpers.dart)

static List<TabData> filterItems(
  List<TabData> items,
  String query,
  String filterType,
) {
  return items.where((item) => {
    // Filter logic here
  }).toList();
}

PURPOSE:

  • Pure Functions: Same input always produces same output
  • Reusable Logic: Can be used anywhere in the app
  • Testing: Easy to unit test

Constants (constants/app_constants.dart)

class AppConstants {
  static const Color primaryColor = Color(0xFF0175C2);
  static const String extensionSource = 'tab-tracker-extension';
}

BENEFITS:

  • Single Source of Truth: Change value in one place
  • Type Safety: Compile-time checking
  • Maintainability: Easy to update app-wide settings

🔄 Data Flow & State Management

Complete Data Flow Cycle:

1. User Action (tap, type, click)
       ↓
2. Widget calls parent function
       ↓
3. Parent updates state with setState()
       ↓
4. Flutter rebuilds widget tree
       ↓
5. UI reflects new state

Example: Search Flow

// 1. User types in search bar
SearchBar(onChanged: (text) => {
  // 2. SearchBar calls parent's function
  _filterItems();
});

// 3. Parent filters data and updates state
void _filterItems() {
  setState(() => {
    filteredItems = // ... filter logic
  });
  // 4. Flutter rebuilds UI with new filteredItems
}

🌐 Browser API Integration

How Browser APIs Work:

Future<String?> _callBrowserAPI(String method, [List<dynamic>? args]) async {
  // 1. Check if browser API exists
  if (!js_util.hasProperty(html.window, 'BrowserAPI')) {
    return null;  // Development mode
  }
  
  // 2. Get the API object from browser
  final browserAPI = js_util.getProperty(html.window, 'BrowserAPI');
  
  // 3. Call the specific method
  final result = await js_util.promiseToFuture(
    js_util.callMethod(function, 'call', [browserAPI, ...args])
  );
  
  return json.encode(result);  // 4. Return as JSON string
}

STEPS:

  1. Check Availability: Is the browser API injected?
  2. Get Reference: Access the API object
  3. Call Method: Execute with parameters
  4. Handle Response: Convert to usable format

📡 Extension Communication

Message Passing System:

// SENDING to extension:
html.window.postMessage({
  'source': 'tab-tracker-webapp',
  'action': 'startTracking'
}, '*');

// RECEIVING from extension:
html.window.onMessage.listen((event) => {
  final data = event.data;
  if (data['source'] == 'tab-tracker-extension') {
    _handleExtensionMessage(data);
  }
});

COMMUNICATION FLOW:

Web App ←→ Browser Window ←→ Extension

Message Types:

  • startTracking: Begin tab monitoring
  • stopTracking: Stop tab monitoring
  • updateTabs: Extension sends current tabs
  • getStatus: Request current state

🎯 Key Learning Points

1. State Management Pattern

  • State lives in parent components
  • Children receive data and callback functions
  • setState() triggers UI rebuilds

2. Async Programming

  • async/await for non-blocking operations
  • Future<T> represents eventual values
  • Error handling with try/catch

3. Widget Communication

  • Parent-to-child: Pass data via constructor
  • Child-to-parent: Pass callback functions
  • Sibling-to-sibling: Through common parent

4. Service Layer Benefits

  • Separates business logic from UI
  • Makes testing easier
  • Provides clean abstractions

5. Browser Integration

  • JavaScript interop for browser APIs
  • Message passing for extension communication
  • Graceful degradation for development mode

🔍 Next Steps for Deep Learning

  1. Trace a complete user action from UI tap to state update
  2. Follow data transformation from browser API to UI display
  3. Understand lifecycle methods and when they're called
  4. Practice modifying one small feature at a time
  5. Add logging to see the flow in action

This architecture provides a solid foundation for building complex, maintainable Flutter web applications! 🚀