Skip to content

Commit aa6648d

Browse files
committedAug 30, 2020
Polling added to example app
1 parent 6a5f488 commit aa6648d

19 files changed

+212
-243
lines changed
 

‎example/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
Demonstrates how to use the sendbird_chat plugin.
44

5+
## Usage
6+
This example app requires the inclusion of a `.env` file located in the example root directory. Simplest option is to add your Sendbird keys to the `.env_sample` file and rename the file to `.env`.
7+
8+
## Polling
9+
Because there doesn't appear to be a public websocket endpoint, this example app polls sendbird periodically for available users and open group channels and every second when the chat window is open.
10+
511
## Getting Started
612

713
This project is a starting point for a Flutter application.

‎example/ios/Flutter/Debug.xcconfig

-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
21
#include "Generated.xcconfig"

‎example/ios/Flutter/Release.xcconfig

-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
21
#include "Generated.xcconfig"

‎example/ios/Podfile

-41
This file was deleted.

‎example/ios/Podfile.lock

-16
This file was deleted.

‎example/ios/Runner.xcodeproj/project.pbxproj

+8-89
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 50;
6+
objectVersion = 46;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -13,7 +13,6 @@
1313
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
1414
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
1515
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16-
D4A9295E937B33D654155169 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E3A8B606E54A2E88EB66C257 /* Pods_Runner.framework */; };
1716
/* End PBXBuildFile section */
1817

1918
/* Begin PBXCopyFilesBuildPhase section */
@@ -32,7 +31,6 @@
3231
/* Begin PBXFileReference section */
3332
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
3433
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
35-
21AED4E5F239DFAF19980177 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
3634
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3735
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
3836
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -44,17 +42,13 @@
4442
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
4543
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
4644
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
47-
AEA3983F690281D74E267B38 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
48-
E3A8B606E54A2E88EB66C257 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
49-
FB9CE378619EFFA96512F321 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
5045
/* End PBXFileReference section */
5146

5247
/* Begin PBXFrameworksBuildPhase section */
5348
97C146EB1CF9000F007C117D /* Frameworks */ = {
5449
isa = PBXFrameworksBuildPhase;
5550
buildActionMask = 2147483647;
5651
files = (
57-
D4A9295E937B33D654155169 /* Pods_Runner.framework in Frameworks */,
5852
);
5953
runOnlyForDeploymentPostprocessing = 0;
6054
};
@@ -78,8 +72,6 @@
7872
9740EEB11CF90186004384FC /* Flutter */,
7973
97C146F01CF9000F007C117D /* Runner */,
8074
97C146EF1CF9000F007C117D /* Products */,
81-
CD0CE6DA9744819482BD45FE /* Pods */,
82-
D378A891AACEBABBC9F1D273 /* Frameworks */,
8375
);
8476
sourceTree = "<group>";
8577
};
@@ -106,40 +98,19 @@
10698
path = Runner;
10799
sourceTree = "<group>";
108100
};
109-
CD0CE6DA9744819482BD45FE /* Pods */ = {
110-
isa = PBXGroup;
111-
children = (
112-
21AED4E5F239DFAF19980177 /* Pods-Runner.debug.xcconfig */,
113-
FB9CE378619EFFA96512F321 /* Pods-Runner.release.xcconfig */,
114-
AEA3983F690281D74E267B38 /* Pods-Runner.profile.xcconfig */,
115-
);
116-
name = Pods;
117-
path = Pods;
118-
sourceTree = "<group>";
119-
};
120-
D378A891AACEBABBC9F1D273 /* Frameworks */ = {
121-
isa = PBXGroup;
122-
children = (
123-
E3A8B606E54A2E88EB66C257 /* Pods_Runner.framework */,
124-
);
125-
name = Frameworks;
126-
sourceTree = "<group>";
127-
};
128101
/* End PBXGroup section */
129102

130103
/* Begin PBXNativeTarget section */
131104
97C146ED1CF9000F007C117D /* Runner */ = {
132105
isa = PBXNativeTarget;
133106
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
134107
buildPhases = (
135-
DDA9D6D3DF913EE48B7F2516 /* [CP] Check Pods Manifest.lock */,
136108
9740EEB61CF901F6004384FC /* Run Script */,
137109
97C146EA1CF9000F007C117D /* Sources */,
138110
97C146EB1CF9000F007C117D /* Frameworks */,
139111
97C146EC1CF9000F007C117D /* Resources */,
140112
9705A1C41CF9048500538489 /* Embed Frameworks */,
141113
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
142-
E99BF84CE2F8B32858186FFA /* [CP] Embed Pods Frameworks */,
143114
);
144115
buildRules = (
145116
);
@@ -226,45 +197,6 @@
226197
shellPath = /bin/sh;
227198
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
228199
};
229-
DDA9D6D3DF913EE48B7F2516 /* [CP] Check Pods Manifest.lock */ = {
230-
isa = PBXShellScriptBuildPhase;
231-
buildActionMask = 2147483647;
232-
files = (
233-
);
234-
inputFileListPaths = (
235-
);
236-
inputPaths = (
237-
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
238-
"${PODS_ROOT}/Manifest.lock",
239-
);
240-
name = "[CP] Check Pods Manifest.lock";
241-
outputFileListPaths = (
242-
);
243-
outputPaths = (
244-
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
245-
);
246-
runOnlyForDeploymentPostprocessing = 0;
247-
shellPath = /bin/sh;
248-
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
249-
showEnvVarsInLog = 0;
250-
};
251-
E99BF84CE2F8B32858186FFA /* [CP] Embed Pods Frameworks */ = {
252-
isa = PBXShellScriptBuildPhase;
253-
buildActionMask = 2147483647;
254-
files = (
255-
);
256-
inputFileListPaths = (
257-
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
258-
);
259-
name = "[CP] Embed Pods Frameworks";
260-
outputFileListPaths = (
261-
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
262-
);
263-
runOnlyForDeploymentPostprocessing = 0;
264-
shellPath = /bin/sh;
265-
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
266-
showEnvVarsInLog = 0;
267-
};
268200
/* End PBXShellScriptBuildPhase section */
269201

270202
/* Begin PBXSourcesBuildPhase section */
@@ -356,22 +288,18 @@
356288
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
357289
CLANG_ENABLE_MODULES = YES;
358290
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
359-
DEVELOPMENT_TEAM = 98C9JXLB72;
360291
ENABLE_BITCODE = NO;
361292
FRAMEWORK_SEARCH_PATHS = (
362293
"$(inherited)",
363294
"$(PROJECT_DIR)/Flutter",
364295
);
365296
INFOPLIST_FILE = Runner/Info.plist;
366-
LD_RUNPATH_SEARCH_PATHS = (
367-
"$(inherited)",
368-
"@executable_path/Frameworks",
369-
);
297+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
370298
LIBRARY_SEARCH_PATHS = (
371299
"$(inherited)",
372300
"$(PROJECT_DIR)/Flutter",
373301
);
374-
PRODUCT_BUNDLE_IDENTIFIER = com.example.sendbirdChatExample;
302+
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
375303
PRODUCT_NAME = "$(TARGET_NAME)";
376304
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
377305
SWIFT_VERSION = 5.0;
@@ -479,8 +407,7 @@
479407
MTL_ENABLE_DEBUG_INFO = NO;
480408
SDKROOT = iphoneos;
481409
SUPPORTED_PLATFORMS = iphoneos;
482-
SWIFT_COMPILATION_MODE = wholemodule;
483-
SWIFT_OPTIMIZATION_LEVEL = "-O";
410+
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
484411
TARGETED_DEVICE_FAMILY = "1,2";
485412
VALIDATE_PRODUCT = YES;
486413
};
@@ -493,22 +420,18 @@
493420
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
494421
CLANG_ENABLE_MODULES = YES;
495422
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
496-
DEVELOPMENT_TEAM = 98C9JXLB72;
497423
ENABLE_BITCODE = NO;
498424
FRAMEWORK_SEARCH_PATHS = (
499425
"$(inherited)",
500426
"$(PROJECT_DIR)/Flutter",
501427
);
502428
INFOPLIST_FILE = Runner/Info.plist;
503-
LD_RUNPATH_SEARCH_PATHS = (
504-
"$(inherited)",
505-
"@executable_path/Frameworks",
506-
);
429+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
507430
LIBRARY_SEARCH_PATHS = (
508431
"$(inherited)",
509432
"$(PROJECT_DIR)/Flutter",
510433
);
511-
PRODUCT_BUNDLE_IDENTIFIER = com.example.sendbirdChatExample;
434+
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
512435
PRODUCT_NAME = "$(TARGET_NAME)";
513436
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
514437
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -524,22 +447,18 @@
524447
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
525448
CLANG_ENABLE_MODULES = YES;
526449
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
527-
DEVELOPMENT_TEAM = 98C9JXLB72;
528450
ENABLE_BITCODE = NO;
529451
FRAMEWORK_SEARCH_PATHS = (
530452
"$(inherited)",
531453
"$(PROJECT_DIR)/Flutter",
532454
);
533455
INFOPLIST_FILE = Runner/Info.plist;
534-
LD_RUNPATH_SEARCH_PATHS = (
535-
"$(inherited)",
536-
"@executable_path/Frameworks",
537-
);
456+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
538457
LIBRARY_SEARCH_PATHS = (
539458
"$(inherited)",
540459
"$(PROJECT_DIR)/Flutter",
541460
);
542-
PRODUCT_BUNDLE_IDENTIFIER = com.example.sendbirdChatExample;
461+
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
543462
PRODUCT_NAME = "$(TARGET_NAME)";
544463
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
545464
SWIFT_VERSION = 5.0;

‎example/ios/Runner.xcworkspace/contents.xcworkspacedata

-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎example/ios/Runner/Info.plist

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<key>CFBundleInfoDictionaryVersion</key>
1212
<string>6.0</string>
1313
<key>CFBundleName</key>
14-
<string>sendbird_chat_example</string>
14+
<string>example</string>
1515
<key>CFBundlePackageType</key>
1616
<string>APPL</string>
1717
<key>CFBundleShortVersionString</key>

‎example/lib/chat.dart

+44-23
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,60 @@ import 'package:provider/provider.dart';
44
import 'sendbird_model.dart';
55
import 'sendbird_message.dart';
66
import 'sendbird_user.dart';
7+
import 'dart:async';
8+
import 'package:focus_detector/focus_detector.dart';
79

810
class ChatPage extends StatefulWidget {
911
@override
1012
ChatState createState() => new ChatState();
1113
}
1214

1315
class ChatState extends State {
16+
Timer timer;
17+
18+
@override
19+
void dispose() {
20+
super.dispose();
21+
timer.cancel();
22+
}
23+
1424
@override
1525
Widget build(BuildContext context) {
1626
final _sendbird = Provider.of<SendbirdModel>(context, listen: true);
17-
return Scaffold(
18-
appBar: AppBar(
19-
title: Text("Chat App"),
20-
),
21-
body: new DashChat(
22-
showUserAvatar: true,
23-
onPressAvatar: (ChatUser user) {
24-
print("OnPressAvatar: ${user.name}");
25-
},
26-
key: Key(_sendbird.channel().channelUrl.toString()),
27-
onSend: (ChatMessage message) async {
28-
print('chat.dart: message to send: $message');
29-
setState(() {
30-
_sendbird.sendOpenChannelMessage(message.text);
31-
});
32-
},
33-
sendOnEnter: true,
34-
textInputAction: TextInputAction.send,
35-
// messages: this.messages,
36-
messages: asDashChatMessages(_sendbird.messages()),
37-
user: asDashChatUser(_sendbird.user()),
38-
inputDecoration:
39-
InputDecoration.collapsed(hintText: "Add message here..."),
27+
final _resumeDetectorKey = UniqueKey();
28+
29+
return FocusDetector(
30+
key: _resumeDetectorKey,
31+
onFocusGained: () {
32+
timer = new Timer.periodic(Duration(seconds: 1), (timer) {
33+
_sendbird.refreshOpenChannelMessages();
34+
});
35+
},
36+
onFocusLost: () {
37+
timer.cancel();
38+
},
39+
child: Scaffold(
40+
appBar: AppBar(
41+
title: Text("${_sendbird.currentChannel.name}"),
42+
),
43+
body: new DashChat(
44+
showUserAvatar: true,
45+
onPressAvatar: (ChatUser user) {
46+
print("OnPressAvatar: ${user.name}");
47+
},
48+
key: Key(_sendbird.channel().channelUrl.toString()),
49+
onSend: (ChatMessage message) async {
50+
setState(() {
51+
_sendbird.sendOpenChannelMessage(message.text);
52+
});
53+
},
54+
sendOnEnter: true,
55+
textInputAction: TextInputAction.send,
56+
messages: asDashChatMessages(_sendbird.messages()),
57+
user: asDashChatUser(_sendbird.user()),
58+
inputDecoration:
59+
InputDecoration.collapsed(hintText: "Add message here..."),
60+
),
4061
),
4162
);
4263
}

‎example/lib/main.dart

+13
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import 'package:flutter/material.dart';
22
import 'dart:async';
33

4+
import 'open_channel_selection.dart';
45
import 'sendbird_model.dart';
56
import 'package:flutter_dotenv/flutter_dotenv.dart';
67
import 'package:provider/provider.dart';
78
import 'user_selection.dart';
89
import 'open_channel_selection.dart';
910
import 'chat.dart';
11+
// import 'route_aware.dart';
12+
13+
// final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
1014

1115
Future main() async {
1216
await DotEnv().load('.env');
@@ -46,6 +50,15 @@ class _MyAppState extends State<MyApp> {
4650
),
4751
debugShowCheckedModeBanner: false,
4852
home: UserSelectionPage(),
53+
// navigatorObservers: [
54+
// routeObserver
55+
// ],
56+
// routes: {
57+
// '/home': (context) =>
58+
// RouteAwareWidget('/home', child: UserSelectionPage()),
59+
// '/open_channel': (context) => RouteAwareWidget('/open_channel',
60+
// child: OpenChannelSelectionPage()),
61+
// }
4962
routes: <String, WidgetBuilder>{
5063
'/home': (context) => UserSelectionPage(),
5164
'/open_channel': (context) => OpenChannelSelectionPage(),

‎example/lib/open_channel_selection.dart

+39-16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
22
import 'package:provider/provider.dart';
33
import 'sendbird_model.dart';
44
import 'sendbird_channel.dart';
5+
import 'dart:async';
6+
import 'package:focus_detector/focus_detector.dart';
57

68
class OpenChannelSelectionPage extends StatefulWidget {
79
@override
@@ -10,27 +12,48 @@ class OpenChannelSelectionPage extends StatefulWidget {
1012

1113
class OpenChannelState extends State {
1214
TextEditingController _textFieldController = TextEditingController();
15+
Timer timer;
16+
17+
@override
18+
void dispose() {
19+
// TODO: implement dispose
20+
super.dispose();
21+
timer.cancel();
22+
}
1323

1424
@override
1525
Widget build(BuildContext context) {
1626
final _sendbird = Provider.of<SendbirdModel>(context, listen: true);
27+
final _resumeDetectorKey = UniqueKey();
1728

18-
return Scaffold(
19-
appBar: AppBar(title: Text("Select an Open Group")),
20-
body: ListView.builder(
21-
padding: const EdgeInsets.all(8),
22-
itemCount: _sendbird.channels().length,
23-
itemBuilder: (BuildContext context, int index) {
24-
SendbirdChannel channel = _sendbird.channels()[index];
25-
return Column(
26-
children: [_row(context, channel, _sendbird)],
27-
);
28-
}),
29-
floatingActionButton: FloatingActionButton(
30-
onPressed: () {
31-
_displayDialog(context, _sendbird);
32-
},
33-
child: Icon(Icons.add)),
29+
return FocusDetector(
30+
key: _resumeDetectorKey,
31+
onFocusGained: () {
32+
timer = new Timer.periodic(Duration(seconds: 5), (timer) {
33+
_sendbird.refreshOpenChannels();
34+
});
35+
},
36+
onFocusLost: () {
37+
timer.cancel();
38+
},
39+
child: Scaffold(
40+
appBar: AppBar(
41+
title: Text("${_sendbird.currentUser.nickname}'s Open Groups")),
42+
body: ListView.builder(
43+
padding: const EdgeInsets.all(8),
44+
itemCount: _sendbird.channels().length,
45+
itemBuilder: (BuildContext context, int index) {
46+
SendbirdChannel channel = _sendbird.channels()[index];
47+
return Column(
48+
children: [_row(context, channel, _sendbird)],
49+
);
50+
}),
51+
floatingActionButton: FloatingActionButton(
52+
onPressed: () {
53+
_displayDialog(context, _sendbird);
54+
},
55+
child: Icon(Icons.add)),
56+
),
3457
);
3558
}
3659

‎example/lib/sendbird_model.dart

+35-15
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import 'package:flutter/foundation.dart';
22
import 'package:flutter/material.dart';
33
import 'package:sendbird_chat/sendbird_chat.dart';
4-
import 'sendbird_user.dart';
54
import 'sendbird_channel.dart';
65
import 'sendbird_message.dart';
6+
import 'sendbird_user.dart';
77

88
class SendbirdModel extends ChangeNotifier {
99
SendbirdChat _chat;
1010
List<SendbirdUser> _users = new List<SendbirdUser>();
1111
List<SendbirdChannel> _openChannels = new List<SendbirdChannel>();
12-
SendbirdUser _currentUser;
13-
SendbirdChannel _currentChannel = new SendbirdChannel("", "", []);
12+
SendbirdUser currentUser;
13+
SendbirdChannel currentChannel = new SendbirdChannel("", "", []);
1414
List<SendbirdMessage> _currentMessages = new List<SendbirdMessage>();
1515

1616
void init(String appId, String token) async {
@@ -20,8 +20,14 @@ class SendbirdModel extends ChangeNotifier {
2020
refreshUsers() async {
2121
// TODO: Error handling
2222
List currentUsers = await _chat.listUsers();
23-
_users = [];
24-
currentUsers.forEach((user) => _users.add(SendbirdUser.fromJson(user)));
23+
List<SendbirdUser> newUsers = [];
24+
currentUsers.forEach((user) => newUsers.add(SendbirdUser.fromJson(user)));
25+
// TODO: Actually check content
26+
if (newUsers.length == _users.length) {
27+
print('sendbird_model.dart: refreshUsers: no change in users list.');
28+
return;
29+
}
30+
_users = newUsers;
2531
notifyListeners();
2632
}
2733

@@ -43,9 +49,15 @@ class SendbirdModel extends ChangeNotifier {
4349

4450
refreshOpenChannels() async {
4551
List currentChannels = await _chat.listOpenChannels();
46-
_openChannels = [];
52+
List<SendbirdChannel> newChannels = [];
4753
currentChannels.forEach(
48-
(channel) => _openChannels.add(SendbirdChannel.fromJson(channel)));
54+
(channel) => newChannels.add(SendbirdChannel.fromJson(channel)));
55+
// TODO: Actually check contents
56+
if (newChannels.length == _openChannels.length) {
57+
print('sendbird_model.dart: refreshOpenChannels: no change in channels');
58+
return;
59+
}
60+
_openChannels = newChannels;
4961
notifyListeners();
5062
}
5163

@@ -55,12 +67,12 @@ class SendbirdModel extends ChangeNotifier {
5567
}
5668

5769
SendbirdChannel channel() {
58-
return this._currentChannel;
70+
return this.currentChannel;
5971
}
6072

6173
void setChannel(SendbirdChannel channel) {
6274
this._currentMessages.clear();
63-
this._currentChannel = channel;
75+
this.currentChannel = channel;
6476
}
6577

6678
Future createOpenChannel(String name, List<SendbirdUser> users) async {
@@ -78,7 +90,7 @@ class SendbirdModel extends ChangeNotifier {
7890

7991
// MESSAGES
8092
Future<List<SendbirdMessage>> getOpenChannelMessages() async {
81-
String channelUrl = this._currentChannel.channelUrl;
93+
String channelUrl = this.currentChannel.channelUrl;
8294
List messages = await this._chat.getOpenChannelMessages(channelUrl);
8395
List<SendbirdMessage> result = new List<SendbirdMessage>();
8496
if (messages.length > 0) {
@@ -89,14 +101,22 @@ class SendbirdModel extends ChangeNotifier {
89101
}
90102

91103
Future<void> refreshOpenChannelMessages() async {
92-
this._currentMessages = await getOpenChannelMessages();
104+
List<SendbirdMessage> newMessages = await getOpenChannelMessages();
105+
// TODO; Actually check message contents
106+
if (newMessages.length == this._currentMessages.length) {
107+
// No change, ignore.
108+
print(
109+
'sendbird_model.dart: refreshOpenChannelMessages: no change in messages');
110+
return;
111+
}
112+
this._currentMessages = newMessages;
93113
notifyListeners();
94114
}
95115

96116
Future<void> sendOpenChannelMessage(String message) async {
97117
await this._chat.sendOpenChannelMessage(
98-
channelUrl: this._currentChannel.channelUrl,
99-
originUserId: this._currentUser.userId,
118+
channelUrl: this.currentChannel.channelUrl,
119+
originUserId: this.currentUser.userId,
100120
message: message);
101121
List<SendbirdMessage> messages = await getOpenChannelMessages();
102122
this._currentMessages.clear();
@@ -109,10 +129,10 @@ class SendbirdModel extends ChangeNotifier {
109129
}
110130

111131
SendbirdUser user() {
112-
return this._currentUser;
132+
return this.currentUser;
113133
}
114134

115135
void setUser(SendbirdUser user) {
116-
this._currentUser = user;
136+
this.currentUser = user;
117137
}
118138
}

‎example/lib/user_selection.dart

+37-17
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,56 @@ import 'package:flutter/material.dart';
22
import 'package:provider/provider.dart';
33
import 'sendbird_user.dart';
44
import 'sendbird_model.dart';
5+
import 'dart:async';
6+
import 'package:focus_detector/focus_detector.dart';
57

68
class UserSelectionPage extends StatefulWidget {
79
@override
810
UserSelectionState createState() => new UserSelectionState();
911
}
1012

1113
class UserSelectionState extends State {
12-
// class UserSelectionPage extends StatelessWidget {
1314
TextEditingController _textFieldController = TextEditingController();
15+
Timer timer;
16+
17+
@override
18+
void dispose() {
19+
super.dispose();
20+
timer.cancel();
21+
}
1422

1523
@override
1624
Widget build(BuildContext context) {
1725
final _sendbird = Provider.of<SendbirdModel>(context, listen: true);
26+
final _resumeDetectorKey = UniqueKey();
1827

19-
return Scaffold(
20-
appBar: AppBar(title: Text("Select a User")),
21-
body: ListView.builder(
22-
padding: const EdgeInsets.all(8),
23-
itemCount: _sendbird.users().length,
24-
itemBuilder: (BuildContext context, int index) {
25-
SendbirdUser user = _sendbird.users()[index];
26-
return Column(
27-
children: [_row(context, user, _sendbird)],
28-
);
29-
}),
30-
floatingActionButton: FloatingActionButton(
31-
onPressed: () {
32-
_displayDialog(context, _sendbird);
33-
},
34-
child: Icon(Icons.add)),
28+
return FocusDetector(
29+
key: _resumeDetectorKey,
30+
onFocusGained: () {
31+
timer = new Timer.periodic(Duration(seconds: 8), (timer) {
32+
_sendbird.refreshUsers();
33+
});
34+
},
35+
onFocusLost: () {
36+
timer.cancel();
37+
},
38+
child: Scaffold(
39+
appBar: AppBar(title: Text("Select a User")),
40+
body: ListView.builder(
41+
padding: const EdgeInsets.all(8),
42+
itemCount: _sendbird.users().length,
43+
itemBuilder: (BuildContext context, int index) {
44+
SendbirdUser user = _sendbird.users()[index];
45+
return Column(
46+
children: [_row(context, user, _sendbird)],
47+
);
48+
}),
49+
floatingActionButton: FloatingActionButton(
50+
onPressed: () {
51+
_displayDialog(context, _sendbird);
52+
},
53+
child: Icon(Icons.add)),
54+
),
3555
);
3656
}
3757

‎example/pubspec.lock

+18-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ packages:
77
name: async
88
url: "https://pub.dartlang.org"
99
source: hosted
10-
version: "2.4.1"
10+
version: "2.4.2"
1111
boolean_selector:
1212
dependency: transitive
1313
description:
@@ -102,6 +102,13 @@ packages:
102102
description: flutter
103103
source: sdk
104104
version: "0.0.0"
105+
focus_detector:
106+
dependency: "direct main"
107+
description:
108+
name: focus_detector
109+
url: "https://pub.dartlang.org"
110+
source: hosted
111+
version: "1.0.3"
105112
http:
106113
dependency: transitive
107114
description:
@@ -171,7 +178,7 @@ packages:
171178
path: ".."
172179
relative: true
173180
source: path
174-
version: "0.0.1"
181+
version: "0.0.2"
175182
sky_engine:
176183
dependency: transitive
177184
description: flutter
@@ -190,7 +197,7 @@ packages:
190197
name: stack_trace
191198
url: "https://pub.dartlang.org"
192199
source: hosted
193-
version: "1.9.3"
200+
version: "1.9.5"
194201
stream_channel:
195202
dependency: transitive
196203
description:
@@ -247,6 +254,13 @@ packages:
247254
url: "https://pub.dartlang.org"
248255
source: hosted
249256
version: "2.0.8"
257+
visibility_detector:
258+
dependency: transitive
259+
description:
260+
name: visibility_detector
261+
url: "https://pub.dartlang.org"
262+
source: hosted
263+
version: "0.1.5"
250264
sdks:
251265
dart: ">=2.9.0-14.0.dev <3.0.0"
252-
flutter: ">=1.16.0"
266+
flutter: ">=1.16.0 <2.0.0"

‎example/pubspec.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ dependencies:
1212
flutter:
1313
sdk: flutter
1414
flutter_dotenv: ^2.1.0
15+
focus_detector: ^1.0.3
1516
provider: ^4.0.2
1617
dash_chat: ^1.1.14
1718

‎lib/rest.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Rest {
1717
print('rest.dart: postTo: $url: Non 200 response recevied: $json');
1818
return;
1919
}
20-
print('rest.dart: postTo: $url successful: response: $response');
20+
// print('rest.dart: postTo: $url successful: response: $response');
2121
String responseBody = response.body;
2222
return json.decode(responseBody);
2323
}
@@ -31,7 +31,7 @@ class Rest {
3131
print('rest.dart: getFrom: $url: Non 200 response: $code: body: $body');
3232
return {};
3333
}
34-
print('rest.dart: getFrom: $url: successful.');
34+
// print('rest.dart: getFrom: $url: successful.');
3535
return json.decode(body);
3636
}
3737

‎lib/sendbird_chat.dart

+5-11
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ class SendbirdChat {
1111
String _openChannelsApi;
1212
Map<String, String> _defaultHeaders;
1313
Rest _rest = Rest();
14+
Timer timer;
1415

15-
SendbirdChat({String applicationId, String apiToken}) {
16+
SendbirdChat({
17+
String applicationId,
18+
String apiToken,
19+
}) {
1620
this._usersApi = "https://api-$applicationId.sendbird.com/v3/users/";
1721
this._openChannelsApi =
1822
"https://api-$applicationId.sendbird.com/v3/open_channels/";
@@ -25,7 +29,6 @@ class SendbirdChat {
2529
// USERS
2630
Future listUsers() async {
2731
var result = await this._rest.getFrom(this._usersApi, this._defaultHeaders);
28-
print('sendbird_chat.dart: listUsers: result: $result');
2932
return result["users"];
3033
}
3134

@@ -37,23 +40,20 @@ class SendbirdChat {
3740
};
3841
var result =
3942
await this._rest.postTo(this._usersApi, this._defaultHeaders, body);
40-
print('sendbird_chat.dart: createUser: result: $result');
4143
return result;
4244
}
4345

4446
Future<bool> deleteUser(String userId) async {
4547
String parentURL = this._usersApi;
4648
String finalURL = '$parentURL$userId';
4749
var result = await this._rest.delete(finalURL, this._defaultHeaders);
48-
print('sendbird_chat.dart: deleteUser: url: $finalURL result: $result');
4950
return result;
5051
}
5152

5253
// OPEN CHANNELS
5354
Future<List> listOpenChannels() async {
5455
var result =
5556
await this._rest.getFrom(this._openChannelsApi, this._defaultHeaders);
56-
print('sendbird_chat.dart: listOpenChannels: result: $result');
5757
return result["channels"];
5858
}
5959

@@ -65,16 +65,13 @@ class SendbirdChat {
6565
var result = await this
6666
._rest
6767
.postTo(this._openChannelsApi, this._defaultHeaders, body);
68-
print('sendbird_chat.dart: createOpenChannel: result: $result');
6968
return result;
7069
}
7170

7271
Future<bool> deleteOpenChannel(String channelUrl) async {
7372
String parentURL = this._openChannelsApi;
7473
String finalURL = '$parentURL$channelUrl';
7574
var result = await this._rest.delete(finalURL, this._defaultHeaders);
76-
print(
77-
'sendbird_chat.dart: deleteOpenChannel: url: $finalURL result: $result');
7875
return result;
7976
}
8077

@@ -83,8 +80,6 @@ class SendbirdChat {
8380
String now = DateTime.now().toUtc().millisecondsSinceEpoch.toString();
8481
String finalURL = '$parentURL$channelUrl/messages?message_ts=$now';
8582
var result = await this._rest.getFrom(finalURL, this._defaultHeaders);
86-
print(
87-
'sendbird_chat.dart: getOpenChannelMessages: url: $finalURL, result: $result');
8883
return result["messages"];
8984
}
9085

@@ -98,7 +93,6 @@ class SendbirdChat {
9893
'message': message,
9994
};
10095
var result = await this._rest.postTo(finalURL, this._defaultHeaders, body);
101-
print('sendbird_chat.dart: getOpenChannel: url: $finalURL result: $result');
10296
return result;
10397
}
10498
}

‎pubspec.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ packages:
77
name: async
88
url: "https://pub.dartlang.org"
99
source: hosted
10-
version: "2.4.1"
10+
version: "2.4.2"
1111
boolean_selector:
1212
dependency: transitive
1313
description:
@@ -120,7 +120,7 @@ packages:
120120
name: stack_trace
121121
url: "https://pub.dartlang.org"
122122
source: hosted
123-
version: "1.9.3"
123+
version: "1.9.5"
124124
stream_channel:
125125
dependency: transitive
126126
description:

‎pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: sendbird_chat
22
description: A flutter plugin for utilizing sendbird's chat platform API.
3-
version: 0.0.1
3+
version: 0.0.2
44
homepage: https://github.com/jalakoo/sendbird_chat
55

66
environment:

0 commit comments

Comments
 (0)
Please sign in to comment.