source-code/
student-hub
Public
codeCodeinfoIssues 0call_splitPull Requestsplay_circleActions
student-hub/lib/screens/ai_assistant_screen.dart
text162 lines5.4 KB
import 'package:flutter/material.dart';
import '../services/ai_service.dart';
import '../widgets/chat_bubble.dart';

class AiAssistantScreen extends StatefulWidget {
  const AiAssistantScreen({super.key});

  @override
  State<AiAssistantScreen> createState() => _AiAssistantScreenState();
}

class _AiAssistantScreenState extends State<AiAssistantScreen> {
  final GeminiService _geminiService = GeminiService();
  final TextEditingController _promptController = TextEditingController();
  
  final List<Map<String, String>> _messages = [];
  bool _isLoading = false;

  // Menyimpan referensi model AI yang saat ini dipilih oleh pengguna
  String _selectedModel = 'gemini-2.5-flash';
  
  // Daftar koleksi model inferensi AI yang terintegrasi di dalam aplikasi
  final List<String> _availableModels = [
    'gemini-2.5-flash',
    'gemini-3.5-flash',
    'llama3',
    'openai/gpt-5',
    'openai/gpt-5-chat',
    'deepseek/deepseek-r1',
    'microsoft/phi-4'
  ];

  /// Mengirimkan pesan pengguna ke layanan AI dan memperbarui antarmuka dengan respons.
  void _sendMessage() async {
    if (_promptController.text.trim().isEmpty) return;

    final userText = _promptController.text;
    
    setState(() {
      _messages.add({"role": "user", "text": userText});
      _isLoading = true;
      _promptController.clear();
    });

    // Meneruskan teks instruksi pengguna dan model AI spesifik yang dipilih ke berkas layanan
    final aiResponse = await _geminiService.askGeminiWithContext(userText, _selectedModel);

    setState(() {
      _messages.add({"role": "ai", "text": aiResponse});
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Tanya AI"),
        backgroundColor: Colors.teal,
        foregroundColor: Colors.white,
        actions: [
          // Menu tarik-turun (Dropdown) yang berfungsi untuk melakukan transisi model bahasa AI
          DropdownButtonHideUnderline(
            child: DropdownButton<String>(
              value: _selectedModel,
              dropdownColor: Colors.teal[700],
              icon: const Icon(Icons.arrow_drop_down, color: Colors.white),
              style: const TextStyle(color: Colors.white, fontSize: 13, fontWeight: FontWeight.bold),
              items: _availableModels.map((String model) {
                // Memformat representasi string model bahasa agar lebih rapi secara visual
                String displayName = model;
                if (model.contains('/')) {
                  displayName = model.split('/').last;
                }
                displayName = displayName.replaceAll('gemini-', '').toUpperCase();
                if (displayName.startsWith('LLAMA')) {
                  displayName = 'LLAMA 3 (LOKAL)';
                }
                return DropdownMenuItem<String>(
                  value: model,
                  child: Text(displayName),
                );
              }).toList(),
              onChanged: (String? newValue) {
                if (newValue != null) {
                  setState(() {
                    _selectedModel = newValue;
                  });
                }
              },
            ),
          ),
          const SizedBox(width: 15),
        ],
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              padding: const EdgeInsets.all(16),
              itemCount: _messages.length,
              itemBuilder: (context, index) {
                final msg = _messages[index];
                final isUser = msg["role"] == "user";

                return ChatBubble(message: msg, isUser: isUser);
              },
            ),
          ),
          
          if (_isLoading)
            const Padding(
              padding: EdgeInsets.all(8.0),
              child: CircularProgressIndicator(),
            ),

          Container(
            padding: const EdgeInsets.all(12),
            decoration: BoxDecoration(
              color: Colors.white,
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.05),
                  blurRadius: 10,
                  offset: const Offset(0, -2),
                ),
              ],
            ),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _promptController,
                    decoration: InputDecoration(
                      hintText: "Tanya jadwal, tugas, materi, atau coding...",
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(25),
                        borderSide: BorderSide.none,
                      ),
                      filled: true,
                      fillColor: Colors.grey[100],
                      contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
                    ),
                    onSubmitted: (_) => _sendMessage(),
                  ),
                ),
                const SizedBox(width: 8),
                CircleAvatar(
                  backgroundColor: Colors.teal,
                  child: IconButton(
                    icon: const Icon(Icons.send, color: Colors.white),
                    onPressed: _isLoading ? null : _sendMessage,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

About

Student Hub UGM - Task & Schedule Tracker

FlutterDartSQLiteAIGeminiMobile App

Contributors

2