Dialog.js 10 KB

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