import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_chat_ui/flutter_chat_ui.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'package:file_picker/file_picker.dart'; import 'package:http/http.dart' as http; import 'package:muse_nepu_course/home.dart'; import 'package:uuid/uuid.dart'; import 'package:path_provider/path_provider.dart'; import 'package:mime/mime.dart'; import 'package:flutter/services.dart' show rootBundle; import 'dart:convert'; import 'dart:io'; import 'package:image_picker/image_picker.dart';

class chat_gpt extends StatefulWidget { @override _chat_gptState createState() => _chat_gptState(); }

class _chat_gptState extends State<chat_gpt> { List<types.Message> _messages = []; final _user = const types.User( id: '82091008-a484-4a89-ae75-a22bf8d6f3ac', ); var _filteredStringList = []; var _stringList = []; //从assets/prompts.json中读取数据,并转换为List<Map<String, String>> void loadprompts() async { String prompt = await rootBundle.loadString('assets/prompts.json'); _stringList = json.decode(prompt); _filteredStringList = List.from(_stringList); }

int _selectedIndex = -1; @override void initState() { super.initState(); _loadMessages(); }

void onSearch(String keyword) { SchedulerBinding.instance!.addPostFrameCallback(() { setState(() { _filteredStringList = _stringList.where((item) { return item['act']!.contains(keyword) || item['prompt']!.contains(keyword); }).toList(); }); }); }

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Chat with GPT'), //加入返回按鈕 leading: IconButton( icon: Icon(Icons.arrow_back), onPressed: () { //跳转到成绩页面 Navigator.push(context, MaterialPageRoute(builder: (context) { return HomePage(); })); }, ), actions: [ IconButton( icon: Icon(Icons.settings), onPressed: () { showDialog( context: context, builder: (context) { return Scaffold( appBar: AppBar( title: Text('自动注入'), actions: [ IconButton( icon: const Icon(Icons.search), onPressed: () { showSearch( context: context, delegate: _SearchBarDelegate( onSearch: _onSearch)); }, ), ], ), body: ListView.builder( itemCount: _filteredStringList.length, itemBuilder: (BuildContext context, int index) { String act = _filteredStringList[index]['act']!; String prompt = _filteredStringList[index]['prompt']!; return RadioListTile( title: Text('行为: $act'), subtitle: Text('语句: $prompt'), value: index, groupValue: _selectedIndex, onChanged: (int? value) { setState(() { _selectedIndex = value!; }); }, ); }, )); }); }, ), ], ), body: Chat( messages: _messages, onAttachmentPressed: _handleAttachmentPressed, onMessageTap: _handleMessageTap, onPreviewDataFetched: _handlePreviewDataFetched, onSendPressed: _handleSendPressed, showUserAvatars: true, showUserNames: true, user: _user, ), ); }

void _addMessage(types.Message message) { setState(() { _messages.insert(0, message); }); }

void _handleAttachmentPressed() { showModalBottomSheet( context: context, builder: (BuildContext context) => SafeArea( child: SizedBox( height: 144, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ TextButton( onPressed: () { Navigator.pop(context); _handleImageSelection(); }, child: const Align( alignment: AlignmentDirectional.centerStart, child: Text('Photo'), ), ), TextButton( onPressed: () { Navigator.pop(context); _handleFileSelection(); }, child: const Align( alignment: AlignmentDirectional.centerStart, child: Text('File'), ), ), TextButton( onPressed: () => Navigator.pop(context), child: const Align( alignment: AlignmentDirectional.centerStart, child: Text('Cancel'), ), ), ], ), ), ), ); }

void _handleFileSelection() async { final result = await FilePicker.platform.pickFiles( type: FileType.any, );

if (result != null && result.files.single.path != null) {
  final message = types.FileMessage(
    author: _user,
    createdAt: DateTime.now().millisecondsSinceEpoch,
    id: const Uuid().v4(),
    mimeType: lookupMimeType(result.files.single.path!),
    name: result.files.single.name,
    size: result.files.single.size,
    uri: result.files.single.path!,
  );

  _addMessage(message);
}

}

void _handleImageSelection() async { final result = await ImagePicker().pickImage( imageQuality: 70, maxWidth: 1440, source: ImageSource.gallery, );

if (result != null) {
  final bytes = await result.readAsBytes();
  final image = await decodeImageFromList(bytes);

  final message = types.ImageMessage(
    author: _user,
    createdAt: DateTime.now().millisecondsSinceEpoch,
    height: image.height.toDouble(),
    id: const Uuid().v4(),
    name: result.name,
    size: bytes.length,
    uri: result.path,
    width: image.width.toDouble(),
  );

  _addMessage(message);
}

}

void _handleMessageTap(BuildContext _, types.Message message) async { if (message is types.FileMessage) { var localPath = message.uri;

  if (message.uri.startsWith('http')) {
    try {
      final index = _messages.indexWhere((element) => element.id == message.id);
      final updatedMessage = (_messages[index] as types.FileMessage).copyWith(
        isLoading: true,
      );

      setState(() {
        _messages[index] = updatedMessage;
      });

      final client = http.Client();
      final request = await client.get(Uri.parse(message.uri));
      final bytes = request.bodyBytes;
      final documentsDir = (await getApplicationDocumentsDirectory()).path;
      localPath = '$documentsDir/${message.name}';

      if (!File(localPath).existsSync()) {
        final file = File(localPath);
        await file.writeAsBytes(bytes);
      }
    } finally {
      final index = _messages.indexWhere((element) => element.id == message.id);
      final updatedMessage = (_messages[index] as types.FileMessage).copyWith(
        isLoading: null,
      );

      setState(() {
        _messages[index] = updatedMessage;
      });
    }
  }
}

}

void _handlePreviewDataFetched( types.TextMessage message, types.PreviewData previewData, ) { final index = _messages.indexWhere((element) => element.id == message.id); final updatedMessage = (_messages[index] as types.TextMessage).copyWith( previewData: previewData, );

setState(() {
  _messages[index] = updatedMessage;
});

}

void _handleSendPressed(types.PartialText message) { final textMessage = types.TextMessage( author: _user, createdAt: DateTime.now().millisecondsSinceEpoch, id: const Uuid().v4(), text: message.text, );

_addMessage(textMessage);
print(message.text);
//打印最近20条消息
print(_messages.sublist(0, 20));

}

void _loadMessages() async { final response = await rootBundle.loadString('assets/messages.json'); final messages = (jsonDecode(response) as List) .map((e) => types.Message.fromJson(e as Map<String, dynamic>)) .toList();

setState(() {
  _messages = messages;
});

} }

class _SearchBarDelegate extends SearchDelegate { final Function(String) onSearch;

_SearchBarDelegate({required this.onSearch});

@override List buildActions(BuildContext context) { return [ IconButton( icon: const Icon(Icons.clear), onPressed: () { query = ''; }, ), ]; }

@override Widget buildLeading(BuildContext context) { return IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { close(context, ''); }, ); }

@override Widget buildResults(BuildContext context) { onSearch(query); return const SizedBox.shrink(); }

@override Widget buildSuggestions(BuildContext context) { return Dialog( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: MainAxisSize.min, children: [ TextField( onChanged: (value) { onSearch(value); }, decoration: InputDecoration( hintText: 'Search', suffixIcon: Icon(Icons.search), ), ), Expanded( child: ListView.builder( itemCount: _filteredStringList.length, itemBuilder: (context, index) { String act = _filteredStringList[index]['act']!; String prompt = _filteredStringList[index]['prompt']!; return RadioListTile( title: Text('行为: $act'), subtitle: Text('语句: $prompt'), value: index, groupValue: _selectedIndex, onChanged: (value) { setState(() { _selectedIndex = value!; }); }, ); }, ), ), FlatButton( onPressed: () { Navigator.of(context).pop(_filteredStringList[_selectedIndex]); }, child: Text('OK'), ), ], ), ); } }

Flutter Chat with GPT: Real-Time Chat, File Sharing, and More

原文地址: https://www.cveoy.top/t/topic/lQr9 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录