Merge pull request #87 from GetStream/chore/update-package-lints
chore: update package lints and apply fixes
This commit is contained in:
@@ -5,8 +5,6 @@ import 'package:imessage/utils.dart';
|
||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'
|
||||
show Channel;
|
||||
|
||||
import 'utils.dart';
|
||||
|
||||
class ChannelPreview extends StatelessWidget {
|
||||
final VoidCallback onTap;
|
||||
final Channel channel;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at
|
||||
# https://dart-lang.github.io/linter/lints/index.html.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
@@ -45,12 +45,14 @@ StreamChatClient buildStreamChatClient(
|
||||
)..chatPersistenceClient = chatPersistentClient;
|
||||
}
|
||||
|
||||
class MyApp extends StatefulWidget {
|
||||
class StreamChatSampleApp extends StatefulWidget {
|
||||
const StreamChatSampleApp({super.key});
|
||||
|
||||
@override
|
||||
_MyAppState createState() => _MyAppState();
|
||||
State<StreamChatSampleApp> createState() => _StreamChatSampleAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp>
|
||||
class _StreamChatSampleAppState extends State<StreamChatSampleApp>
|
||||
with SplashScreenStateMixin, TickerProviderStateMixin {
|
||||
InitData? _initData;
|
||||
|
||||
@@ -58,7 +60,7 @@ class _MyAppState extends State<MyApp>
|
||||
String? apiKey, userId, token;
|
||||
|
||||
if (!kIsWeb) {
|
||||
final secureStorage = FlutterSecureStorage();
|
||||
const secureStorage = FlutterSecureStorage();
|
||||
apiKey = await secureStorage.read(key: kStreamApiKey);
|
||||
userId = await secureStorage.read(key: kStreamUserId);
|
||||
token = await secureStorage.read(key: kStreamToken);
|
||||
@@ -95,7 +97,7 @@ class _MyAppState extends State<MyApp>
|
||||
forwardAnimations();
|
||||
});
|
||||
} else {
|
||||
Future.delayed(Duration(milliseconds: 1500)).then((value) {
|
||||
Future.delayed(const Duration(milliseconds: 1500)).then((value) {
|
||||
forwardAnimations();
|
||||
});
|
||||
}
|
||||
@@ -157,7 +159,7 @@ class _MyAppState extends State<MyApp>
|
||||
}
|
||||
return [
|
||||
AppRoutes.generateRoute(
|
||||
RouteSettings(
|
||||
const RouteSettings(
|
||||
name: Routes.CHOOSE_USER,
|
||||
),
|
||||
)!
|
||||
|
||||
@@ -19,7 +19,7 @@ void main() async {
|
||||
}
|
||||
};
|
||||
|
||||
Future<void> _reportError(dynamic error, StackTrace stackTrace) async {
|
||||
Future<void> reportError(dynamic error, StackTrace stackTrace) async {
|
||||
// Print the exception to the console.
|
||||
if (kDebugMode) {
|
||||
// Print the full stacktrace in debug mode.
|
||||
@@ -36,8 +36,8 @@ void main() async {
|
||||
await SentryFlutter.init(
|
||||
(options) => options.dsn = sentryDsn,
|
||||
);
|
||||
runApp(MyApp());
|
||||
runApp(const StreamChatSampleApp());
|
||||
},
|
||||
_reportError,
|
||||
reportError,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,10 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'choose_user_page.dart';
|
||||
|
||||
class AdvancedOptionsPage extends StatefulWidget {
|
||||
const AdvancedOptionsPage({super.key});
|
||||
|
||||
@override
|
||||
_AdvancedOptionsPageState createState() => _AdvancedOptionsPageState();
|
||||
State<AdvancedOptionsPage> createState() => _AdvancedOptionsPageState();
|
||||
}
|
||||
|
||||
class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
@@ -88,7 +90,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
.textHighEmphasis,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
errorStyle: TextStyle(height: 0, fontSize: 0),
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
labelStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -110,7 +112,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
const SizedBox(height: 8),
|
||||
TextFormField(
|
||||
controller: _userIdController,
|
||||
onChanged: (_) {
|
||||
@@ -139,7 +141,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: TextStyle(height: 0, fontSize: 0),
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
labelStyle: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
@@ -160,7 +162,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
: AppLocalizations.of(context).userId,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
const SizedBox(height: 8),
|
||||
TextFormField(
|
||||
onChanged: (_) {
|
||||
if (_userTokenError != null) {
|
||||
@@ -189,7 +191,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: TextStyle(height: 0, fontSize: 0),
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
labelStyle: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
@@ -210,7 +212,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
: AppLocalizations.of(context).userToken,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
const SizedBox(height: 8),
|
||||
TextFormField(
|
||||
controller: _usernameController,
|
||||
textInputAction: TextInputAction.done,
|
||||
@@ -231,7 +233,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
labelText: AppLocalizations.of(context).usernameOptional,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all<Color>(
|
||||
@@ -286,7 +288,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
),
|
||||
height: 100,
|
||||
width: 100,
|
||||
child: Center(
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
@@ -294,6 +296,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
);
|
||||
|
||||
final client = buildStreamChatClient(apiKey);
|
||||
final navigator = Navigator.of(context);
|
||||
|
||||
try {
|
||||
await client.connectUser(
|
||||
@@ -303,7 +306,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
userToken,
|
||||
);
|
||||
|
||||
final secureStorage = FlutterSecureStorage();
|
||||
const secureStorage = FlutterSecureStorage();
|
||||
secureStorage.write(
|
||||
key: kStreamApiKey,
|
||||
value: apiKey,
|
||||
@@ -330,8 +333,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
return;
|
||||
}
|
||||
loading = false;
|
||||
await Navigator.pushNamedAndRemoveUntil(
|
||||
context,
|
||||
await navigator.pushNamedAndRemoveUntil(
|
||||
Routes.HOME,
|
||||
ModalRoute.withName(Routes.HOME),
|
||||
arguments: HomePageArgs(client),
|
||||
@@ -339,7 +341,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
|
||||
}
|
||||
},
|
||||
),
|
||||
StreamVersion(),
|
||||
const StreamVersion(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -27,10 +27,10 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
|
||||
),
|
||||
messageFilter: Filter.in_(
|
||||
'attachments.type',
|
||||
['file'],
|
||||
const ['file'],
|
||||
),
|
||||
sort: [
|
||||
SortOption(
|
||||
const SortOption(
|
||||
'created_at',
|
||||
direction: SortOption.ASC,
|
||||
),
|
||||
@@ -52,7 +52,7 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
|
||||
fontSize: 16.0,
|
||||
),
|
||||
),
|
||||
leading: StreamBackButton(),
|
||||
leading: const StreamBackButton(),
|
||||
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
|
||||
),
|
||||
body: ValueListenableBuilder(
|
||||
@@ -73,7 +73,7 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
|
||||
size: 136.0,
|
||||
color: StreamChatTheme.of(context).colorTheme.disabled,
|
||||
),
|
||||
SizedBox(height: 16.0),
|
||||
const SizedBox(height: 16.0),
|
||||
Text(
|
||||
AppLocalizations.of(context).noFiles,
|
||||
style: TextStyle(
|
||||
@@ -83,7 +83,7 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
|
||||
.textHighEmphasis,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.0),
|
||||
const SizedBox(height: 8.0),
|
||||
Text(
|
||||
AppLocalizations.of(context).filesAppearHere,
|
||||
textAlign: TextAlign.center,
|
||||
@@ -132,10 +132,10 @@ class _ChannelFileDisplayScreenState extends State<ChannelFileDisplayScreen> {
|
||||
),
|
||||
);
|
||||
},
|
||||
loading: () => Center(
|
||||
child: const CircularProgressIndicator(),
|
||||
loading: () => const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
error: (_) => Offstage(),
|
||||
error: (_) => const Offstage(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -18,7 +18,7 @@ class ChannelListPage extends StatefulWidget {
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ChannelListPageState createState() => _ChannelListPageState();
|
||||
State<ChannelListPage> createState() => _ChannelListPageState();
|
||||
}
|
||||
|
||||
class _ChannelListPageState extends State<ChannelListPage> {
|
||||
@@ -37,7 +37,7 @@ class _ChannelListPageState extends State<ChannelListPage> {
|
||||
? StreamChatTheme.of(context).colorTheme.textHighEmphasis
|
||||
: Colors.grey,
|
||||
),
|
||||
Positioned(
|
||||
const Positioned(
|
||||
top: -3,
|
||||
right: -16,
|
||||
child: StreamUnreadIndicator(),
|
||||
@@ -66,7 +66,7 @@ class _ChannelListPageState extends State<ChannelListPage> {
|
||||
Widget build(BuildContext context) {
|
||||
final user = StreamChat.of(context).currentUser;
|
||||
if (user == null) {
|
||||
return Offstage();
|
||||
return const Offstage();
|
||||
}
|
||||
return Scaffold(
|
||||
backgroundColor: StreamChatTheme.of(context).colorTheme.appBg,
|
||||
@@ -99,7 +99,7 @@ class _ChannelListPageState extends State<ChannelListPage> {
|
||||
),
|
||||
body: IndexedStack(
|
||||
index: _currentIndex,
|
||||
children: [
|
||||
children: const [
|
||||
ChannelList(),
|
||||
UserMentionsPage(),
|
||||
],
|
||||
@@ -164,13 +164,14 @@ class LeftDrawer extends StatelessWidget {
|
||||
StreamUserAvatar(
|
||||
user: user,
|
||||
showOnlineStatus: false,
|
||||
constraints: BoxConstraints.tight(Size.fromRadius(20)),
|
||||
constraints:
|
||||
BoxConstraints.tight(const Size.fromRadius(20)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0),
|
||||
child: Text(
|
||||
user.name,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
@@ -194,7 +195,7 @@ class LeftDrawer extends StatelessWidget {
|
||||
},
|
||||
title: Text(
|
||||
AppLocalizations.of(context).newDirectMessage,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 14.5,
|
||||
),
|
||||
),
|
||||
@@ -214,7 +215,7 @@ class LeftDrawer extends StatelessWidget {
|
||||
},
|
||||
title: Text(
|
||||
AppLocalizations.of(context).newGroup,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 14.5,
|
||||
),
|
||||
),
|
||||
@@ -224,21 +225,20 @@ class LeftDrawer extends StatelessWidget {
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: ListTile(
|
||||
onTap: () async {
|
||||
final client = StreamChat.of(context).client;
|
||||
final navigator =
|
||||
Navigator.of(context, rootNavigator: true);
|
||||
Navigator.pop(context);
|
||||
|
||||
if (!kIsWeb) {
|
||||
final secureStorage = FlutterSecureStorage();
|
||||
const secureStorage = FlutterSecureStorage();
|
||||
await secureStorage.deleteAll();
|
||||
}
|
||||
|
||||
final client = StreamChat.of(context).client;
|
||||
client.disconnectUser();
|
||||
await client.dispose();
|
||||
|
||||
await Navigator.of(
|
||||
context,
|
||||
rootNavigator: true,
|
||||
).pushNamedAndRemoveUntil(
|
||||
await navigator.pushNamedAndRemoveUntil(
|
||||
Routes.CHOOSE_USER,
|
||||
ModalRoute.withName(Routes.CHOOSE_USER),
|
||||
);
|
||||
@@ -251,7 +251,7 @@ class LeftDrawer extends StatelessWidget {
|
||||
),
|
||||
title: Text(
|
||||
AppLocalizations.of(context).signOut,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 14.5,
|
||||
),
|
||||
),
|
||||
@@ -263,12 +263,11 @@ class LeftDrawer extends StatelessWidget {
|
||||
.colorTheme
|
||||
.textLowEmphasis,
|
||||
onPressed: () async {
|
||||
final theme = Theme.of(context);
|
||||
final sp = await StreamingSharedPreferences.instance;
|
||||
sp.setInt(
|
||||
'theme',
|
||||
Theme.of(context).brightness == Brightness.dark
|
||||
? 1
|
||||
: -1,
|
||||
theme.brightness == Brightness.dark ? 1 : -1,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -30,10 +30,10 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
|
||||
),
|
||||
messageFilter: Filter.in_(
|
||||
'attachments.type',
|
||||
['image', 'video'],
|
||||
const ['image', 'video'],
|
||||
),
|
||||
sort: [
|
||||
SortOption(
|
||||
const SortOption(
|
||||
'created_at',
|
||||
direction: SortOption.ASC,
|
||||
),
|
||||
@@ -55,7 +55,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
|
||||
fontSize: 16.0,
|
||||
),
|
||||
),
|
||||
leading: StreamBackButton(),
|
||||
leading: const StreamBackButton(),
|
||||
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
|
||||
),
|
||||
body: ValueListenableBuilder(
|
||||
@@ -73,7 +73,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
|
||||
size: 136.0,
|
||||
color: StreamChatTheme.of(context).colorTheme.disabled,
|
||||
),
|
||||
SizedBox(height: 16.0),
|
||||
const SizedBox(height: 16.0),
|
||||
Text(
|
||||
AppLocalizations.of(context).noMedia,
|
||||
style: TextStyle(
|
||||
@@ -83,7 +83,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
|
||||
.textHighEmphasis,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.0),
|
||||
const SizedBox(height: 8.0),
|
||||
Text(
|
||||
AppLocalizations.of(context)
|
||||
.photosOrVideosWillAppearHere,
|
||||
@@ -131,7 +131,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
|
||||
}
|
||||
},
|
||||
child: GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3),
|
||||
itemBuilder: (context, position) {
|
||||
var channel = StreamChannel.of(context).channel;
|
||||
@@ -158,6 +158,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
|
||||
onShowMessage: (m, c) async {
|
||||
final client =
|
||||
StreamChat.of(context).client;
|
||||
final navigator = Navigator.of(context);
|
||||
final message = m;
|
||||
final channel = client.channel(
|
||||
c.type,
|
||||
@@ -166,8 +167,7 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
|
||||
if (channel.state == null) {
|
||||
await channel.watch();
|
||||
}
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
navigator.pushNamed(
|
||||
Routes.CHANNEL_PAGE,
|
||||
arguments: ChannelPageArgs(
|
||||
channel: channel,
|
||||
@@ -197,10 +197,10 @@ class _ChannelMediaDisplayScreenState extends State<ChannelMediaDisplayScreen> {
|
||||
),
|
||||
);
|
||||
},
|
||||
loading: () => Center(
|
||||
child: const CircularProgressIndicator(),
|
||||
loading: () => const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
error: (_) => Offstage(),
|
||||
error: (_) => const Offstage(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -30,12 +30,12 @@ class ChannelPage extends StatefulWidget {
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ChannelPageState createState() => _ChannelPageState();
|
||||
State<ChannelPage> createState() => _ChannelPageState();
|
||||
}
|
||||
|
||||
class _ChannelPageState extends State<ChannelPage> {
|
||||
FocusNode? _focusNode;
|
||||
StreamMessageInputController _messageInputController =
|
||||
final StreamMessageInputController _messageInputController =
|
||||
StreamMessageInputController();
|
||||
|
||||
@override
|
||||
@@ -64,7 +64,8 @@ class _ChannelPageState extends State<ChannelPage> {
|
||||
appBar: StreamChannelHeader(
|
||||
showTypingIndicator: false,
|
||||
onImageTap: () async {
|
||||
var channel = StreamChannel.of(context).channel;
|
||||
final channel = StreamChannel.of(context).channel;
|
||||
final navigator = Navigator.of(context);
|
||||
|
||||
if (channel.memberCount == 2 && channel.isDistinct) {
|
||||
final currentUser = StreamChat.of(context).currentUser;
|
||||
@@ -76,17 +77,17 @@ class _ChannelPageState extends State<ChannelPage> {
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => StreamChannel(
|
||||
channel: channel,
|
||||
child: ChatInfoScreen(
|
||||
messageTheme: StreamChatTheme.of(context).ownMessageTheme,
|
||||
user: otherUser.user,
|
||||
),
|
||||
channel: channel,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (pop == true) {
|
||||
Navigator.pop(context);
|
||||
navigator.pop();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -94,10 +95,10 @@ class _ChannelPageState extends State<ChannelPage> {
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => StreamChannel(
|
||||
channel: channel,
|
||||
child: GroupInfoScreen(
|
||||
messageTheme: StreamChatTheme.of(context).ownMessageTheme,
|
||||
),
|
||||
channel: channel,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -116,6 +117,7 @@ class _ChannelPageState extends State<ChannelPage> {
|
||||
onMessageSwiped: _reply,
|
||||
messageFilter: defaultFilter,
|
||||
messageBuilder: (context, details, messages, defaultMessage) {
|
||||
final navigator = Navigator.of(context);
|
||||
return defaultMessage.copyWith(
|
||||
onReplyTap: _reply,
|
||||
onShowMessage: (m, c) async {
|
||||
@@ -128,8 +130,7 @@ class _ChannelPageState extends State<ChannelPage> {
|
||||
if (channel.state == null) {
|
||||
await channel.watch();
|
||||
}
|
||||
Navigator.pushReplacementNamed(
|
||||
context,
|
||||
navigator.pushReplacementNamed(
|
||||
Routes.CHANNEL_PAGE,
|
||||
arguments: ChannelPageArgs(
|
||||
channel: channel,
|
||||
@@ -184,8 +185,8 @@ class _ChannelPageState extends State<ChannelPage> {
|
||||
}
|
||||
|
||||
bool defaultFilter(Message m) {
|
||||
var _currentUser = StreamChat.of(context).currentUser;
|
||||
final isMyMessage = m.user?.id == _currentUser?.id;
|
||||
final currentUser = StreamChat.of(context).currentUser;
|
||||
final isMyMessage = m.user?.id == currentUser?.id;
|
||||
final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true;
|
||||
if (isDeletedOrShadowed && !isMyMessage) return false;
|
||||
return true;
|
||||
|
||||
@@ -20,7 +20,7 @@ class ChatInfoScreen extends StatefulWidget {
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ChatInfoScreenState createState() => _ChatInfoScreenState();
|
||||
State<ChatInfoScreen> createState() => _ChatInfoScreenState();
|
||||
}
|
||||
|
||||
class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
@@ -69,7 +69,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: StreamUserAvatar(
|
||||
user: widget.user!,
|
||||
constraints: BoxConstraints.tightFor(
|
||||
constraints: const BoxConstraints.tightFor(
|
||||
width: 72.0,
|
||||
height: 72.0,
|
||||
),
|
||||
@@ -79,11 +79,12 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
),
|
||||
Text(
|
||||
widget.user!.name,
|
||||
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontSize: 16.0, fontWeight: FontWeight.bold),
|
||||
),
|
||||
SizedBox(height: 7.0),
|
||||
const SizedBox(height: 7.0),
|
||||
_buildConnectedTitleState(),
|
||||
SizedBox(height: 15.0),
|
||||
const SizedBox(height: 15.0),
|
||||
StreamOptionListTile(
|
||||
title: '@${widget.user!.id}',
|
||||
tileColor: StreamChatTheme.of(context).colorTheme.appBg,
|
||||
@@ -103,7 +104,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
const Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 58,
|
||||
@@ -120,18 +121,6 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
// _OptionListTile(
|
||||
// title: 'Notifications',
|
||||
// leading: StreamSvgIcon.Icon_notification(
|
||||
// size: 24.0,
|
||||
// color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5),
|
||||
// ),
|
||||
// trailing: CupertinoSwitch(
|
||||
// value: true,
|
||||
// onChanged: (val) {},
|
||||
// ),
|
||||
// onTap: () {},
|
||||
// ),
|
||||
StreamBuilder<bool>(
|
||||
stream: StreamChannel.of(context).channel.isMutedStream,
|
||||
builder: (context, snapshot) {
|
||||
@@ -152,7 +141,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
),
|
||||
),
|
||||
trailing: snapshot.data == null
|
||||
? CircularProgressIndicator()
|
||||
? const CircularProgressIndicator()
|
||||
: ValueListenableBuilder<bool?>(
|
||||
valueListenable: mutedBool,
|
||||
builder: (context, value, _) {
|
||||
@@ -172,24 +161,6 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
onTap: () {},
|
||||
);
|
||||
}),
|
||||
// _OptionListTile(
|
||||
// title: 'Block User',
|
||||
// leading: StreamSvgIcon.Icon_user_delete(
|
||||
// size: 24.0,
|
||||
// color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5),
|
||||
// ),
|
||||
// trailing: CupertinoSwitch(
|
||||
// value: widget.user.banned,
|
||||
// onChanged: (val) {
|
||||
// if (widget.user.banned) {
|
||||
// channel.channel.shadowBan(widget.user.id, {});
|
||||
// } else {
|
||||
// channel.channel.unbanUser(widget.user.id);
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// onTap: () {},
|
||||
// ),
|
||||
StreamOptionListTile(
|
||||
title: AppLocalizations.of(context).pinnedMessages,
|
||||
tileColor: StreamChatTheme.of(context).colorTheme.appBg,
|
||||
@@ -215,7 +186,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
MaterialPageRoute(
|
||||
builder: (context) => StreamChannel(
|
||||
channel: channel,
|
||||
child: PinnedMessagesScreen(),
|
||||
child: const PinnedMessagesScreen(),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -338,6 +309,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
}
|
||||
|
||||
void _showDeleteDialog() async {
|
||||
final streamChannel = StreamChannel.of(context);
|
||||
final res = await showConfirmationBottomSheet(
|
||||
context,
|
||||
title: AppLocalizations.of(context).deleteConversationTitle,
|
||||
@@ -348,7 +320,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
color: StreamChatTheme.of(context).colorTheme.accentError,
|
||||
),
|
||||
);
|
||||
var channel = StreamChannel.of(context).channel;
|
||||
final channel = streamChannel.channel;
|
||||
if (res == true) {
|
||||
await channel.delete().then((value) {
|
||||
Navigator.pop(context);
|
||||
@@ -358,7 +330,7 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
}
|
||||
|
||||
Widget _buildConnectedTitleState() {
|
||||
var alternativeWidget;
|
||||
late Text alternativeWidget;
|
||||
|
||||
final otherMember = widget.user;
|
||||
|
||||
@@ -390,22 +362,22 @@ class _ChatInfoScreenState extends State<ChatInfoScreen> {
|
||||
if (widget.user!.online)
|
||||
Material(
|
||||
type: MaterialType.circle,
|
||||
color: StreamChatTheme.of(context).colorTheme.barsBg,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
constraints: BoxConstraints.tightFor(
|
||||
constraints: const BoxConstraints.tightFor(
|
||||
width: 24,
|
||||
height: 12,
|
||||
),
|
||||
child: Material(
|
||||
shape: CircleBorder(),
|
||||
shape: const CircleBorder(),
|
||||
color: StreamChatTheme.of(context).colorTheme.accentInfo,
|
||||
),
|
||||
),
|
||||
color: StreamChatTheme.of(context).colorTheme.barsBg,
|
||||
),
|
||||
alternativeWidget,
|
||||
if (widget.user!.online)
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
width: 24.0,
|
||||
),
|
||||
],
|
||||
@@ -417,7 +389,7 @@ class _SharedGroupsScreen extends StatefulWidget {
|
||||
final User? mainUser;
|
||||
final User? otherUser;
|
||||
|
||||
_SharedGroupsScreen(this.mainUser, this.otherUser);
|
||||
const _SharedGroupsScreen(this.mainUser, this.otherUser);
|
||||
|
||||
@override
|
||||
__SharedGroupsScreenState createState() => __SharedGroupsScreenState();
|
||||
@@ -439,7 +411,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
|
||||
color: StreamChatTheme.of(context).colorTheme.textHighEmphasis,
|
||||
fontSize: 16.0),
|
||||
),
|
||||
leading: StreamBackButton(),
|
||||
leading: const StreamBackButton(),
|
||||
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
|
||||
),
|
||||
body: StreamBuilder<List<Channel>>(
|
||||
@@ -451,7 +423,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
|
||||
),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return Center(
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
@@ -465,7 +437,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
|
||||
size: 136.0,
|
||||
color: StreamChatTheme.of(context).colorTheme.disabled,
|
||||
),
|
||||
SizedBox(height: 16.0),
|
||||
const SizedBox(height: 16.0),
|
||||
Text(
|
||||
AppLocalizations.of(context).noSharedGroups,
|
||||
style: TextStyle(
|
||||
@@ -475,7 +447,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
|
||||
.textHighEmphasis,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.0),
|
||||
const SizedBox(height: 8.0),
|
||||
Text(
|
||||
AppLocalizations.of(context).groupSharedWithUserAppearHere,
|
||||
textAlign: TextAlign.center,
|
||||
@@ -515,84 +487,86 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> {
|
||||
}
|
||||
|
||||
Widget _buildListTile(Channel channel) {
|
||||
var extraData = channel.extraData;
|
||||
var members = channel.state!.members;
|
||||
final extraData = channel.extraData;
|
||||
final members = channel.state!.members;
|
||||
|
||||
var textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold);
|
||||
const textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold);
|
||||
|
||||
return Container(
|
||||
return SizedBox(
|
||||
height: 64.0,
|
||||
child: LayoutBuilder(builder: (context, constraints) {
|
||||
String? title;
|
||||
if (extraData['name'] == null) {
|
||||
final otherMembers = members.where((member) =>
|
||||
member.userId != StreamChat.of(context).currentUser!.id);
|
||||
if (otherMembers.isNotEmpty) {
|
||||
final maxWidth = constraints.maxWidth;
|
||||
final maxChars = maxWidth / textStyle.fontSize!;
|
||||
var currentChars = 0;
|
||||
final currentMembers = <Member>[];
|
||||
otherMembers.forEach((element) {
|
||||
final newLength = currentChars + element.user!.name.length;
|
||||
if (newLength < maxChars) {
|
||||
currentChars = newLength;
|
||||
currentMembers.add(element);
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
String? title;
|
||||
if (extraData['name'] == null) {
|
||||
final otherMembers = members.where((member) =>
|
||||
member.userId != StreamChat.of(context).currentUser!.id);
|
||||
if (otherMembers.isNotEmpty) {
|
||||
final maxWidth = constraints.maxWidth;
|
||||
final maxChars = maxWidth / textStyle.fontSize!;
|
||||
var currentChars = 0;
|
||||
final currentMembers = <Member>[];
|
||||
for (var element in otherMembers) {
|
||||
final newLength = currentChars + element.user!.name.length;
|
||||
if (newLength < maxChars) {
|
||||
currentChars = newLength;
|
||||
currentMembers.add(element);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final exceedingMembers =
|
||||
otherMembers.length - currentMembers.length;
|
||||
title =
|
||||
'${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}';
|
||||
final exceedingMembers =
|
||||
otherMembers.length - currentMembers.length;
|
||||
title =
|
||||
'${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}';
|
||||
} else {
|
||||
title = 'No title';
|
||||
}
|
||||
} else {
|
||||
title = 'No title';
|
||||
title = extraData['name'] as String;
|
||||
}
|
||||
} else {
|
||||
title = extraData['name'] as String;
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: StreamChannelAvatar(
|
||||
channel: channel,
|
||||
constraints:
|
||||
BoxConstraints(maxWidth: 40.0, maxHeight: 40.0),
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: StreamChannelAvatar(
|
||||
channel: channel,
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 40.0, maxHeight: 40.0),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: textStyle,
|
||||
)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
title,
|
||||
style: textStyle,
|
||||
)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
'${channel.memberCount} ${AppLocalizations.of(context).members.toLowerCase()}',
|
||||
style: TextStyle(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(0.5)),
|
||||
),
|
||||
)
|
||||
],
|
||||
'${channel.memberCount} ${AppLocalizations.of(context).members.toLowerCase()}',
|
||||
style: TextStyle(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(0.5)),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 1.0,
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(.08),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Container(
|
||||
height: 1.0,
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(.08),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ const kStreamUserId = 'STREAM_USER_ID';
|
||||
const kStreamToken = 'STREAM_TOKEN';
|
||||
|
||||
class ChooseUserPage extends StatelessWidget {
|
||||
const ChooseUserPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final users = defaultUsers;
|
||||
@@ -85,7 +87,7 @@ class ChooseUserPage extends StatelessWidget {
|
||||
),
|
||||
height: 100,
|
||||
width: 100,
|
||||
child: Center(
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
@@ -97,13 +99,15 @@ class ChooseUserPage extends StatelessWidget {
|
||||
logLevel: Level.INFO,
|
||||
)..chatPersistenceClient = chatPersistentClient;
|
||||
|
||||
final navigator = Navigator.of(context);
|
||||
|
||||
await client.connectUser(
|
||||
user,
|
||||
token,
|
||||
);
|
||||
|
||||
if (!kIsWeb) {
|
||||
final secureStorage = FlutterSecureStorage();
|
||||
const secureStorage = FlutterSecureStorage();
|
||||
secureStorage.write(
|
||||
key: kStreamApiKey,
|
||||
value: kDefaultStreamApiKey,
|
||||
@@ -117,8 +121,7 @@ class ChooseUserPage extends StatelessWidget {
|
||||
value: token,
|
||||
);
|
||||
}
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
context,
|
||||
navigator.pushNamedAndRemoveUntil(
|
||||
Routes.HOME,
|
||||
ModalRoute.withName(Routes.HOME),
|
||||
arguments: HomePageArgs(client),
|
||||
@@ -127,7 +130,7 @@ class ChooseUserPage extends StatelessWidget {
|
||||
leading: StreamUserAvatar(
|
||||
user: user,
|
||||
constraints: BoxConstraints.tight(
|
||||
Size.fromRadius(20),
|
||||
const Size.fromRadius(20),
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
@@ -158,13 +161,13 @@ class ChooseUserPage extends StatelessWidget {
|
||||
Navigator.pushNamed(context, Routes.ADVANCED_OPTIONS);
|
||||
},
|
||||
leading: CircleAvatar(
|
||||
backgroundColor:
|
||||
StreamChatTheme.of(context).colorTheme.borders,
|
||||
child: StreamSvgIcon.settings(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis,
|
||||
),
|
||||
backgroundColor:
|
||||
StreamChatTheme.of(context).colorTheme.borders,
|
||||
),
|
||||
title: Text(
|
||||
AppLocalizations.of(context).advancedOptions,
|
||||
@@ -193,7 +196,7 @@ class ChooseUserPage extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
StreamVersion(),
|
||||
const StreamVersion(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -14,7 +14,7 @@ class GroupChatDetailsScreen extends StatefulWidget {
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_GroupChatDetailsScreenState createState() => _GroupChatDetailsScreenState();
|
||||
State<GroupChatDetailsScreen> createState() => _GroupChatDetailsScreenState();
|
||||
}
|
||||
|
||||
class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
|
||||
@@ -73,7 +73,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
|
||||
),
|
||||
centerTitle: true,
|
||||
bottom: PreferredSize(
|
||||
preferredSize: Size.fromHeight(kToolbarHeight),
|
||||
preferredSize: const Size.fromHeight(kToolbarHeight),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 16),
|
||||
child: Row(
|
||||
@@ -87,7 +87,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
|
||||
.textLowEmphasis,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _groupNameController,
|
||||
@@ -130,8 +130,9 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
|
||||
try {
|
||||
final groupName = _groupNameController!.text;
|
||||
final client = StreamChat.of(context).client;
|
||||
final navigator = Navigator.of(context);
|
||||
final channel = client.channel('messaging',
|
||||
id: Uuid().v4(),
|
||||
id: const Uuid().v4(),
|
||||
extraData: {
|
||||
'members': [
|
||||
client.state.currentUser!.id,
|
||||
@@ -140,8 +141,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
|
||||
'name': groupName,
|
||||
});
|
||||
await channel.watch();
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
context,
|
||||
navigator.pushNamedAndRemoveUntil(
|
||||
Routes.CHANNEL_PAGE,
|
||||
ModalRoute.withName(Routes.CHANNEL_LIST_PAGE),
|
||||
arguments: ChannelPageArgs(channel: channel),
|
||||
@@ -223,14 +223,15 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
|
||||
key: ObjectKey(user),
|
||||
leading: StreamUserAvatar(
|
||||
user: user,
|
||||
constraints: BoxConstraints.tightFor(
|
||||
constraints: const BoxConstraints.tightFor(
|
||||
width: 40,
|
||||
height: 40,
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
user.name,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style:
|
||||
const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
@@ -273,7 +274,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
|
||||
useRootNavigator: false,
|
||||
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
|
||||
context: context,
|
||||
shape: RoundedRectangleBorder(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(16.0),
|
||||
topRight: Radius.circular(16.0),
|
||||
@@ -282,25 +283,25 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 26.0,
|
||||
),
|
||||
StreamSvgIcon.error(
|
||||
color: StreamChatTheme.of(context).colorTheme.accentError,
|
||||
size: 24.0,
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 26.0,
|
||||
),
|
||||
Text(
|
||||
AppLocalizations.of(context).somethingWentWrongErrorMessage,
|
||||
style: StreamChatTheme.of(context).textTheme.headlineBold,
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 7.0,
|
||||
),
|
||||
Text(AppLocalizations.of(context).operationCouldNotBeCompleted),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 36.0,
|
||||
),
|
||||
Container(
|
||||
|
||||
@@ -21,7 +21,7 @@ class GroupInfoScreen extends StatefulWidget {
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_GroupInfoScreenState createState() => _GroupInfoScreenState();
|
||||
State<GroupInfoScreen> createState() => _GroupInfoScreenState();
|
||||
}
|
||||
|
||||
class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
@@ -101,7 +101,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
],
|
||||
),
|
||||
sort: [
|
||||
SortOption(
|
||||
const SortOption(
|
||||
'name',
|
||||
direction: 1,
|
||||
),
|
||||
@@ -124,7 +124,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
if (!snapshot.hasData) {
|
||||
return Container(
|
||||
color: StreamChatTheme.of(context).colorTheme.disabled,
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
child: const Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
elevation: 1.0,
|
||||
toolbarHeight: 56.0,
|
||||
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
|
||||
leading: StreamBackButton(),
|
||||
leading: const StreamBackButton(),
|
||||
title: Column(
|
||||
children: [
|
||||
StreamBuilder<ChannelState>(
|
||||
@@ -171,7 +171,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
}),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 3.0,
|
||||
),
|
||||
Text(
|
||||
@@ -242,11 +242,12 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
children: [
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: groupMembersLength,
|
||||
itemBuilder: (context, index) {
|
||||
final member = groupMembers[index];
|
||||
return Material(
|
||||
color: StreamChatTheme.of(context).colorTheme.appBg,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
final userMember = groupMembers.firstWhereOrNull(
|
||||
@@ -255,7 +256,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
_showUserInfoModal(
|
||||
member.user, userMember?.userId == channel.createdBy?.id);
|
||||
},
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
height: 65.0,
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -268,7 +269,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
),
|
||||
child: StreamUserAvatar(
|
||||
user: member.user!,
|
||||
constraints: BoxConstraints.tightFor(
|
||||
constraints: const BoxConstraints.tightFor(
|
||||
height: 40.0,
|
||||
width: 40.0,
|
||||
),
|
||||
@@ -281,9 +282,10 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
children: [
|
||||
Text(
|
||||
member.user!.name,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 1.0,
|
||||
),
|
||||
Text(
|
||||
@@ -320,7 +322,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
color: StreamChatTheme.of(context).colorTheme.appBg,
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -333,7 +334,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
},
|
||||
child: Material(
|
||||
color: StreamChatTheme.of(context).colorTheme.appBg,
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
height: 65.0,
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -401,7 +402,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
.withOpacity(0.5)),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
width: 7.0,
|
||||
),
|
||||
Expanded(
|
||||
@@ -422,7 +423,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(0.5))),
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 0.82,
|
||||
),
|
||||
@@ -478,18 +479,6 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
Widget _buildOptionListTiles() {
|
||||
return Column(
|
||||
children: [
|
||||
// OptionListTile(
|
||||
// title: 'Notifications',
|
||||
// leading: StreamSvgIcon.Icon_notification(
|
||||
// size: 24.0,
|
||||
// color: StreamChatTheme.of(context).colorTheme.textHighEmphasis.withOpacity(0.5),
|
||||
// ),
|
||||
// trailing: CupertinoSwitch(
|
||||
// value: true,
|
||||
// onChanged: (val) {},
|
||||
// ),
|
||||
// onTap: () {},
|
||||
// ),
|
||||
if (channel.ownCapabilities.contains(PermissionType.muteChannel))
|
||||
StreamBuilder<bool>(
|
||||
stream: channel.isMutedStream,
|
||||
@@ -513,7 +502,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
),
|
||||
),
|
||||
trailing: snapshot.data == null
|
||||
? CircularProgressIndicator()
|
||||
? const CircularProgressIndicator()
|
||||
: ValueListenableBuilder<bool?>(
|
||||
valueListenable: mutedBool,
|
||||
builder: (context, value, _) {
|
||||
@@ -558,7 +547,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
MaterialPageRoute(
|
||||
builder: (context) => StreamChannel(
|
||||
channel: channel,
|
||||
child: PinnedMessagesScreen(),
|
||||
child: const PinnedMessagesScreen(),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -649,11 +638,14 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
trailing: Container(
|
||||
trailing: const SizedBox(
|
||||
height: 24.0,
|
||||
width: 24.0,
|
||||
),
|
||||
onTap: () async {
|
||||
final streamChannel = StreamChannel.of(context);
|
||||
final streamChat = StreamChat.of(context);
|
||||
final navigator = Navigator.of(context);
|
||||
final res = await showConfirmationBottomSheet(
|
||||
context,
|
||||
title: AppLocalizations.of(context).leaveConversation,
|
||||
@@ -666,10 +658,9 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
),
|
||||
);
|
||||
if (res == true) {
|
||||
final channel = StreamChannel.of(context).channel;
|
||||
await channel
|
||||
.removeMembers([StreamChat.of(context).currentUser!.id]);
|
||||
Navigator.pop(context);
|
||||
final channel = streamChannel.channel;
|
||||
await channel.removeMembers([streamChat.currentUser!.id]);
|
||||
navigator.pop();
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -684,9 +675,9 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
|
||||
builder: (context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0),
|
||||
padding: const EdgeInsets.only(top: 16.0, left: 8.0, right: 8.0),
|
||||
child: Material(
|
||||
borderRadius: BorderRadius.only(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(16.0),
|
||||
topRight: Radius.circular(16.0),
|
||||
),
|
||||
@@ -703,16 +694,17 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
controller: userListController,
|
||||
onUserTap: (user) async {
|
||||
_searchController!.clear();
|
||||
final navigator = Navigator.of(context);
|
||||
|
||||
await channel.addMembers([user.id]);
|
||||
Navigator.pop(context);
|
||||
navigator.pop();
|
||||
setState(() {});
|
||||
},
|
||||
emptyBuilder: (_) {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
return SingleChildScrollView(
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: viewportConstraints.maxHeight,
|
||||
@@ -760,7 +752,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
height: 36,
|
||||
child: TextField(
|
||||
controller: _searchController,
|
||||
@@ -771,7 +763,8 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
hintStyle: theme.textTheme.body.copyWith(
|
||||
color: theme.colorTheme.textLowEmphasis,
|
||||
),
|
||||
prefixIconConstraints: BoxConstraints.tight(Size(40, 24)),
|
||||
prefixIconConstraints:
|
||||
BoxConstraints.tight(const Size(40, 24)),
|
||||
prefixIcon: StreamSvgIcon.search(
|
||||
color: theme.colorTheme.textHighEmphasis,
|
||||
size: 24,
|
||||
@@ -792,12 +785,12 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16.0),
|
||||
const SizedBox(width: 16.0),
|
||||
IconButton(
|
||||
icon: StreamSvgIcon.closeSmall(
|
||||
color: theme.colorTheme.textLowEmphasis,
|
||||
),
|
||||
constraints: BoxConstraints.tightFor(
|
||||
constraints: const BoxConstraints.tightFor(
|
||||
height: 24,
|
||||
width: 24,
|
||||
),
|
||||
@@ -829,19 +822,19 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 24.0,
|
||||
),
|
||||
Center(
|
||||
child: Text(
|
||||
user!.name,
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 5.0,
|
||||
),
|
||||
_buildConnectedTitleState(user)!,
|
||||
@@ -850,7 +843,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: StreamUserAvatar(
|
||||
user: user,
|
||||
constraints: BoxConstraints.tightFor(
|
||||
constraints: const BoxConstraints.tightFor(
|
||||
height: 64.0,
|
||||
width: 64.0,
|
||||
),
|
||||
@@ -869,9 +862,10 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
),
|
||||
AppLocalizations.of(context).viewInfo,
|
||||
() async {
|
||||
var client = StreamChat.of(context).client;
|
||||
final client = StreamChat.of(context).client;
|
||||
final navigator = Navigator.of(context);
|
||||
|
||||
var c = client.channel('messaging', extraData: {
|
||||
final c = client.channel('messaging', extraData: {
|
||||
'members': [
|
||||
user.id,
|
||||
StreamChat.of(context).currentUser!.id,
|
||||
@@ -880,8 +874,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
|
||||
await c.watch();
|
||||
|
||||
await Navigator.push(
|
||||
context,
|
||||
await navigator.push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => StreamChannel(
|
||||
channel: c,
|
||||
@@ -905,9 +898,10 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
),
|
||||
AppLocalizations.of(context).message,
|
||||
() async {
|
||||
var client = StreamChat.of(context).client;
|
||||
final client = StreamChat.of(context).client;
|
||||
final navigator = Navigator.of(context);
|
||||
|
||||
var c = client.channel('messaging', extraData: {
|
||||
final c = client.channel('messaging', extraData: {
|
||||
'members': [
|
||||
user.id,
|
||||
StreamChat.of(context).currentUser!.id,
|
||||
@@ -916,12 +910,11 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
|
||||
await c.watch();
|
||||
|
||||
await Navigator.push(
|
||||
context,
|
||||
await navigator.push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => StreamChannel(
|
||||
channel: c,
|
||||
child: ChannelPage(),
|
||||
child: const ChannelPage(),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -939,6 +932,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
size: 24.0,
|
||||
),
|
||||
AppLocalizations.of(context).removeFromGroup, () async {
|
||||
final navigator = Navigator.of(context);
|
||||
final res = await showConfirmationBottomSheet(
|
||||
context,
|
||||
title: AppLocalizations.of(context).removeMember,
|
||||
@@ -953,7 +947,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
if (res == true) {
|
||||
await channel.removeMembers([user.id]);
|
||||
}
|
||||
Navigator.pop(context);
|
||||
navigator.pop();
|
||||
},
|
||||
color:
|
||||
StreamChatTheme.of(context).colorTheme.accentError),
|
||||
@@ -974,7 +968,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
),
|
||||
);
|
||||
},
|
||||
shape: RoundedRectangleBorder(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(16.0),
|
||||
topRight: Radius.circular(16.0),
|
||||
@@ -984,7 +978,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
}
|
||||
|
||||
Widget? _buildConnectedTitleState(User? user) {
|
||||
var alternativeWidget;
|
||||
late Text alternativeWidget;
|
||||
|
||||
final otherMember = user;
|
||||
|
||||
@@ -1028,7 +1022,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
height: 1.0,
|
||||
color: StreamChatTheme.of(context).colorTheme.disabled,
|
||||
),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: 64.0,
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -1068,13 +1062,13 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
|
||||
final maxChars = maxWidth / maxFontSize!;
|
||||
var currentChars = 0;
|
||||
final currentMembers = <Member>[];
|
||||
otherMembers.forEach((element) {
|
||||
for (var element in otherMembers) {
|
||||
final newLength = currentChars + element.user!.name.length;
|
||||
if (newLength < maxChars) {
|
||||
currentChars = newLength;
|
||||
currentMembers.add(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final exceedingMembers = otherMembers.length - currentMembers.length;
|
||||
title =
|
||||
|
||||
@@ -72,7 +72,7 @@ class HomePageArgs {
|
||||
}
|
||||
|
||||
class HomePage extends StatefulWidget {
|
||||
HomePage({
|
||||
const HomePage({
|
||||
Key? key,
|
||||
required this.chatClient,
|
||||
}) : super(key: key);
|
||||
@@ -80,7 +80,7 @@ class HomePage extends StatefulWidget {
|
||||
final StreamChatClient chatClient;
|
||||
|
||||
@override
|
||||
_HomePageState createState() => _HomePageState();
|
||||
State<HomePage> createState() => _HomePageState();
|
||||
}
|
||||
|
||||
class _HomePageState extends State<HomePage> {
|
||||
|
||||
@@ -9,8 +9,10 @@ import '../widgets/chips_input_text_field.dart';
|
||||
import '../routes/routes.dart';
|
||||
|
||||
class NewChatScreen extends StatefulWidget {
|
||||
const NewChatScreen({super.key});
|
||||
|
||||
@override
|
||||
_NewChatScreenState createState() => _NewChatScreenState();
|
||||
State<NewChatScreen> createState() => _NewChatScreenState();
|
||||
}
|
||||
|
||||
class _NewChatScreenState extends State<NewChatScreen> {
|
||||
@@ -26,7 +28,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
Filter.notEqual('id', StreamChat.of(context).currentUser!.id),
|
||||
]),
|
||||
sort: [
|
||||
SortOption(
|
||||
const SortOption(
|
||||
'name',
|
||||
direction: 1,
|
||||
),
|
||||
@@ -54,11 +56,12 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
void _userNameListener() {
|
||||
if (_debounce?.isActive ?? false) _debounce!.cancel();
|
||||
_debounce = Timer(const Duration(milliseconds: 350), () {
|
||||
if (mounted)
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_userNameQuery = _controller.text;
|
||||
_isSearchActive = _userNameQuery.isNotEmpty;
|
||||
});
|
||||
}
|
||||
userListController.filter = Filter.and([
|
||||
if (_userNameQuery.isNotEmpty)
|
||||
Filter.autoComplete('name', _userNameQuery),
|
||||
@@ -97,13 +100,13 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
'distinct': true,
|
||||
}),
|
||||
messageLimit: 0,
|
||||
paginationParams: PaginationParams(
|
||||
paginationParams: const PaginationParams(
|
||||
limit: 1,
|
||||
),
|
||||
);
|
||||
|
||||
final _channelExisted = res.length == 1;
|
||||
if (_channelExisted) {
|
||||
final channelExisted = res.length == 1;
|
||||
if (channelExisted) {
|
||||
channel = res.first;
|
||||
await channel!.watch();
|
||||
} else {
|
||||
@@ -224,7 +227,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
child: StreamUserAvatar(
|
||||
showOnlineStatus: false,
|
||||
user: user,
|
||||
constraints: BoxConstraints.tightFor(
|
||||
constraints: const BoxConstraints.tightFor(
|
||||
height: 24,
|
||||
width: 24,
|
||||
),
|
||||
@@ -243,37 +246,35 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
},
|
||||
),
|
||||
if (!_isSearchActive && !_selectedUsers.isNotEmpty)
|
||||
Container(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
Routes.NEW_GROUP_CHAT,
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
StreamNeumorphicButton(
|
||||
child: Center(
|
||||
child: StreamSvgIcon.contacts(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.accentPrimary,
|
||||
size: 24,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
Routes.NEW_GROUP_CHAT,
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
StreamNeumorphicButton(
|
||||
child: Center(
|
||||
child: StreamSvgIcon.contacts(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.accentPrimary,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
AppLocalizations.of(context).createAGroup,
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.bodyBold,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
AppLocalizations.of(context).createAGroup,
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.bodyBold,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -337,7 +338,8 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
return SingleChildScrollView(
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
physics:
|
||||
const AlwaysScrollableScrollPhysics(),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight:
|
||||
@@ -382,7 +384,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
|
||||
future: channel!.initialized,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.data == true) {
|
||||
return StreamMessageListView();
|
||||
return const StreamMessageListView();
|
||||
}
|
||||
|
||||
return Center(
|
||||
|
||||
@@ -8,8 +8,10 @@ import '../routes/routes.dart';
|
||||
import '../widgets/search_text_field.dart';
|
||||
|
||||
class NewGroupChatScreen extends StatefulWidget {
|
||||
const NewGroupChatScreen({super.key});
|
||||
|
||||
@override
|
||||
_NewGroupChatScreenState createState() => _NewGroupChatScreenState();
|
||||
State<NewGroupChatScreen> createState() => _NewGroupChatScreenState();
|
||||
}
|
||||
|
||||
class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
@@ -26,7 +28,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
late final userListController = StreamUserListController(
|
||||
client: StreamChat.of(context).client,
|
||||
sort: [
|
||||
SortOption(
|
||||
const SortOption(
|
||||
'name',
|
||||
direction: 1,
|
||||
),
|
||||
@@ -144,13 +146,14 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
),
|
||||
if (_selectedUsers.isNotEmpty)
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
height: 104,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: _selectedUsers.length,
|
||||
padding: const EdgeInsets.all(8),
|
||||
separatorBuilder: (_, __) => SizedBox(width: 16),
|
||||
separatorBuilder: (_, __) =>
|
||||
const SizedBox(width: 16),
|
||||
itemBuilder: (_, index) {
|
||||
final user = _selectedUsers.elementAt(index);
|
||||
return Column(
|
||||
@@ -159,11 +162,12 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
children: [
|
||||
StreamUserAvatar(
|
||||
onlineIndicatorAlignment:
|
||||
Alignment(0.9, 0.9),
|
||||
const Alignment(0.9, 0.9),
|
||||
user: user,
|
||||
showOnlineStatus: true,
|
||||
borderRadius: BorderRadius.circular(32),
|
||||
constraints: BoxConstraints.tightFor(
|
||||
constraints:
|
||||
const BoxConstraints.tightFor(
|
||||
height: 64,
|
||||
width: 64,
|
||||
),
|
||||
@@ -201,10 +205,10 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
user.name.split(' ')[0],
|
||||
style: TextStyle(
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
@@ -218,7 +222,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
SliverPersistentHeader(
|
||||
pinned: true,
|
||||
delegate: _HeaderDelegate(
|
||||
height: 30,
|
||||
height: 32,
|
||||
child: Container(
|
||||
width: double.maxFinite,
|
||||
decoration: BoxDecoration(
|
||||
@@ -232,7 +236,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
),
|
||||
child: Text(
|
||||
_isSearchActive
|
||||
? '${AppLocalizations.of(context).matchesFor} \"$_userNameQuery\"'
|
||||
? '${AppLocalizations.of(context).matchesFor} "$_userNameQuery"'
|
||||
: AppLocalizations.of(context).onThePlatorm,
|
||||
style: TextStyle(
|
||||
color: StreamChatTheme.of(context)
|
||||
@@ -271,7 +275,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
return SingleChildScrollView(
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: viewportConstraints.maxHeight,
|
||||
|
||||
@@ -6,6 +6,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'channel_page.dart';
|
||||
|
||||
class PinnedMessagesScreen extends StatefulWidget {
|
||||
const PinnedMessagesScreen({super.key});
|
||||
|
||||
@override
|
||||
State<PinnedMessagesScreen> createState() => _PinnedMessagesScreenState();
|
||||
}
|
||||
@@ -22,7 +24,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
|
||||
true,
|
||||
),
|
||||
sort: [
|
||||
SortOption(
|
||||
const SortOption(
|
||||
'created_at',
|
||||
direction: SortOption.ASC,
|
||||
),
|
||||
@@ -44,7 +46,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
|
||||
fontSize: 16.0,
|
||||
),
|
||||
),
|
||||
leading: StreamBackButton(),
|
||||
leading: const StreamBackButton(),
|
||||
backgroundColor: StreamChatTheme.of(context).colorTheme.barsBg,
|
||||
),
|
||||
body: StreamMessageSearchListView(
|
||||
@@ -58,7 +60,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
|
||||
size: 136.0,
|
||||
color: StreamChatTheme.of(context).colorTheme.disabled,
|
||||
),
|
||||
SizedBox(height: 16.0),
|
||||
const SizedBox(height: 16.0),
|
||||
Text(
|
||||
AppLocalizations.of(context).noPinnedItems,
|
||||
style: TextStyle(
|
||||
@@ -68,7 +70,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.0),
|
||||
const SizedBox(height: 8.0),
|
||||
RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(children: [
|
||||
@@ -101,6 +103,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
|
||||
},
|
||||
onMessageTap: (messageResponse) async {
|
||||
final client = StreamChat.of(context).client;
|
||||
final navigator = Navigator.of(context);
|
||||
final message = messageResponse.message;
|
||||
final channel = client.channel(
|
||||
messageResponse.channel!.type,
|
||||
@@ -109,8 +112,7 @@ class _PinnedMessagesScreenState extends State<PinnedMessagesScreen> {
|
||||
if (channel.state == null) {
|
||||
await channel.watch();
|
||||
}
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
navigator.pushNamed(
|
||||
Routes.CHANNEL_PAGE,
|
||||
arguments: ChannelPageArgs(
|
||||
channel: channel,
|
||||
|
||||
@@ -12,7 +12,7 @@ mixin SplashScreenStateMixin<T extends StatefulWidget> on State<T>
|
||||
_scaleAnimationController = AnimationController(
|
||||
vsync: this,
|
||||
value: 0,
|
||||
duration: Duration(
|
||||
duration: const Duration(
|
||||
milliseconds: 500,
|
||||
),
|
||||
);
|
||||
@@ -26,7 +26,7 @@ mixin SplashScreenStateMixin<T extends StatefulWidget> on State<T>
|
||||
|
||||
_animationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: Duration(
|
||||
duration: const Duration(
|
||||
milliseconds: 1000,
|
||||
),
|
||||
);
|
||||
@@ -38,14 +38,14 @@ mixin SplashScreenStateMixin<T extends StatefulWidget> on State<T>
|
||||
curve: Curves.easeInOut,
|
||||
));
|
||||
colorAnimation = ColorTween(
|
||||
begin: Color(0xff005FFF),
|
||||
end: Color(0xff005FFF),
|
||||
begin: const Color(0xff005FFF),
|
||||
end: const Color(0xff005FFF),
|
||||
).animate(CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Curves.easeInOut,
|
||||
));
|
||||
colorAnimation = ColorTween(
|
||||
begin: Color(0xff005FFF),
|
||||
begin: const Color(0xff005FFF),
|
||||
end: Colors.transparent,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _animationController,
|
||||
@@ -73,14 +73,14 @@ mixin SplashScreenStateMixin<T extends StatefulWidget> on State<T>
|
||||
builder: (context, snapshot) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
constraints: BoxConstraints.expand(),
|
||||
constraints: const BoxConstraints.expand(),
|
||||
color: colorAnimation.value,
|
||||
child: !_animationController.isAnimating
|
||||
? Lottie.asset(
|
||||
'assets/floating_boat.json',
|
||||
alignment: Alignment.center,
|
||||
)
|
||||
: SizedBox(),
|
||||
: const SizedBox(),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@ class ThreadPage extends StatefulWidget {
|
||||
final int? initialScrollIndex;
|
||||
final double? initialAlignment;
|
||||
|
||||
ThreadPage({
|
||||
const ThreadPage({
|
||||
Key? key,
|
||||
required this.parent,
|
||||
this.initialScrollIndex,
|
||||
@@ -14,11 +14,11 @@ class ThreadPage extends StatefulWidget {
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ThreadPageState createState() => _ThreadPageState();
|
||||
State<ThreadPage> createState() => _ThreadPageState();
|
||||
}
|
||||
|
||||
class _ThreadPageState extends State<ThreadPage> {
|
||||
FocusNode _focusNode = FocusNode();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
late StreamMessageInputController _messageInputController;
|
||||
|
||||
@override
|
||||
@@ -82,8 +82,8 @@ class _ThreadPageState extends State<ThreadPage> {
|
||||
}
|
||||
|
||||
bool defaultFilter(Message m) {
|
||||
var _currentUser = StreamChat.of(context).currentUser;
|
||||
final isMyMessage = m.user?.id == _currentUser?.id;
|
||||
final currentUser = StreamChat.of(context).currentUser;
|
||||
final isMyMessage = m.user?.id == currentUser?.id;
|
||||
final isDeletedOrShadowed = m.isDeleted == true || m.shadowed == true;
|
||||
if (isDeletedOrShadowed && !isMyMessage) return false;
|
||||
return true;
|
||||
|
||||
@@ -6,6 +6,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
import 'channel_page.dart';
|
||||
|
||||
class UserMentionsPage extends StatefulWidget {
|
||||
const UserMentionsPage({super.key});
|
||||
|
||||
@override
|
||||
State<UserMentionsPage> createState() => _UserMentionsPageState();
|
||||
}
|
||||
@@ -20,7 +22,7 @@ class _UserMentionsPageState extends State<UserMentionsPage> {
|
||||
value: StreamChat.of(context).currentUser!.id,
|
||||
),
|
||||
sort: [
|
||||
SortOption(
|
||||
const SortOption(
|
||||
'created_at',
|
||||
direction: SortOption.ASC,
|
||||
),
|
||||
@@ -35,7 +37,7 @@ class _UserMentionsPageState extends State<UserMentionsPage> {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
return SingleChildScrollView(
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: viewportConstraints.maxHeight,
|
||||
@@ -70,6 +72,7 @@ class _UserMentionsPageState extends State<UserMentionsPage> {
|
||||
},
|
||||
onMessageTap: (messageResponse) async {
|
||||
final client = StreamChat.of(context).client;
|
||||
final navigator = Navigator.of(context);
|
||||
final message = messageResponse.message;
|
||||
final channel = client.channel(
|
||||
messageResponse.channel!.type,
|
||||
@@ -78,8 +81,7 @@ class _UserMentionsPageState extends State<UserMentionsPage> {
|
||||
if (channel.state == null) {
|
||||
await channel.watch();
|
||||
}
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
navigator.pushNamed(
|
||||
Routes.CHANNEL_PAGE,
|
||||
arguments: ChannelPageArgs(
|
||||
channel: channel,
|
||||
|
||||
@@ -25,7 +25,7 @@ class AppRoutes {
|
||||
return MaterialPageRoute(
|
||||
settings: RouteSettings(arguments: args, name: Routes.APP),
|
||||
builder: (_) {
|
||||
return MyApp();
|
||||
return const StreamChatSampleApp();
|
||||
});
|
||||
case Routes.HOME:
|
||||
return MaterialPageRoute(
|
||||
@@ -40,13 +40,13 @@ class AppRoutes {
|
||||
return MaterialPageRoute(
|
||||
settings: RouteSettings(arguments: args, name: Routes.CHOOSE_USER),
|
||||
builder: (_) {
|
||||
return ChooseUserPage();
|
||||
return const ChooseUserPage();
|
||||
});
|
||||
case Routes.ADVANCED_OPTIONS:
|
||||
return MaterialPageRoute(
|
||||
settings:
|
||||
RouteSettings(arguments: args, name: Routes.ADVANCED_OPTIONS),
|
||||
builder: (_) => AdvancedOptionsPage(),
|
||||
builder: (_) => const AdvancedOptionsPage(),
|
||||
);
|
||||
case Routes.CHANNEL_PAGE:
|
||||
return MaterialPageRoute(
|
||||
@@ -83,14 +83,14 @@ class AppRoutes {
|
||||
return MaterialPageRoute(
|
||||
settings: RouteSettings(arguments: args, name: Routes.NEW_CHAT),
|
||||
builder: (_) {
|
||||
return NewChatScreen();
|
||||
return const NewChatScreen();
|
||||
});
|
||||
case Routes.NEW_GROUP_CHAT:
|
||||
return MaterialPageRoute(
|
||||
settings:
|
||||
RouteSettings(arguments: args, name: Routes.NEW_GROUP_CHAT),
|
||||
builder: (_) {
|
||||
return NewGroupChatScreen();
|
||||
return const NewGroupChatScreen();
|
||||
});
|
||||
case Routes.NEW_GROUP_CHAT_DETAILS:
|
||||
return MaterialPageRoute(
|
||||
@@ -125,7 +125,7 @@ class AppRoutes {
|
||||
settings:
|
||||
RouteSettings(arguments: args, name: Routes.CHANNEL_LIST_PAGE),
|
||||
builder: (context) {
|
||||
return ChannelListPage();
|
||||
return const ChannelListPage();
|
||||
});
|
||||
// Default case, should not reach here.
|
||||
default:
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
/// Application routes
|
||||
abstract class Routes {
|
||||
static const String APP = '/app';
|
||||
|
||||
@@ -9,7 +9,7 @@ final defaultUsers = <String, User>{
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FsdmF0b3JlIn0.pgiJz7sIc7iP29BHKFwe3nLm5-OaR_1l2P-SlgiC9a8':
|
||||
User(
|
||||
id: 'salvatore',
|
||||
extraData: {
|
||||
extraData: const {
|
||||
'name': 'Salvatore Giordano',
|
||||
'image':
|
||||
'https://avatars.githubusercontent.com/u/20601437?s=460&u=3f66c22a7483980624804054ae7f357cf102c784&v=4',
|
||||
@@ -18,7 +18,7 @@ final defaultUsers = <String, User>{
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic2FoaWwifQ.WnIUoB5gR2kcAsFhiDvkiD6zdHXZ-VSU2aQWWkhsvfo':
|
||||
User(
|
||||
id: 'sahil',
|
||||
extraData: {
|
||||
extraData: const {
|
||||
'name': 'Sahil Kumar',
|
||||
'image':
|
||||
'https://avatars.githubusercontent.com/u/25670178?s=400&u=30ded3784d8d2310c5748f263fd5e6433c119aa1&v=4',
|
||||
@@ -27,7 +27,7 @@ final defaultUsers = <String, User>{
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiYmVuIn0.nAz2sNFGQwY7rl2Og2z3TGHUsdpnN53tOsUglJFvLmg':
|
||||
User(
|
||||
id: 'ben',
|
||||
extraData: {
|
||||
extraData: const {
|
||||
'name': 'Ben Golden',
|
||||
'image': 'https://avatars.githubusercontent.com/u/1581974?s=400&v=4',
|
||||
},
|
||||
@@ -35,7 +35,7 @@ final defaultUsers = <String, User>{
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidGhpZXJyeSJ9.lEq6TrZtHzjoNtf7HHRufUPyGo_pa8vg4_XhEBp4ckY':
|
||||
User(
|
||||
id: 'thierry',
|
||||
extraData: {
|
||||
extraData: const {
|
||||
'name': 'Thierry Schellenbach',
|
||||
'image':
|
||||
'https://avatars.githubusercontent.com/u/265409?s=400&u=2d0e3bb1820db992066196bff7b004f0eee8e28d&v=4',
|
||||
@@ -44,7 +44,7 @@ final defaultUsers = <String, User>{
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidG9tbWFzbyJ9.GLSI0ESshERMo2WjUpysD709NEtn1zmGimUN2an7g9o':
|
||||
User(
|
||||
id: 'tommaso',
|
||||
extraData: {
|
||||
extraData: const {
|
||||
'name': 'Tommaso Barbugli',
|
||||
'image': 'https://avatars.githubusercontent.com/u/88735?s=400&v=4',
|
||||
},
|
||||
@@ -52,7 +52,7 @@ final defaultUsers = <String, User>{
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiZGV2ZW4ifQ.z3zI4PqJnNhc-1o-VKcmb6BnnQ0oxFNCRHwEulHqcWc':
|
||||
User(
|
||||
id: 'deven',
|
||||
extraData: {
|
||||
extraData: const {
|
||||
'name': 'Deven Joshi',
|
||||
'image':
|
||||
'https://avatars.githubusercontent.com/u/26357843?s=400&u=0c61d890866e67bf69f58878be58915e9bfd39ee&v=4',
|
||||
@@ -61,7 +61,7 @@ final defaultUsers = <String, User>{
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoibmVldmFzaCJ9.3EdHegTxibrz3A9cTiKmpEyawwcCVB8FXnoFzr4eKvw':
|
||||
User(
|
||||
id: 'neevash',
|
||||
extraData: {
|
||||
extraData: const {
|
||||
'name': 'Neevash Ramdial',
|
||||
'image':
|
||||
'https://avatars.githubusercontent.com/u/25674767?s=400&u=1d7333baf7dd9d143db8bfcdb31a838b89cfff9c&v=4',
|
||||
@@ -70,14 +70,14 @@ final defaultUsers = <String, User>{
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MSJ9.fnelU7HcP7QoEEsCGteNlF1fppofzNlrnpDQuIgeKCU':
|
||||
User(
|
||||
id: 'qatest1',
|
||||
extraData: {
|
||||
extraData: const {
|
||||
'name': 'QA test 1',
|
||||
},
|
||||
),
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoicWF0ZXN0MiJ9.vSCqAEbs2WVmMWsOsa7065Fsjq-rsTih6qsHPynl7XM':
|
||||
User(
|
||||
id: 'qatest2',
|
||||
extraData: {
|
||||
extraData: const {
|
||||
'name': 'QA test 2',
|
||||
},
|
||||
),
|
||||
|
||||
@@ -20,18 +20,23 @@ void showLocalNotification(
|
||||
}
|
||||
if (event.message == null) return;
|
||||
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
final initializationSettingsAndroid =
|
||||
const initializationSettingsAndroid =
|
||||
AndroidInitializationSettings('launch_background');
|
||||
final initializationSettingsIOS = IOSInitializationSettings();
|
||||
final initializationSettings = InitializationSettings(
|
||||
const initializationSettingsIOS = IOSInitializationSettings();
|
||||
const initializationSettings = InitializationSettings(
|
||||
android: initializationSettingsAndroid,
|
||||
iOS: initializationSettingsIOS,
|
||||
);
|
||||
|
||||
final appLocalizations = AppLocalizations.of(context);
|
||||
|
||||
await flutterLocalNotificationsPlugin.initialize(
|
||||
initializationSettings,
|
||||
onSelectNotification: (channelCid) async {
|
||||
if (channelCid != null) {
|
||||
final client = StreamChat.of(context).client;
|
||||
final navigator = Navigator.of(context);
|
||||
|
||||
var channel = client.state.channels[channelCid];
|
||||
|
||||
if (channel == null) {
|
||||
@@ -45,8 +50,7 @@ void showLocalNotification(
|
||||
await channel.watch();
|
||||
}
|
||||
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
navigator.pushNamed(
|
||||
Routes.CHANNEL_PAGE,
|
||||
arguments: ChannelPageArgs(
|
||||
channel: channel,
|
||||
@@ -62,13 +66,12 @@ void showLocalNotification(
|
||||
NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
'message channel',
|
||||
AppLocalizations.of(context).messageChannelName,
|
||||
channelDescription:
|
||||
AppLocalizations.of(context).messageChannelDescription,
|
||||
appLocalizations.messageChannelName,
|
||||
channelDescription: appLocalizations.messageChannelDescription,
|
||||
priority: Priority.high,
|
||||
importance: Importance.high,
|
||||
),
|
||||
iOS: IOSNotificationDetails(),
|
||||
iOS: const IOSNotificationDetails(),
|
||||
),
|
||||
payload: '${event.channelType}:${event.channelId}',
|
||||
);
|
||||
|
||||
@@ -13,21 +13,23 @@ import '../pages/chat_info_screen.dart';
|
||||
import '../pages/group_info_screen.dart';
|
||||
|
||||
class ChannelList extends StatefulWidget {
|
||||
const ChannelList({super.key});
|
||||
|
||||
@override
|
||||
_ChannelList createState() => _ChannelList();
|
||||
State<ChannelList> createState() => _ChannelList();
|
||||
}
|
||||
|
||||
class _ChannelList extends State<ChannelList> {
|
||||
ScrollController _scrollController = ScrollController();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
late StreamMessageSearchListController _messageSearchListController =
|
||||
late final StreamMessageSearchListController _messageSearchListController =
|
||||
StreamMessageSearchListController(
|
||||
client: StreamChat.of(context).client,
|
||||
filter: Filter.in_('members', [StreamChat.of(context).currentUser!.id]),
|
||||
limit: 5,
|
||||
searchQuery: '',
|
||||
sort: [
|
||||
SortOption(
|
||||
const SortOption(
|
||||
'created_at',
|
||||
direction: SortOption.ASC,
|
||||
),
|
||||
@@ -116,7 +118,7 @@ class _ChannelList extends State<ChannelList> {
|
||||
return LayoutBuilder(
|
||||
builder: (context, viewportConstraints) {
|
||||
return SingleChildScrollView(
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: viewportConstraints.maxHeight,
|
||||
@@ -153,6 +155,7 @@ class _ChannelList extends State<ChannelList> {
|
||||
final messageResponse = messageResponses[index];
|
||||
FocusScope.of(context).requestFocus(FocusNode());
|
||||
final client = StreamChat.of(context).client;
|
||||
final navigator = Navigator.of(context);
|
||||
final message = messageResponse.message;
|
||||
final channel = client.channel(
|
||||
messageResponse.channel!.type,
|
||||
@@ -161,8 +164,7 @@ class _ChannelList extends State<ChannelList> {
|
||||
if (channel.state == null) {
|
||||
await channel.watch();
|
||||
}
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
navigator.pushNamed(
|
||||
Routes.CHANNEL_PAGE,
|
||||
arguments: ChannelPageArgs(
|
||||
channel: channel,
|
||||
@@ -192,7 +194,6 @@ class _ChannelList extends State<ChannelList> {
|
||||
motion: const BehindMotion(),
|
||||
children: [
|
||||
CustomSlidableAction(
|
||||
child: Icon(Icons.more_horiz),
|
||||
backgroundColor: backgroundColor,
|
||||
onPressed: (_) {
|
||||
showChannelInfoModalBottomSheet(
|
||||
@@ -236,6 +237,7 @@ class _ChannelList extends State<ChannelList> {
|
||||
},
|
||||
);
|
||||
},
|
||||
child: const Icon(Icons.more_horiz),
|
||||
),
|
||||
if (canDeleteChannel)
|
||||
CustomSlidableAction(
|
||||
|
||||
@@ -68,97 +68,95 @@ class ChipInputTextFieldState<T> extends State<ChipsInputTextField<T>> {
|
||||
child: Material(
|
||||
elevation: 1,
|
||||
color: StreamChatTheme.of(context).colorTheme.barsBg,
|
||||
child: Container(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
child: Text(
|
||||
'${AppLocalizations.of(context).to.toUpperCase()}:',
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.footnote
|
||||
.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(.5)),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
child: Text(
|
||||
'${AppLocalizations.of(context).to.toUpperCase()}:',
|
||||
style: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.footnote
|
||||
.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(.5)),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Wrap(
|
||||
spacing: 8.0,
|
||||
runSpacing: 4.0,
|
||||
children: _chips.map((item) {
|
||||
return widget.chipBuilder(context, item);
|
||||
}).toList(),
|
||||
),
|
||||
if (!_pauseItemAddition)
|
||||
TextField(
|
||||
controller: widget.controller,
|
||||
onChanged: widget.onInputChanged,
|
||||
focusNode: widget.focusNode,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding: const EdgeInsets.only(top: 4.0),
|
||||
hintText: widget.hint,
|
||||
hintStyle: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.body
|
||||
.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(.5)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: IconButton(
|
||||
icon: _chips.isEmpty
|
||||
? StreamSvgIcon.user(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(0.5),
|
||||
size: 24,
|
||||
)
|
||||
: StreamSvgIcon.userAdd(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(0.5),
|
||||
size: 24,
|
||||
),
|
||||
onPressed: resumeItemAddition,
|
||||
alignment: Alignment.topRight,
|
||||
visualDensity: VisualDensity.compact,
|
||||
padding: const EdgeInsets.all(0),
|
||||
splashRadius: 24,
|
||||
constraints: BoxConstraints.tightFor(
|
||||
height: 24,
|
||||
width: 24,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Wrap(
|
||||
spacing: 8.0,
|
||||
runSpacing: 4.0,
|
||||
children: _chips.map((item) {
|
||||
return widget.chipBuilder(context, item);
|
||||
}).toList(),
|
||||
),
|
||||
if (!_pauseItemAddition)
|
||||
TextField(
|
||||
controller: widget.controller,
|
||||
onChanged: widget.onInputChanged,
|
||||
focusNode: widget.focusNode,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding: const EdgeInsets.only(top: 4.0),
|
||||
hintText: widget.hint,
|
||||
hintStyle: StreamChatTheme.of(context)
|
||||
.textTheme
|
||||
.body
|
||||
.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(.5)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: IconButton(
|
||||
icon: _chips.isEmpty
|
||||
? StreamSvgIcon.user(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(0.5),
|
||||
size: 24,
|
||||
)
|
||||
: StreamSvgIcon.userAdd(
|
||||
color: StreamChatTheme.of(context)
|
||||
.colorTheme
|
||||
.textHighEmphasis
|
||||
.withOpacity(0.5),
|
||||
size: 24,
|
||||
),
|
||||
onPressed: resumeItemAddition,
|
||||
alignment: Alignment.topRight,
|
||||
visualDensity: VisualDensity.compact,
|
||||
padding: const EdgeInsets.all(0),
|
||||
splashRadius: 24,
|
||||
constraints: const BoxConstraints.tightFor(
|
||||
height: 24,
|
||||
width: 24,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -41,7 +41,7 @@ class SearchTextField extends StatelessWidget {
|
||||
onChanged: onChanged,
|
||||
decoration: InputDecoration(
|
||||
prefixText: ' ',
|
||||
prefixIconConstraints: BoxConstraints.tight(Size(40, 24)),
|
||||
prefixIconConstraints: BoxConstraints.tight(const Size(40, 24)),
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 8,
|
||||
|
||||
@@ -18,7 +18,7 @@ class StreamVersion extends StatelessWidget {
|
||||
future: rootBundle.loadString('pubspec.lock'),
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return SizedBox();
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
final pubspec = snapshot.data!;
|
||||
|
||||
@@ -39,6 +39,7 @@ dependencies:
|
||||
dev_dependencies:
|
||||
flutter_launcher_icons: ^0.9.2
|
||||
test: any
|
||||
flutter_lints: ^2.0.0
|
||||
|
||||
dependency_overrides:
|
||||
stream_chat:
|
||||
|
||||
Reference in New Issue
Block a user