LogBoxNotificationContainer.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. * @flow strict-local
  8. * @format
  9. */
  10. 'use strict';
  11. import * as React from 'react';
  12. import StyleSheet from '../StyleSheet/StyleSheet';
  13. import View from '../Components/View/View';
  14. import * as LogBoxData from './Data/LogBoxData';
  15. import LogBoxLog from './Data/LogBoxLog';
  16. import LogBoxLogNotification from './UI/LogBoxNotification';
  17. type Props = $ReadOnly<{|
  18. logs: $ReadOnlyArray<LogBoxLog>,
  19. selectedLogIndex: number,
  20. isDisabled?: ?boolean,
  21. |}>;
  22. export function _LogBoxNotificationContainer(props: Props): React.Node {
  23. const {logs} = props;
  24. const onDismissWarns = () => {
  25. LogBoxData.clearWarnings();
  26. };
  27. const onDismissErrors = () => {
  28. LogBoxData.clearErrors();
  29. };
  30. const setSelectedLog = (index: number): void => {
  31. LogBoxData.setSelectedLog(index);
  32. };
  33. function openLog(log: LogBoxLog) {
  34. let index = logs.length - 1;
  35. // Stop at zero because if we don't find any log, we'll open the first log.
  36. while (index > 0 && logs[index] !== log) {
  37. index -= 1;
  38. }
  39. setSelectedLog(index);
  40. }
  41. if (logs.length === 0 || props.isDisabled === true) {
  42. return null;
  43. }
  44. const warnings = logs.filter(log => log.level === 'warn');
  45. const errors = logs.filter(
  46. log => log.level === 'error' || log.level === 'fatal',
  47. );
  48. return (
  49. <View style={styles.list}>
  50. {warnings.length > 0 && (
  51. <View style={styles.toast}>
  52. <LogBoxLogNotification
  53. log={warnings[warnings.length - 1]}
  54. level="warn"
  55. totalLogCount={warnings.length}
  56. onPressOpen={() => openLog(warnings[warnings.length - 1])}
  57. onPressDismiss={onDismissWarns}
  58. />
  59. </View>
  60. )}
  61. {errors.length > 0 && (
  62. <View style={styles.toast}>
  63. <LogBoxLogNotification
  64. log={errors[errors.length - 1]}
  65. level="error"
  66. totalLogCount={errors.length}
  67. onPressOpen={() => openLog(errors[errors.length - 1])}
  68. onPressDismiss={onDismissErrors}
  69. />
  70. </View>
  71. )}
  72. </View>
  73. );
  74. }
  75. const styles = StyleSheet.create({
  76. list: {
  77. bottom: 20,
  78. left: 10,
  79. right: 10,
  80. position: 'absolute',
  81. },
  82. toast: {
  83. borderRadius: 8,
  84. marginBottom: 5,
  85. overflow: 'hidden',
  86. },
  87. });
  88. export default (LogBoxData.withSubscription(
  89. _LogBoxNotificationContainer,
  90. ): React.AbstractComponent<{||}>);