Dialog.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /**
  2. * Dialog
  3. * @邠心vbe on 2021/02/20
  4. */
  5. import React from 'react';
  6. import * as Progress from 'react-native-progress';
  7. import {Pressable, StyleSheet, Text, View, Image} from 'react-native';
  8. import Toast from 'react-native-root-toast';
  9. import utils from '../utils/utils';
  10. import ModalPortal from './ModalPortal';
  11. import Button from './Button';
  12. import TextView from './TextView';
  13. const maxDef = isIOS ? 480 : 540;
  14. var _maxWidth = isIOS ? $vw(75) : $vw(87);
  15. const maxWidth = _maxWidth > maxDef ? maxDef: _maxWidth;
  16. const BUTTON_OK = 'ok';
  17. const BUTTON_CANCEL = 'cancel';
  18. /**
  19. * 显示一个弹窗
  20. * @param {*} props 参数{title, message, ok, cancel, showCancel, callback(button)}
  21. */
  22. const showDialog = (props) => {
  23. var param = {
  24. align: props.align || 'left',
  25. title: props.title || '',
  26. message: props.message || '',
  27. ok: props.ok || $t('nav.ok'),
  28. cancel: props.cancel || $t('nav.cancel'),
  29. showCancel: props.showCancel != undefined ? props.showCancel : true,
  30. callback: props.callback,
  31. onBackPress: props.onBackPress
  32. }
  33. ModalPortal.show((
  34. isIOS ? <IOSDialog {...param}/>
  35. : <AndroidDialog {...param}/>
  36. ), param?.onBackPress);
  37. }
  38. /**
  39. * 显示一个只有确认按钮的弹窗
  40. * @param {}} message 消息
  41. * @param {*} ok 按钮文字
  42. * @param {*} back callback(btn)
  43. */
  44. const showResultDialog = (message, ok, back) => {
  45. var param = {
  46. title: isIOS ? message : '',
  47. message: !isIOS ? message : '',
  48. showCancel: false,
  49. ok: ok || $t('nav.ok'),
  50. callback: back
  51. }
  52. showDialog(param);
  53. }
  54. const showProgressDialog = (message=$t('nav.loading')) => {
  55. //message = message ?? 'Waiting...';
  56. ModalPortal.showLoading((
  57. isIOS ? <IOSProgress message={message}/>
  58. : <AndroidProgress message={message}/>
  59. ));
  60. }
  61. const dismissDialog = () => {
  62. ModalPortal.dismiss();
  63. }
  64. const dismissLoading = () => {
  65. ModalPortal.dismissLoading();
  66. }
  67. const dismissAll = () => {
  68. ModalPortal.dismissAll();
  69. }
  70. const IOSDialog = (props) => {
  71. return (
  72. <View style={iosStyle.modalDialog}>
  73. { props.title != '' &&
  74. <TextView style={iosStyle.title}>{props.title}</TextView>
  75. }
  76. { props.message != '' &&
  77. <TextView style={[
  78. iosStyle.message,
  79. {
  80. textAlign: props.align
  81. }
  82. ]}>
  83. {props.message}
  84. </TextView>
  85. }
  86. <View style={iosStyle.modalFooter}>
  87. <Button
  88. text={props.ok}
  89. style={iosStyle.btnGroup}
  90. viewStyle={iosStyle.btnView}
  91. textStyle={iosStyle.btnConfirm}
  92. onClick={() => {
  93. dismissDialog();
  94. if (props.callback) {
  95. props.callback(BUTTON_OK);
  96. }
  97. }}/>
  98. { props.showCancel &&
  99. <Button
  100. text={props.cancel}
  101. style={[iosStyle.btnGroup, iosStyle.btnRight]}
  102. viewStyle={iosStyle.btnView}
  103. textStyle={iosStyle.btnText}
  104. onClick={() => {
  105. dismissDialog();
  106. if (props.callback) {
  107. props.callback(BUTTON_CANCEL);
  108. }
  109. }}/>
  110. }
  111. </View>
  112. </View>
  113. );
  114. }
  115. const AndroidDialog = (props) => {
  116. return (
  117. <View style={andStyles.modalDialog}>
  118. { props.title != '' &&
  119. <TextView style={andStyles.title}>
  120. {props.title}
  121. </TextView>
  122. }
  123. { props.message != '' &&
  124. <TextView style={[
  125. andStyles.message,
  126. {
  127. textAlign: props.align
  128. }
  129. ]}>
  130. {props.message}
  131. </TextView>
  132. }
  133. <View style={andStyles.modalFooter}>
  134. { props.showCancel &&
  135. <AndroidButton
  136. title={props.cancel}
  137. onPress={() => {
  138. dismissDialog();
  139. if (props.callback) {
  140. props.callback(BUTTON_CANCEL);
  141. }
  142. }}
  143. />
  144. }
  145. <AndroidButton
  146. title={props.ok}
  147. onPress={() => {
  148. dismissDialog();
  149. if (props.callback) {
  150. props.callback(BUTTON_OK);
  151. }
  152. }}
  153. />
  154. </View>
  155. </View>
  156. )
  157. }
  158. const AndroidButton = ({title, onPress}) => {
  159. return (
  160. <View style={andStyles.modalButton}>
  161. <Pressable
  162. style={andStyles.modalPress}
  163. android_ripple={ripple}
  164. onPress={onPress}>
  165. <TextView style={andStyles.modalBtnText}>{title}</TextView>
  166. </Pressable>
  167. </View>
  168. );
  169. }
  170. const IOSProgress = (props) => {
  171. return (
  172. <View style={iosStyle.modalProgress}>
  173. <Image
  174. style={iosStyle.loadingIcon}
  175. source={require('../images/icon/loading.gif')}/>
  176. <TextView
  177. style={iosStyle.proMessage}
  178. onPress={() => {
  179. dismissLoading();
  180. }}>{props.message}</TextView>
  181. </View>
  182. );
  183. }
  184. const AndroidProgress = (props) => {
  185. return (
  186. <View style={andStyles.progressDialog}>
  187. <View style={andStyles.progressView}>
  188. <View style={{
  189. width: 48,
  190. height: 48
  191. }}>
  192. <Progress.CircleSnail
  193. size={48}
  194. duration={667}
  195. thickness={4}
  196. color={[colorAccent]}
  197. direction={'clockwise'}
  198. spinDuration={2000}/>
  199. </View>
  200. <TextView
  201. style={andStyles.proMessage}
  202. onPress={() => {
  203. dismissLoading();
  204. }}>{props.message}</TextView>
  205. </View>
  206. </View>
  207. );
  208. }
  209. const iosStyle = StyleSheet.create({
  210. modalDialog: {
  211. width: maxWidth,
  212. marginLeft: 'auto',
  213. marginRight: 'auto',
  214. borderRadius: 12,
  215. overflow: 'hidden',
  216. backgroundColor: colorLight
  217. },
  218. modalProgress: {
  219. width: 180,
  220. overflow: 'hidden',
  221. alignItems: 'center',
  222. marginLeft: 'auto',
  223. marginRight: 'auto',
  224. borderRadius: 12,
  225. backgroundColor: colorLight
  226. },
  227. loadingIcon: {
  228. width: 80,
  229. height: 80,
  230. transform: [{scale: 1.3}]
  231. },
  232. title: {
  233. color: '#111',
  234. fontSize: 18,
  235. paddingTop: 18,
  236. paddingLeft: 10,
  237. paddingRight: 10,
  238. fontWeight: 'bold',
  239. textAlign: 'center',
  240. },
  241. message: {
  242. color: textPrimary,
  243. fontSize: 14,
  244. paddingTop: 8,
  245. paddingLeft: 20,
  246. paddingRight: 20
  247. },
  248. proMessage: {
  249. color: '#555',
  250. fontSize: 15,
  251. marginTop: -4,
  252. paddingBottom: 14
  253. },
  254. modalFooter: {
  255. width: maxWidth,
  256. marginTop: 18,
  257. borderTopWidth: 1,
  258. borderTopColor: '#EFF1F1',
  259. flexDirection: 'row'
  260. },
  261. btnGroup: {
  262. flex: 1,
  263. borderRadius: 0,
  264. backgroundColor: colorLight
  265. },
  266. btnRight: {
  267. borderLeftWidth: 1,
  268. borderLeftColor: '#EFF1F1'
  269. },
  270. btnView: {
  271. flex: 1,
  272. height: 45,
  273. alignItems: 'center',
  274. justifyContent: 'center'
  275. },
  276. btnText: {
  277. color: '#064FE1',
  278. fontSize: 14,
  279. textAlign: 'center'
  280. },
  281. btnConfirm: {
  282. color: '#064FE1',
  283. fontSize: 14,
  284. fontWeight: 'bold'
  285. }
  286. })
  287. const andStyles = StyleSheet.create({
  288. modalDialog: {
  289. width: maxWidth,
  290. zIndex: 100,
  291. paddingTop: 16,
  292. paddingLeft: 20,
  293. paddingRight: 20,
  294. paddingBottom: 8,
  295. borderRadius: 3,
  296. marginLeft: 'auto',
  297. marginRight: 'auto',
  298. backgroundColor: colorLight
  299. },
  300. progressDialog: {
  301. width: maxWidth,
  302. zIndex: 100,
  303. paddingTop: 16,
  304. paddingLeft: 24,
  305. paddingRight: 24,
  306. paddingBottom: 16,
  307. borderRadius: 3,
  308. marginLeft: 'auto',
  309. marginRight: 'auto',
  310. backgroundColor: colorLight
  311. },
  312. title: {
  313. color: '#000',
  314. paddingBottom: 8,
  315. fontSize: 18
  316. },
  317. message: {
  318. color: textPrimary,
  319. fontSize: 14,
  320. paddingBottom: 8,
  321. },
  322. proMessage: {
  323. flex: 1,
  324. color: textPrimary,
  325. fontSize: 15,
  326. paddingLeft: 24
  327. },
  328. modalFooter: {
  329. paddingTop: 8,
  330. alignItems: 'center',
  331. flexDirection: 'row',
  332. justifyContent: 'flex-end'
  333. },
  334. modalButton: {
  335. marginLeft: 8,
  336. borderRadius: 3,
  337. overflow: 'hidden'
  338. },
  339. modalPress: {
  340. padding: 8
  341. },
  342. modalBtnText: {
  343. fontSize: 14,
  344. color: colorPrimary
  345. },
  346. progressView: {
  347. alignItems: 'center',
  348. flexDirection: 'row'
  349. },
  350. endView: {
  351. width: 16,
  352. paddingTop: 16
  353. },
  354. halfView: {
  355. width: 8,
  356. paddingTop: 8
  357. }
  358. });
  359. export default Dialog = {
  360. dialogWidth: maxWidth,
  361. BUTTON_OK: BUTTON_OK,
  362. BUTTON_CANCEL: BUTTON_CANCEL,
  363. isShowing: ModalPortal.isShowing,
  364. showDialog: showDialog,
  365. dismissAll: dismissAll,
  366. dismissDialog: dismissDialog,
  367. dismissLoading: dismissLoading,
  368. showResultDialog: showResultDialog,
  369. showProgressDialog: showProgressDialog,
  370. modalProps: {
  371. avoidKeyboard: true,
  372. animationIn: "fadeIn",
  373. animationOut: "fadeOut",
  374. propagateSwipe: true,
  375. useNativeDriver: true,
  376. hideModalContentWhileAnimating: true
  377. },
  378. styles: isIOS ? iosStyle : andStyles,
  379. IOSProgress: IOSProgress,
  380. AndroidButton: AndroidButton
  381. }
  382. //Toast显示位置
  383. const toastPosition = isIOS ? 0 : -70;
  384. const getStringMessage = (msg) => {
  385. if (typeof msg == 'object') {
  386. if (msg.err) {
  387. return "" + msg.err;
  388. } else if (msg.msg) {
  389. return "" + msg.msg;
  390. } else if (msg.message) {
  391. return "" + msg.message;
  392. } else {
  393. return JSON.stringify(msg);
  394. }
  395. } else {
  396. return "" + msg;
  397. }
  398. }
  399. export const InitSomething = () => {
  400. global.dialogId = undefined;
  401. global.EndView = ({half=false}) => (
  402. half
  403. ? <View style={andStyles.halfView}/>
  404. : <View style={andStyles.endView}/>
  405. )
  406. global.toastShort = (msg) => {
  407. if (typeof msg !== 'string')
  408. msg = getStringMessage(msg);
  409. if (utils.isNotEmpty(msg)) {
  410. Toast.show(msg, {
  411. duration: Toast.durations.SHORT,
  412. position: toastPosition,
  413. shadow: false,
  414. opacity: 0.85,
  415. textStyle: {
  416. fontSize: 14,
  417. lineHeight: 18
  418. },
  419. backgroundColor: '#222222',
  420. containerStyle: {
  421. paddingLeft: 16,
  422. paddingRight: 16,
  423. borderRadius: 50,
  424. maxHeight: $vh(80)
  425. }
  426. });
  427. }
  428. }
  429. global.toastLong = (msg) => {
  430. if (typeof msg !== 'string')
  431. msg = getStringMessage(msg);
  432. if (utils.isNotEmpty(msg)) {
  433. Toast.show(msg, {
  434. duration: Toast.durations.LONG,
  435. position: toastPosition,
  436. shadow: false,
  437. opacity: 0.85,
  438. textStyle: {
  439. fontSize: 14
  440. },
  441. backgroundColor: '#222222',
  442. containerStyle: {
  443. paddingLeft: 16,
  444. paddingRight: 16,
  445. borderRadius: 50,
  446. maxHeight: $vh(80)
  447. }
  448. });
  449. }
  450. }
  451. }