index.ios.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. import {StackNavigator, TabNavigator} from 'react-navigation';
  2. import React, {Component} from 'react';
  3. import TitleBar from './app/views/TitleBar';
  4. import ContactsScreen from './app/screens/ContactsScreen';
  5. import FindScreen from './app/screens/FindScreen';
  6. import MeScreen from './app/screens/MeScreen';
  7. import SearchScreen from './app/screens/SearchScreen';
  8. import ContactDetailScreen from './app/screens/ContactDetailScreen';
  9. import ChattingScreen from './app/screens/ChattingScreen';
  10. import MomentScreen from './app/screens/MomentScreen';
  11. import ScanScreen from './app/screens/ScanScreen';
  12. import ScanResultScreen from './app/screens/ScanResultScreen';
  13. import ShoppingScreen from './app/screens/ShoppingScreen';
  14. import CardPackageScreen from './app/screens/CardPackageScreen';
  15. import SplashScreen from './app/screens/SplashScreen';
  16. import LoginScreen from './app/screens/LoginScreen';
  17. import RegisterScreen from './app/screens/RegisterScreen';
  18. import NewFriendsScreen from './app/screens/NewFriendsScreen';
  19. import PersonInfoScreen from './app/screens/PersonInfoScreen';
  20. import PublishMomentScreen from './app/screens/PublishMomentScreen';
  21. import ImageShowScreen from './app/screens/ImageShowScreen';
  22. import ShakeScreen from './app/screens/ShakeScreen';
  23. import SettingsScreen from './app/screens/SettingsScreen';
  24. import StorageUtil from './app/utils/StorageUtil';
  25. import UpgradeModule from './app/utils/UpgradeModule';
  26. import UpgradeDialog from './app/views/UpgradeDialog';
  27. import ConversationUtil from './app/utils/ConversationUtil';
  28. import TimeUtil from './app/utils/TimeUtil';
  29. import CountEmitter from './app/event/CountEmitter';
  30. import Global from './app/utils/Global';
  31. import Utils from './app/utils/Utils';
  32. import Toast from '@remobile/react-native-toast';
  33. import UserInfoUtil from './app/utils/UserInfoUtil';
  34. import {
  35. AppRegistry,
  36. StyleSheet,
  37. Text,
  38. View,
  39. Image,
  40. Dimensions,
  41. PixelRatio,
  42. StatusBar,
  43. FlatList,
  44. TouchableHighlight,
  45. Platform
  46. } from 'react-native';
  47. const {width} = Dimensions.get('window');
  48. export default class HomeScreen extends Component {
  49. static navigationOptions = {
  50. tabBarLabel: '微信',
  51. tabBarIcon: ({focused, tintColor}) => {
  52. if (focused) {
  53. return (
  54. <Image style={styles.tabBarIcon} source={require('./images/ic_weixin_selected.png')}/>
  55. );
  56. }
  57. return (
  58. <Image style={styles.tabBarIcon} source={require('./images/ic_weixin_normal.png')}/>
  59. );
  60. },
  61. };
  62. constructor(props) {
  63. super(props);
  64. this.state = {
  65. checkedUpgrade: true, // 标记是否检查了更新,这里置为true则不会检查更新,设置为false则每次启动时检查更新,该功能默认不开启
  66. recentConversation: []
  67. };
  68. this.registerHXListener();
  69. }
  70. loadConversations(username) {
  71. ConversationUtil.getConversations(username, (result) => {
  72. let count = result.length;
  73. let index = 0;
  74. for (let i = 0; i < count; i++) {
  75. let conversation = result[i];
  76. let chatWithUsername = conversation.conversationId.replace(username, '');
  77. UserInfoUtil.getUserInfo(chatWithUsername, (userInfo) => {
  78. index++;
  79. if (userInfo != null) {
  80. conversation['avatar'] = userInfo.avatar;
  81. conversation['nick'] = userInfo.nick;
  82. }
  83. if (index == count) {
  84. this.setState({recentConversation: result});
  85. ConversationUtil.showConversations();
  86. }
  87. });
  88. }
  89. });
  90. }
  91. registerHXListener() { // 注册环信的消息监听器
  92. WebIM.conn.listen({
  93. // xmpp连接成功
  94. onOpened: (msg) => {
  95. Toast.showShortCenter('onOpend')
  96. // 登录环信服务器成功后回调这里
  97. // 出席后才能接受推送消息
  98. WebIM.conn.setPresence();
  99. },
  100. // 出席消息
  101. onPresence: (msg) => {
  102. },
  103. // 各种异常
  104. onError: (error) => {
  105. Toast.showShortCenter('登录聊天服务器出错');
  106. console.log('onError: ' + JSON.stringify(error));
  107. },
  108. // 连接断开
  109. onClosed: (msg) => {
  110. Toast.showShortCenter('与聊天服务器连接断开');
  111. },
  112. // 更新黑名单
  113. onBlacklistUpdate: (list) => {
  114. },
  115. // 文本消息
  116. onTextMessage: (message) => {
  117. message.conversationId = ConversationUtil.generateConversationId(message.from, message.to);
  118. message.msgType = 'txt';
  119. message.time = TimeUtil.currentTime();
  120. ConversationUtil.addMessage(message, (error) => {
  121. // 重新加载会话
  122. this.loadConversations(this.state.username);
  123. // 若当前在聊天界面,还要通知聊天界面刷新
  124. CountEmitter.emit('notifyChattingRefresh');
  125. });
  126. },
  127. onPictureMessage: (message) => {
  128. message.conversationId = ConversationUtil.generateConversationId(message.from, message.to);
  129. message.msgType = 'img';
  130. message.time = TimeUtil.currentTime();
  131. ConversationUtil.addMessage(message, (error) => {
  132. // 重新加载会话
  133. this.loadConversations(this.state.username);
  134. // 若当前在聊天界面,还要通知聊天界面刷新
  135. CountEmitter.emit('notifyChattingRefresh');
  136. });
  137. }
  138. });
  139. }
  140. componentWillMount() {
  141. CountEmitter.addListener('notifyConversationListRefresh', () => {
  142. // 重新加载会话
  143. this.loadConversations(this.state.username);
  144. });
  145. }
  146. render() {
  147. return (
  148. <View style={styles.container}>
  149. <StatusBar
  150. backgroundColor='#393A3E'
  151. barStyle="light-content"
  152. />
  153. <TitleBar nav={this.props.navigation}/>
  154. <View style={styles.divider}></View>
  155. <View style={styles.content}>
  156. {
  157. this.state.recentConversation.length == 0 ? (
  158. <Text style={styles.emptyHintText}>暂无会话消息</Text>
  159. ) : (
  160. <FlatList
  161. data={this.state.recentConversation}
  162. renderItem={this.renderItem}
  163. keyExtractor={this._keyExtractor}
  164. />
  165. )
  166. }
  167. </View>
  168. <View style={styles.divider}></View>
  169. <View style={{backgroundColor: 'transparent', position: 'absolute', left: 0, top: 0, width: width}}>
  170. <UpgradeDialog ref="upgradeDialog" content={this.state.upgradeContent}/>
  171. </View>
  172. </View>
  173. );
  174. }
  175. unregisterListeners() {
  176. CountEmitter.removeListener('notifyConversationListRefresh', ()=>{});
  177. }
  178. _keyExtractor = (item, index) => item.conversationId
  179. componentDidMount() {
  180. StorageUtil.get('username', (error, object) => {
  181. if (!error && object && object.username) {
  182. this.setState({username: object.username});
  183. this.loadConversations(object.username);
  184. }
  185. });
  186. // 组件挂载完成后检查是否有更新,只针对Android平台检查
  187. if (!this.state.checkedUpgrade) {
  188. if (Platform.OS === 'android') {
  189. UpgradeModule.getVersionCodeName((versionCode, versionName) => {
  190. if (versionCode > 0 && !Utils.isEmpty(versionName)) {
  191. // 请求服务器查询更新
  192. let url = 'http://app.yubo725.top/upgrade?versionCode=' + versionCode + '&versionName=' + versionName;
  193. fetch(url).then((res) => res.json())
  194. .then((json) => {
  195. if (json != null && json.code == 1) {
  196. // 有新版本
  197. let data = json.msg;
  198. if (data != null) {
  199. let newVersionCode = data.versionCode;
  200. let newVersionName = data.versionName;
  201. let newVersionDesc = data.versionDesc;
  202. let downUrl = data.downUrl;
  203. let content = "版本号:" + newVersionCode + "\n\n版本名称:" + newVersionName + "\n\n更新说明:" + newVersionDesc;
  204. this.setState({upgradeContent: content}, () => {
  205. // 显示更新dialog
  206. this.refs.upgradeDialog.showModal();
  207. });
  208. }
  209. }
  210. }).catch((e) => {
  211. })
  212. }
  213. })
  214. }
  215. this.setState({checkedUpgrade: true});
  216. }
  217. }
  218. componentWillUnmount() {
  219. this.unregisterListeners();
  220. }
  221. renderItem = (data) => {
  222. let lastTime = data.item.lastTime;
  223. let lastMsg = data.item.messages[data.item.messages.length - 1];
  224. let contactId = lastMsg.from;
  225. if (contactId == this.state.username) {
  226. contactId = lastMsg.to;
  227. }
  228. let nick = data.item.nick;
  229. if (Utils.isEmpty(nick)) {
  230. nick = contactId;
  231. }
  232. let lastMsgContent = '';
  233. if (lastMsg.msgType == 'txt') {
  234. lastMsgContent = lastMsg.data;
  235. } else if (lastMsg.msgType == 'img') {
  236. lastMsgContent = '[图片]';
  237. }
  238. let avatar = require('./images/ic_list_icon.png');
  239. if (data.item.avatar != null) {
  240. avatar = {uri: data.item.avatar};
  241. }
  242. return (
  243. <View>
  244. <TouchableHighlight underlayColor={Global.touchableHighlightColor}
  245. onPress={() => {
  246. this.props.navigation.navigate('Chatting', {
  247. 'contactId': contactId,
  248. 'name': nick,
  249. 'avatar': avatar
  250. })
  251. }}>
  252. <View style={styles.listItemContainer}>
  253. <Image source={avatar} style={{width: 50, height: 50}}/>
  254. <View style={styles.listItemTextContainer}>
  255. <View style={styles.listItemSubContainer}>
  256. <Text numberOfLines={1} style={styles.listItemTitle}>{nick}</Text>
  257. <Text numberOfLines={1} style={styles.listItemTime}>{TimeUtil.formatChatTime(lastTime)}</Text>
  258. </View>
  259. <View style={styles.listItemSubContainer}>
  260. <Text numberOfLines={1} style={styles.listItemSubtitle}>{lastMsgContent}</Text>
  261. {
  262. data.item.unreadCount > 0 ? (
  263. <View style={styles.redDot}>
  264. <Text style={styles.redDotText}>{data.item.unreadCount}</Text>
  265. </View>
  266. ) : ( null )
  267. }
  268. </View>
  269. </View>
  270. </View>
  271. </TouchableHighlight>
  272. <View style={styles.divider}/>
  273. </View>
  274. );
  275. }
  276. }
  277. const styles = StyleSheet.create({
  278. container: {
  279. flex: 1,
  280. flexDirection: 'column',
  281. justifyContent: 'center',
  282. alignItems: 'center',
  283. },
  284. divider: {
  285. width: width,
  286. height: 1 / PixelRatio.get(),
  287. backgroundColor: Global.dividerColor
  288. },
  289. content: {
  290. flex: 1,
  291. width: width,
  292. flexDirection: 'column',
  293. justifyContent: 'center',
  294. alignItems: 'center',
  295. backgroundColor: Global.pageBackgroundColor
  296. },
  297. listItemContainer: {
  298. flexDirection: 'row',
  299. width: width,
  300. paddingLeft: 15,
  301. paddingRight: 15,
  302. paddingTop: 10,
  303. paddingBottom: 10,
  304. alignItems: 'center',
  305. backgroundColor: '#FFFFFF'
  306. },
  307. listItemTextContainer: {
  308. flexDirection: 'column',
  309. flex: 1,
  310. paddingLeft: 15,
  311. },
  312. listItemSubContainer: {
  313. flexDirection: 'row',
  314. alignItems: 'center',
  315. },
  316. listItemTitle: {
  317. color: '#333333',
  318. fontSize: 16,
  319. flex: 1,
  320. },
  321. listItemTime: {
  322. color: '#999999',
  323. fontSize: 12,
  324. },
  325. listItemSubtitle: {
  326. color: '#999999',
  327. fontSize: 14,
  328. marginTop: 3,
  329. flex: 1,
  330. },
  331. redDot: {
  332. borderRadius: 90,
  333. width: 18,
  334. height: 18,
  335. backgroundColor: '#FF0000',
  336. justifyContent: 'center',
  337. alignItems: 'center'
  338. },
  339. redDotText: {
  340. color: '#FFFFFF',
  341. fontSize: 14,
  342. },
  343. tabBarIcon: {
  344. width: 24,
  345. height: 24,
  346. },
  347. emptyHintText: {
  348. fontSize: 18,
  349. color: '#999999'
  350. }
  351. });
  352. const tabNavigatorScreen = TabNavigator({
  353. Home: {screen: HomeScreen},
  354. Contacts: {screen: ContactsScreen},
  355. Find: {screen: FindScreen},
  356. Me: {screen: MeScreen}
  357. }, {
  358. tabBarOptions: {
  359. activeTintColor: '#45C018',
  360. inactiveTintColor: '#999999',
  361. showIcon: true,
  362. labelStyle: {
  363. fontSize: 12,
  364. marginTop: 0,
  365. marginBottom: 0,
  366. },
  367. style: {
  368. backgroundColor: '#FCFCFC',
  369. paddingBottom: 5
  370. },
  371. tabStyle: {
  372. }
  373. },
  374. tabBarPosition: 'bottom',
  375. });
  376. const MyApp = StackNavigator({
  377. Splash: {screen: SplashScreen},
  378. Home: {screen: tabNavigatorScreen},
  379. Search: {screen: SearchScreen},
  380. ContactDetail: {screen: ContactDetailScreen},
  381. Chatting: {screen: ChattingScreen},
  382. Moment: {screen: MomentScreen},
  383. Scan: {screen: ScanScreen},
  384. ScanResult: {screen: ScanResultScreen},
  385. Shopping: {screen: ShoppingScreen},
  386. CardPackage: {screen: CardPackageScreen},
  387. Login: {screen: LoginScreen},
  388. Register: {screen: RegisterScreen},
  389. NewFriend: {screen: NewFriendsScreen},
  390. PersonInfo: {screen: PersonInfoScreen},
  391. PublishMoment: {screen: PublishMomentScreen},
  392. ImageShow: {screen: ImageShowScreen},
  393. Shake: {screen: ShakeScreen},
  394. Settings: {screen: SettingsScreen}
  395. }, {
  396. headerMode: 'none', // 此参数设置不渲染顶部的导航条
  397. });
  398. AppRegistry.registerComponent('RNWeChat', () => MyApp);