浏览代码

add components/ModalPortal.js

wudebin 6 月之前
父节点
当前提交
2d1864d49a

+ 193 - 0
Strides-SPAPP/app/components/ModalPortal.js

@@ -0,0 +1,193 @@
+/**
+ * ModalPortal
+ * @邠心vbe on 2022/02/28
+ */
+import React, { Component } from 'react';
+import { StyleSheet, View } from 'react-native';
+import Modal from 'react-native-modal';
+
+let modal
+export default class ModalPortal extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      showDialog: false,
+      showLoading: false,
+      showIOSLoading: false,
+      children: <></>,
+      loadChildren: <></>,
+      loadMessage: "...",
+    };
+    modal = this;
+    this.isHide = true;
+    this.onBack = undefined;
+  }
+
+  static show(children, onBack) {
+    return modal.show(children, onBack);
+  }
+
+  static showLoading(children) {
+    return modal.showLoading(children);
+  }
+
+  static dismiss() {
+    modal.dismiss();
+  }
+
+  static dismissLoading() {
+    modal.dismissLoading();
+  }
+
+  static dismissAll() {
+    modal.dismissAll();
+  }
+
+  static isShowing() {
+    return modal.isShowing();
+  }
+
+  show(children, onBack=undefined) {
+    if (isIOS) {
+      if (!this.isHide) {
+        setTimeout(() => {
+          this.show(children);
+        }, 500);
+        return;
+      }
+      this.setState({
+        showDialog: true,
+        children: children,
+      }, () => {
+        this.onModalShow();
+      })
+    } else {
+      this.setState({
+        showDialog: true,
+        children: children
+      })
+      this.onBack = onBack;
+    }
+  }
+
+  showLoading(children) {
+    if (isIOS) {
+      //console.log("showIOSLoading", children)
+      this.setState({
+        loadChildren: children,
+        showIOSLoading: true
+      })
+    } else {
+      this.setState({
+        showLoading: true,
+        loadChildren: children
+      });
+    }
+  }
+
+  dismiss() {
+    this.setState({
+      showDialog: false
+    })
+    this.onBack = undefined;
+  }
+
+  dismissLoading() {
+    if (isIOS) {
+      this.setState({
+        showIOSLoading: false
+      })
+    } else {
+      this.setState({
+        showLoading: false
+      })
+    }
+  }
+
+  dismissAll() {
+    this.setState({
+      showDialog: false,
+      showLoading: false,
+      showIOSLoading: false
+    })
+  }
+
+  isShowing() {
+    //console.log("[ModalPortal] isShowing", this.state.showDialog);
+    return this.state.showDialog;
+  }
+
+  onBackPress() {
+    if (this.onBack) {
+      this.onBack();
+      return;
+    }
+    if (this.state.showLoading) {
+      this.dismissLoading();
+    } else if (this.state.showDialog) {
+      this.dismiss();
+    }
+  }
+
+  onModalShow() {
+    //console.log('onModalShow', this.isHide);
+    this.isHide = false;
+  }
+
+  onModalHide() {
+    //console.log('onModalHide', this.isHide);
+    this.isHide = true;
+  }
+
+  render() {
+    return (
+      <>
+        <Modal
+          style={{margin: 0, zIndex: 900}}
+          isVisible={this.state.showDialog}
+          deviceHeight={$height + statusHeight}
+          avoidKeyboard={true}
+          animationIn={"fadeIn"}
+          animationOut={"fadeOut"}
+          useNativeDriver={true}
+          statusBarTranslucent={true}
+          onBackButtonPress={() => this.onBackPress()}
+          onModalHide={() => this.onModalHide()}>
+          {this.state.children}
+        </Modal>
+        <Modal
+          style={{margin: 0, zIndex: 901}}
+          isVisible={this.state.showLoading}
+          deviceHeight={$height + statusHeight}
+          animationIn="fadeIn"
+          animationOut="fadeOut"
+          useNativeDriver={true}
+          animationInTiming={80}
+          animationOutTiming={100}
+          statusBarTranslucent={true}
+          onBackButtonPress={() => this.onBackPress()}>
+          {this.state.loadChildren}
+        </Modal>
+        { this.state.showIOSLoading &&
+          <View style={styles.iosLoadingView}>
+            {this.state.loadChildren}
+          </View>
+        }
+      </>
+    );
+  }
+}
+
+const styles = StyleSheet.create({
+  iosLoadingView: {
+    top: 0,
+    left: 0,
+    right: 0,
+    bottom: 0,
+    zIndex: 500,
+    alignItems: 'center',
+    position: 'absolute',
+    justifyContent: 'center',
+    backgroundColor: 'rgba(0,0,0,.7)'
+  }
+})

+ 45 - 0
Strides-SPAPP/app/components/MyModal.js

@@ -0,0 +1,45 @@
+import React from 'react';
+import { StyleSheet, Modal, View, Text } from 'react-native';
+import Dialog from './Dialog';
+
+const MyModal = ({
+  visible=false,
+  style=styles.content,
+  layerStyle=styles.dialog,
+  animationType="fade",
+  onLayerPress,
+  children
+}) => (
+  <Modal
+    visible={visible}
+    transparent={true}
+    animationType={animationType}
+    statusBarTranslucent={true}>
+    <View style={layerStyle}>
+      <Text
+        style={StyleSheet.absoluteFillObject}
+        onPress={onLayerPress}>
+      </Text>
+      <View style={style}>
+        {children}
+      </View>
+    </View>
+  </Modal>
+);
+
+export default MyModal;
+
+const styles = StyleSheet.create({
+  dialog: {
+    flex: 1,
+    alignItems: 'center',
+    justifyContent: 'center',
+    backgroundColor: 'rgba(0,0,0,.5)'
+  },
+  content: {
+    width: Dialog.dialogWidth,
+    borderRadius: isIOS ? 16 : 8,
+    overflow: 'hidden',
+    backgroundColor: colorLight
+  }
+})

+ 84 - 0
Strides-SPAPP/app/components/MyStatusBar.js

@@ -0,0 +1,84 @@
+/**
+ * 自定义状态栏(Android)
+ * @邠心vbe on 2023/02/15
+ */
+import React, { Component } from 'react';
+import { StatusBar } from 'react-native';
+
+let statusBar;
+export default class MyStatusBar extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      statusTheme: "dark-content", //themeStatusBar,
+      statusColor: "transparent", //colorPrimaryDark,
+      isTranslucent: true
+    };
+    statusBar = this;
+  }
+
+  static DARK_STYLE = "dark-content";
+  static LIGHT_STYLE = "light-content";
+  static DEFAULT_STYLE = themeStatusBar;
+
+  /**
+   * 设置状态栏颜色
+   * @param {String} color 颜色值
+   */
+  static setStatusBarColor(color) {
+    statusBar.setStatusBarColor(color);
+  }
+
+  /**
+   * 设置状态栏主题(字体图标颜色)
+   * @param {String} theme 主题:MyStatusBar.DARK_STYLE, MyStatusBar.LIGHT_STYLE
+   */
+  static setStatusBarTheme(theme) {
+    statusBar.setStatusBarTheme(theme);
+  }
+
+  /**
+   * 设置状态栏主题和颜色
+   * @param {*} theme 主题:MyStatusBar.DARK_STYLE, MyStatusBar.LIGHT_STYLE
+   * @param {*} color 颜色
+   */
+  static setStatusBarThemes(theme, color="transparent") {
+    statusBar.setStatusBarThemes(theme, color);
+  }
+
+  /**
+   * 设置透明状态栏
+   */
+  static setTranslucentStatusBar() {
+    statusBar.setStatusBarThemes(MyStatusBar.DARK_STYLE, "transparent", true);
+  }
+
+  setStatusBarColor(color) {
+    this.setState({
+      statusColor: color
+    })
+  }
+
+  setStatusBarTheme(theme) {
+    this.setState({
+      statusTheme: theme
+    })
+  }
+
+  setStatusBarThemes(theme, color, trans=true) {
+    this.setState({
+      statusColor: color,
+      statusTheme: theme,
+      isTranslucent: trans
+    })
+  }
+
+  render() {
+    return (
+      <StatusBar
+        barStyle={this.state.statusTheme}
+        translucent={this.state.isTranslucent}
+        backgroundColor={this.state.statusColor}/>
+    );
+  }
+}

+ 63 - 0
Strides-SPAPP/app/components/ShadowView.js

@@ -0,0 +1,63 @@
+import React from 'react';
+import { StyleSheet, Text, View } from 'react-native';
+import Svg, { Defs, Ellipse, G, LinearGradient, Path, Rect, Stop } from 'react-native-svg';
+
+/**
+ * 阴影组件
+ * @param {offset} 阴影左右偏移量(配合style实现margin)
+ * @returns React Element
+ */
+const ShadowView = ({
+  offset=32,
+  style=styles.shadowView,
+  shadowColor="#888888"
+}) => (
+  <View style={style}>
+    <Svg width={$vw(100)-offset} height={$vw(4.36)} viewBox="0 0 342 15" fill="none">
+      <Path d="M0 0H342V7C342 11.4183 338.418 15 334 15H8.00001C3.58173 15 0 11.4183 0 7V0Z" fill="url(#paint0_linear_4117_1875)"/>
+      <Defs>
+        <LinearGradient id="paint0_linear_4117_1875" x1="171" y1="15" x2="171" y2="0" gradientUnits="userSpaceOnUse">
+          <Stop stopColor="#F9F9F9"/>
+          <Stop offset="1" stopColor={shadowColor}/>
+        </LinearGradient>
+      </Defs>
+    </Svg>
+  </View>
+);
+
+export default ShadowView;
+
+export const ShadowViewV2 = ({
+  offset=42,
+  style=styles.shadowViewV2,
+  shadowColor="#222222"
+}) => (
+  <View style={style}>
+    <Svg width={$vw(100)-offset} height={$vw(4.36)} viewBox="0 0 342 15" fill="none">
+      <Path d="M0 0H342V7C342 11.4183 338.418 15 334 15H8.00001C3.58173 15 0 11.4183 0 7V0Z" fill="url(#paint0_linear_4117_1875)"/>
+      <Defs>
+        <LinearGradient id="paint0_linear_4117_1875" x1="171" y1="15" x2="171" y2="0" gradientUnits="userSpaceOnUse">
+          <Stop stopColor="#ddd"/>
+          <Stop offset="1" stopColor={shadowColor}/>
+        </LinearGradient>
+      </Defs>
+    </Svg>
+  </View>
+);
+
+const styles = StyleSheet.create({
+  shadowView: {
+    opacity: 0.8,
+    marginTop: -6,
+    marginLeft: 16,
+    marginRight: 16
+  },
+  shadowViewV2: {
+    zIndex: 1,
+    opacity: .8,
+    marginTop: -8,
+    marginLeft: 20,
+    marginRight: 20,
+    display: "none"
+  }
+})

+ 53 - 0
Strides-SPAPP/app/components/SiteLabelView.js

@@ -0,0 +1,53 @@
+/**
+ * 站点标签组件
+ * @邠心vbe on 2023/11/30
+ */
+import React from 'react';
+import { StyleSheet } from 'react-native';
+import TextView from './TextView';
+
+const SiteLabelView = ({
+  label,
+  color = textLight,
+  version=1,
+  background = colorPrimary
+}) => {
+  if (label) {
+    return (
+      <TextView
+        style={[
+          version == 2
+          ? style.textV2
+          : style.textV1,
+          {
+            color: color || textLight,
+            backgroundColor: background || colorPrimary
+          }
+        ]}>
+        {label}
+      </TextView>
+    )
+  } else {
+    return <></>
+  }
+};
+
+export default SiteLabelView;
+
+const style = StyleSheet.create({
+  textV1: {
+    height: 22,
+    fontSize: 12,
+    marginRight: 5,
+    marginBottom: 5,
+    borderRadius: 3,
+    ...$padding(0, 6)
+  },
+  textV2: {
+    height: 20,
+    fontSize: 8,
+    marginRight: 6,
+    borderRadius: 30,
+    ...$padding(0, 10)
+  }
+})