diff --git a/android/app/build.gradle b/android/app/build.gradle index f360f667e5..cf682d6667 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -45,6 +45,7 @@ android { versionCode localProperties.getProperty('flutter.versionCode').toInteger() versionName localProperties.getProperty('flutter.versionName') } + ndkVersion "26.3.11579264" signingConfigs { release { @@ -96,4 +97,4 @@ flutter { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" -} +} \ No newline at end of file diff --git a/assets/icons/ZulipIcons.ttf b/assets/icons/ZulipIcons.ttf index 57a301f2e8..cdde9f71e7 100644 Binary files a/assets/icons/ZulipIcons.ttf and b/assets/icons/ZulipIcons.ttf differ diff --git a/assets/icons/inbox_done.svg b/assets/icons/inbox_done.svg new file mode 100644 index 0000000000..ac164358de --- /dev/null +++ b/assets/icons/inbox_done.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/lib/widgets/icons.dart b/lib/widgets/icons.dart index ba21bec42f..6dde45635f 100644 --- a/lib/widgets/icons.dart +++ b/lib/widgets/icons.dart @@ -78,56 +78,59 @@ abstract final class ZulipIcons { /// The Zulip custom icon "inbox". static const IconData inbox = IconData(0xf112, fontFamily: "Zulip Icons"); + /// The Zulip custom icon "inbox_done". + static const IconData inbox_done = IconData(0xf113, fontFamily: "Zulip Icons"); + /// The Zulip custom icon "info". - static const IconData info = IconData(0xf113, fontFamily: "Zulip Icons"); + static const IconData info = IconData(0xf114, fontFamily: "Zulip Icons"); /// The Zulip custom icon "inherit". - static const IconData inherit = IconData(0xf114, fontFamily: "Zulip Icons"); + static const IconData inherit = IconData(0xf115, fontFamily: "Zulip Icons"); /// The Zulip custom icon "language". - static const IconData language = IconData(0xf115, fontFamily: "Zulip Icons"); + static const IconData language = IconData(0xf116, fontFamily: "Zulip Icons"); /// The Zulip custom icon "lock". - static const IconData lock = IconData(0xf116, fontFamily: "Zulip Icons"); + static const IconData lock = IconData(0xf117, fontFamily: "Zulip Icons"); /// The Zulip custom icon "menu". - static const IconData menu = IconData(0xf117, fontFamily: "Zulip Icons"); + static const IconData menu = IconData(0xf118, fontFamily: "Zulip Icons"); /// The Zulip custom icon "message_feed". - static const IconData message_feed = IconData(0xf118, fontFamily: "Zulip Icons"); + static const IconData message_feed = IconData(0xf119, fontFamily: "Zulip Icons"); /// The Zulip custom icon "mute". - static const IconData mute = IconData(0xf119, fontFamily: "Zulip Icons"); + static const IconData mute = IconData(0xf11a, fontFamily: "Zulip Icons"); /// The Zulip custom icon "read_receipts". - static const IconData read_receipts = IconData(0xf11a, fontFamily: "Zulip Icons"); + static const IconData read_receipts = IconData(0xf11b, fontFamily: "Zulip Icons"); /// The Zulip custom icon "send". - static const IconData send = IconData(0xf11b, fontFamily: "Zulip Icons"); + static const IconData send = IconData(0xf11c, fontFamily: "Zulip Icons"); /// The Zulip custom icon "share". - static const IconData share = IconData(0xf11c, fontFamily: "Zulip Icons"); + static const IconData share = IconData(0xf11d, fontFamily: "Zulip Icons"); /// The Zulip custom icon "share_ios". - static const IconData share_ios = IconData(0xf11d, fontFamily: "Zulip Icons"); + static const IconData share_ios = IconData(0xf11e, fontFamily: "Zulip Icons"); /// The Zulip custom icon "smile". - static const IconData smile = IconData(0xf11e, fontFamily: "Zulip Icons"); + static const IconData smile = IconData(0xf11f, fontFamily: "Zulip Icons"); /// The Zulip custom icon "star". - static const IconData star = IconData(0xf11f, fontFamily: "Zulip Icons"); + static const IconData star = IconData(0xf120, fontFamily: "Zulip Icons"); /// The Zulip custom icon "star_filled". - static const IconData star_filled = IconData(0xf120, fontFamily: "Zulip Icons"); + static const IconData star_filled = IconData(0xf121, fontFamily: "Zulip Icons"); /// The Zulip custom icon "topic". - static const IconData topic = IconData(0xf121, fontFamily: "Zulip Icons"); + static const IconData topic = IconData(0xf122, fontFamily: "Zulip Icons"); /// The Zulip custom icon "unmute". - static const IconData unmute = IconData(0xf122, fontFamily: "Zulip Icons"); + static const IconData unmute = IconData(0xf123, fontFamily: "Zulip Icons"); /// The Zulip custom icon "user". - static const IconData user = IconData(0xf123, fontFamily: "Zulip Icons"); + static const IconData user = IconData(0xf124, fontFamily: "Zulip Icons"); // END GENERATED ICON DATA } diff --git a/lib/widgets/inbox.dart b/lib/widgets/inbox.dart index 04d5246195..4570349924 100644 --- a/lib/widgets/inbox.dart +++ b/lib/widgets/inbox.dart @@ -1,3 +1,4 @@ +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import '../api/model/model.dart'; @@ -34,6 +35,7 @@ class _InboxPageState extends State with PerAccountStoreAwareStat Set get collapsedStreamIds => _collapsedStreamIds; final Set _collapsedStreamIds = {}; + final sections = <_InboxSectionData>[]; void collapseStream(int streamId) { setState(() { _collapsedStreamIds.add(streamId); @@ -153,6 +155,70 @@ class _InboxPageState extends State with PerAccountStoreAwareStat }); sections.add(_StreamSectionData(streamId, countInStream, streamHasMention, topicItems)); } + if (sections.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, // Centered vertically + crossAxisAlignment: CrossAxisAlignment.center, // Centered horizontally + children: [ + const SizedBox( + height: 50, + ), + Icon( + ZulipIcons.inbox_done, + color: Colors.grey[600], // Lighter gray for the icon + size: 80, + ), + const SizedBox(height: 20), + Text( + "There are no unread messages in your Inbox.", + textAlign: TextAlign.center, + style: TextStyle( + color:Colors.grey[600], // Light gray for the main text + fontSize: 17, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 10), + RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: "You might want to subscribe to more ", + style: TextStyle( + color: Colors.grey[600], // Light gray for regular text + fontSize: 17, + ), + children: [ + TextSpan( + text: "channels", + style: const TextStyle( + color: Color(0xFF1E88E5), // Light blue for link + fontSize: 17, + fontWeight: FontWeight.w600, + decoration: TextDecoration.underline, + ), + recognizer: TapGestureRecognizer() + ..onTap = () { + // Handle "channels" click + // print("Channels clicked"); + }, + ), + TextSpan( + text: ".", + style: TextStyle( + color:Colors.grey[600] , // Light blue for link + fontSize: 17, + ), + + ), + ], + ), + ), + ], + ), + ); + } + return SafeArea( // Don't pad the bottom here; we want the list content to do that. diff --git a/pubspec.lock b/pubspec.lock index e98a6a5339..cb4f2015cc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -711,10 +711,10 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: @@ -1044,18 +1044,18 @@ packages: dependency: "direct dev" description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "4ac0537115a24d772c408a2520ecd0abb99bca2ea9c4e634ccbdbfae64fe17ec" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" stream_transform: dependency: transitive description: @@ -1068,10 +1068,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "0bd04f5bb74fcd6ff0606a888a30e917af9bd52820b178eaa464beb11dca84b6" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" sync_http: dependency: transitive description: @@ -1084,10 +1084,10 @@ packages: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test: dependency: "direct dev" description: diff --git a/test/widgets/autocomplete_test.dart b/test/widgets/autocomplete_test.dart index d6aab7e1cb..9aa638b7ab 100644 --- a/test/widgets/autocomplete_test.dart +++ b/test/widgets/autocomplete_test.dart @@ -330,6 +330,10 @@ void main() { text: 'some', selection: TextSelection(baseOffset: 1, extentOffset: 3))); await tester.pump(); + // Add an extra pump to account for any potential frame delays introduced + // by the post frame callback in RawAutocomplete's implementation. + await tester.pump(); + check(controller.value) ..text.equals('some') ..selection.equals(