diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e0375b8..6507533 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,7 @@ + + + { + final TextEditingController searchController = TextEditingController(); final ScrollController _scrollController = ScrollController(); + bool showSearchbox = true; + RegExp regex = RegExp(""); @override void initState() { super.initState(); @@ -20,6 +26,14 @@ class _ChatPageState extends State { }); } + bool attachmentBoxShow = false; + void _showAttachmentBox() { + setState(() { + attachmentBoxShow = !attachmentBoxShow; // + }); + } + + TextEditingController _textEditingController = TextEditingController(); List messages = [ { "message": "Hola!", @@ -101,65 +115,296 @@ class _ChatPageState extends State { appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, centerTitle: false, - title: ListTile( - leading: CircleAvatar( - backgroundColor: Colors.white, - backgroundImage: AssetImage(widget.image), - ), - title: Text(widget.name), - subtitle: const Text("Online"), - trailing: SizedBox( - width: MediaQuery.of(context).size.width * 0.2, - child: const Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Icon(Icons.video_call), - Icon(Icons.call), - Icon(Icons.more_vert), - ], - ), - ), - ), + title: showSearchbox + ? ListTile( + leading: CircleAvatar( + backgroundColor: Colors.white, + backgroundImage: AssetImage(widget.image), + ), + title: Text(widget.name), + subtitle: const Text("Online"), + trailing: SizedBox( + width: MediaQuery.of(context).size.width * 0.3, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Icon(Icons.video_call), + Icon(Icons.call), + PopupMenuButton( + itemBuilder: (BuildContext context) => + >[ + PopupMenuItem( + value: "View Contacts", + child: Text("View Contacts"), + ), + PopupMenuItem( + value: "Media Links Docs", + child: Text("Media Links Docs"), + ), + PopupMenuItem( + value: "Search", + child: Text("Search"), + onTap: () { + setState(() { + showSearchbox = !showSearchbox; + FocusScope.of(context).unfocus(); + }); + }, + ), + PopupMenuItem( + value: "Mute Notification", + child: Text("Mute Notification"), + ), + PopupMenuItem( + value: "Disappearing message", + child: Text("Disappearing message"), + ), + PopupMenuItem( + value: "Wallpaper", + child: Text("Wallpaper"), + ), + PopupMenuItem( + value: "more >", + child: Text("more >"), + ), + ]) + ], + ), + ), + ) + : TextFormField( + controller: searchController, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + contentPadding: const EdgeInsets.all(10), + suffixIcon: IconButton( + icon: Icon(Icons.search), + onPressed: () { + setState(() { + regex = + RegExp(searchController.text, caseSensitive: false); + if (searchController.text.isEmpty || + searchController.text == " ") { + showSearchbox = !showSearchbox; + FocusScope.of(context).unfocus(); + } else { + for (var message in messages) { + if (regex.hasMatch(message["message"])) {} + } + } + showSearchbox = !showSearchbox; + FocusScope.of(context).unfocus(); + }); + }, + ), + hintText: "Search", + hintStyle: TextStyle( + color: Colors.grey, + ), + ), + onTapOutside: (event) => { + setState(() { + showSearchbox = !showSearchbox; + print(showSearchbox); + FocusScope.of(context).unfocus(); + }), + }, + ), ), body: Padding( padding: const EdgeInsets.all(8.0), - child: ListView.builder( - controller: _scrollController, - itemCount: messages.length, - itemBuilder: (context, index) { - int previous = index - 1 >= 0 ? index - 1 : 0; - int current = index; - return Padding( - padding: messages[previous]["sent"] == messages[current]["sent"] - ? const EdgeInsets.only(left: 8, right: 8, top: 4) - : const EdgeInsets.only(left: 8, right: 8, top: 8), - child: Align( - alignment: messages[index]["sent"] - ? Alignment.centerRight - : Alignment.centerLeft, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - color: messages[index]["sent"] - ? Colors.amber[200] - : Colors.blue[200], - ), - child: Padding( - padding: const EdgeInsets.all(10), - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width * 0.8, + child: GestureDetector( + onTap: () { + setState(() { + attachmentBoxShow = false; + FocusScope.of(context).unfocus(); + }); + }, + child: Column( + children: [ + Expanded( + child: ListView.builder( + controller: _scrollController, + itemCount: messages.length, + itemBuilder: (context, index) { + int previous = index - 1 >= 0 ? index - 1 : 0; + int current = index; + return Padding( + padding: messages[previous]["sent"] == + messages[current]["sent"] + ? const EdgeInsets.only(left: 8, right: 8, top: 4) + : const EdgeInsets.only(left: 8, right: 8, top: 8), + child: Align( + alignment: messages[index]["sent"] + ? Alignment.centerRight + : Alignment.centerLeft, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: messages[index]["sent"] + ? Colors.amber[200] + : Colors.blue[200], + ), + child: Padding( + padding: const EdgeInsets.all(10), + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: + MediaQuery.of(context).size.width * 0.8, + ), + child: Text( + messages[index]["message"], + style: TextStyle( + fontSize: 18, + ), + ), + ), + ), + ), ), - child: Text( - messages[index]["message"], - style: const TextStyle(fontSize: 18), + ); + }), + ), + Row( + children: [ + Expanded( + child: TextField( + keyboardType: TextInputType.text, + controller: _textEditingController, + decoration: InputDecoration( + border: OutlineInputBorder(), + suffixIcon: IconButton( + icon: Icon(Icons.attachment_sharp), + onPressed: _showAttachmentBox, ), + hintText: "Type a message", ), ), ), - ), - ); - }), + TextButton( + onPressed: () { + if (_textEditingController.text.isNotEmpty) { + setState(() { + messages.add({ + "message": _textEditingController.text, + "sent": true, + }); + _textEditingController.clear(); + }); + } + }, + child: const Icon(Icons.send)), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.mic, + color: Color.fromARGB(255, 144, 70, 205), + )) + ], + ), + attachmentBoxShow + ? Container( + padding: EdgeInsets.only(top: 25), + height: MediaQuery.of(context).size.width * 0.5, + decoration: BoxDecoration( + color: const Color.fromARGB(255, 37, 37, 37), + borderRadius: BorderRadius.circular(10), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(25.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + child: GestureDetector( + onTap: () => Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + StoragePermission())), + child: Icon( + Icons.photo, + color: Color.fromARGB(255, 66, 108, 117), + size: 30, + ), + ), + ), + SizedBox( + child: Icon( + Icons.camera, + color: Color.fromARGB(255, 66, 108, 117), + size: 30, + ), + ), + SizedBox( + child: GestureDetector( + onTap: () {}, + child: Icon( + Icons.location_pin, + color: Color.fromARGB(255, 66, 108, 117), + size: 30, + ), + ), + ), + SizedBox( + child: Icon( + Icons.contact_phone, + color: Color.fromARGB(255, 66, 108, 117), + size: 30, + ), + ) + ], + ), + ), + Padding( + padding: const EdgeInsets.all(25.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + child: Icon( + Icons.document_scanner, + color: Color.fromARGB(255, 66, 108, 117), + size: 30, + ), + ), + SizedBox( + child: Icon( + Icons.audio_file, + color: Color.fromARGB(255, 66, 108, 117), + size: 30, + ), + ), + SizedBox( + child: Icon( + Icons.poll, + color: Color.fromARGB(255, 66, 108, 117), + size: 30, + ), + ), + SizedBox( + child: Icon( + Icons.payment, + color: Color.fromARGB(255, 66, 108, 117), + size: 30, + ), + ) + ], + ), + ), + ], + ), + ) + : SizedBox( + height: 0, + ) + ], + ), + ), ), ); } diff --git a/lib/screens/permission.dart b/lib/screens/permission.dart new file mode 100644 index 0000000..2a18307 --- /dev/null +++ b/lib/screens/permission.dart @@ -0,0 +1,58 @@ +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class StoragePermission extends StatefulWidget { + const StoragePermission({super.key}); + + @override + State createState() => _StoragePermissionState(); +} + +Future _requestPermission(Permission permission) async { + AndroidDeviceInfo build = await DeviceInfoPlugin().androidInfo; + if (build.version.sdkInt >= 30) { + var re = await Permission.manageExternalStorage.request(); + if (re.isGranted) { + return true; + } else { + return false; + } + } else { + if (await permission.isGranted) { + return true; + } else { + var result = await permission.request(); + if (result.isGranted) { + return true; + } else { + return false; + } + } + } +} + +class _StoragePermissionState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.blue, + title: Text( + 'Storage Permission in Android(11,12 and 13)', + style: TextStyle(fontSize: 16), + )), + body: Center( + child: ElevatedButton( + onPressed: () async { + if (await _requestPermission(Permission.storage) == true) { + print("Permission is granted"); + } else { + print("permission is not granted"); + } + }, + child: Text('click'), + )), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index f5b0af9..1b5dff7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,6 +49,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91 + url: "https://pub.dev" + source: hosted + version: "10.1.0" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" + source: hosted + version: "7.0.0" fake_async: dependency: transitive description: @@ -57,6 +73,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" flutter: dependency: "direct main" description: flutter @@ -75,6 +107,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" leak_tracker: dependency: transitive description: @@ -139,6 +176,62 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb" + url: "https://pub.dev" + source: hosted + version: "11.3.1" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: "8bb852cd759488893805c3161d0b2b5db55db52f773dbb014420b304055ba2c5" + url: "https://pub.dev" + source: hosted + version: "12.0.6" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662 + url: "https://pub.dev" + source: hosted + version: "9.4.4" + permission_handler_html: + dependency: transitive + description: + name: permission_handler_html + sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d" + url: "https://pub.dev" + source: hosted + version: "0.1.1" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20" + url: "https://pub.dev" + source: hosted + version: "4.2.1" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" sky_engine: dependency: transitive description: flutter @@ -208,5 +301,30 @@ packages: url: "https://pub.dev" source: hosted version: "13.0.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + win32: + dependency: transitive + description: + name: win32 + sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" + url: "https://pub.dev" + source: hosted + version: "5.5.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb" + url: "https://pub.dev" + source: hosted + version: "1.1.3" sdks: dart: ">=3.3.0 <4.0.0" + flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index f83b8c5..89c9cf0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,8 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.6 + permission_handler: ^11.3.1 + device_info_plus: ^10.1.0 dev_dependencies: flutter_test: