flint_dart 1.0.0+8 copy "flint_dart: ^1.0.0+8" to clipboard
flint_dart: ^1.0.0+8 copied to clipboard

A modern, expressive, and extensible server-side framework by Eulogia Technologies.

example/lib/main.dart

import 'dart:convert';

import 'package:flint_dart/flint_dart.dart';
import 'package:sample/src/middlewares/auth_middleware.dart';
import 'package:sample/src/routes/auth_routes.dart';
import 'package:sample/src/routes/user_routes.dart';

void main() {
  final app = Flint(
    withDefaultMiddleware: true,
    enableSwaggerDocs: true,
    autoConnectDb: true,
    viewPath: 'lib/src/views',
  );

  app.use(LoggerMiddleware());

  app.get('/', (req, res) async {
    return res.view("test_ws", data: {"name": "ademola", "age": 12});
  });

  app.get('/login', (req, res) async {
    return res.oAuthRedirect("google", callback: "/api/auth/google/callback");
  });
  app.mount("/users", registerUserRoutes);

  app.get('/profile', (req, res) async {
    return res.json({'msg': 'This is a protected route'});
  }).useMiddleware(AuthMiddleware());

  // Store active users and rooms
  final Map<String, String> userNames = {};
  final Map<String, Set<String>> userRooms = {};

  app.websocket('/chat', (socket, params) {
    print('πŸ‘‹ Client connected: ${socket.id}');

    // Assign a random username
    final userName = 'User${socket.id.substring(0, 6)}';
    userNames[socket.id] = userName;
    userRooms[socket.id] = {'general'};

    // Send connection confirmation
    socket.emit('connected', {
      'userId': socket.id,
      'userName': userName,
      'message': 'Successfully connected to chat server',
      'timestamp': DateTime.now().toIso8601String()
    });

    // Join general room by default
    socket.join('general');

    // Broadcast user joined to general chat
    socket.emitToRoom('general', 'user_joined', {
      'userId': socket.id,
      'userName': userName,
      'timestamp': DateTime.now().toIso8601String(),
      'onlineUsers': userRooms.length
    });

    // Handle incoming messages - BOTH raw text and JSON
    socket.onMessage((data) {
      print('πŸ“¨ Received from $userName: $data (type: ${data.runtimeType})');

      // Try to parse as JSON first
      if (data is String) {
        try {
          final parsed = json.decode(data);
          if (parsed is Map<String, dynamic>) {
            _handleJsonMessage(socket, userName, parsed);
            return;
          }
        } catch (e) {
          // If not JSON, treat as raw text message
          print('πŸ“ Treating as raw text message');
          _handleRawMessage(socket, userName, data);
          return;
        }
      }

      // Handle other data types
      _handleRawMessage(socket, userName, data.toString());
    });

    // Handle typing events
    socket.on('typing_start', (data) {
      final room = data is Map ? data['room'] ?? 'general' : 'general';
      socket.emitToRoom(room, 'user_typing',
          {'userId': socket.id, 'userName': userName, 'isTyping': true});
    });

    socket.on('typing_stop', (data) {
      final room = data is Map ? data['room'] ?? 'general' : 'general';
      socket.emitToRoom(room, 'user_typing',
          {'userId': socket.id, 'userName': userName, 'isTyping': false});
    });

    // Handle joining specific rooms
    socket.on('join_room', (data) {
      if (data is String || (data is Map && data['room'] is String)) {
        final roomName = data is String ? data : data['room'] as String;

        // Leave previous rooms (except general)
        socket.rooms.where((room) => room != 'general').forEach((room) {
          socket.leave(room);
          userRooms[socket.id]?.remove(room);
        });

        // Join new room
        socket.join(roomName);
        userRooms[socket.id]?.add(roomName);

        // Notify user
        socket.emit('room_joined', {
          'room': roomName,
          'message': 'Joined room: $roomName',
          'usersInRoom': userRooms[socket.id]?.length ?? 0
        });

        // Notify room
        socket.emitToRoom(roomName, 'user_joined_room', {
          'userId': socket.id,
          'userName': userName,
          'room': roomName,
          'timestamp': DateTime.now().toIso8601String()
        });

        print('πŸšͺ $userName joined room: $roomName');
      }
    });

    // Handle user name changes
    socket.on('update_username', (data) {
      if (data is String || (data is Map && data['username'] is String)) {
        final newName = data is String ? data : data['username'] as String;
        final oldName = userNames[socket.id];
        userNames[socket.id] = newName;

        // Broadcast name change
        socket.emitToRoom('general', 'username_changed', {
          'userId': socket.id,
          'oldName': oldName,
          'newName': newName,
          'timestamp': DateTime.now().toIso8601String()
        });

        socket.emit(
            'username_updated', {'newName': newName, 'status': 'success'});

        print('πŸ“ $oldName changed name to $newName');
      }
    });

    // Handle disconnection
    socket.onClose(() {
      print('❌ $userName disconnected: ${socket.id}');

      // Remove from tracking
      userNames.remove(socket.id);
      userRooms.remove(socket.id);

      // Broadcast user left to all rooms
      for (var room in socket.rooms) {
        socket.emitToRoom(room, 'user_left', {
          'userId': socket.id,
          'userName': userName,
          'timestamp': DateTime.now().toIso8601String(),
          'onlineUsers': userRooms.length
        });
      }
    });

    // Handle errors
    // socket.onError((error) {
    //   print('❌ WebSocket error for $userName: $error');
    //   socket.emit('error', {
    //     'message': 'Connection error: $error',
    //     'timestamp': DateTime.now().toIso8601String()
    //   });
    // });

    // Send welcome event
    socket.emit('welcome', {
      'message': 'Welcome to the chat!',
      'id': socket.id,
      'userName': userName
    });
  });

  // REST API for chat history (optional)
  app.get('/api/chat/history', (req, res) async {
    return res.json({
      'messages': [
        {
          'id': '1',
          'userName': 'System',
          'message': 'Welcome to the chat!',
          'timestamp': DateTime.now().toIso8601String()
        }
      ]
    });
  });

  app.mount("/auth", authRoutes);
  app.listen(3000);
}

// Handle JSON messages from Flutter app
void _handleJsonMessage(
    FlintWebSocket socket, String userName, Map<String, dynamic> data) {
  final event = data['event'];
  final eventData = data['data'];

  print('🎯 JSON Event: $event from $userName');

  switch (event) {
    case 'send_message':
      final message =
          eventData is Map ? eventData['message'] : eventData.toString();
      final room =
          eventData is Map ? eventData['room'] ?? 'general' : 'general';

      _broadcastMessage(socket, userName, message, room);
      break;

    case 'typing_start':
    case 'typing_stop':
    case 'join_room':
    case 'update_username':
      // These are handled by specific event listeners above
      break;

    default:
      print('❓ Unknown JSON event: $event');
  }
}

// Handle raw text messages from web page
void _handleRawMessage(FlintWebSocket socket, String userName, String message) {
  print('πŸ“ Raw message from $userName: $message');
  _broadcastMessage(socket, userName, message, 'general');
}

// Broadcast message to room
void _broadcastMessage(
    FlintWebSocket socket, String userName, String message, String room) {
  final messageData = {
    'id': DateTime.now().millisecondsSinceEpoch.toString(),
    'userId': socket.id,
    'userName': userName,
    'message': message,
    'timestamp': DateTime.now().toIso8601String(),
    'room': room
  };

  // Broadcast to room as JSON event - MAKE SURE IT'S PROPERLY FORMATTED
  socket.emitToRoom(room, 'new_message', messageData);

  print('πŸ“€ Broadcast message from $userName to room $room: $message');
}
7
likes
150
points
14
downloads

Publisher

verified publisherflintdart.eulogia.net

Weekly Downloads

A modern, expressive, and extensible server-side framework by Eulogia Technologies.

Homepage
Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

bcrypt, crypto, dart_jsonwebtoken, mailer, mime, mysql_dart, package_config, path, postgres, uuid

More

Packages that depend on flint_dart