瀏覽代碼

enhancement map upcoming

vbea 2 年之前
父節點
當前提交
40e6b5a943

+ 2 - 1
Strides-APP/app/i18n/locales/en.js

@@ -408,7 +408,8 @@ export default {
     refreshInterval: "Refresh site interval",
     seconds: "s",
     showMyLocations: "Always show my locations",
-    moveMyLocations: "Move to my locations when refresh"
+    moveMyLocations: "Move to my locations when refresh",
+    useApplesMap: "Use Apple's Map"
   },
   feedback: {
     errFeedbackType: "Please select type of feedback",

+ 2 - 1
Strides-APP/app/i18n/locales/zh-TW.js

@@ -408,7 +408,8 @@ export default {
     refreshInterval: "站點刷新間隔",
     seconds: "秒",
     showMyLocations: "顯示我的位置",
-    moveMyLocations: "刷新時移動到我的位置"
+    moveMyLocations: "刷新時移動到我的位置",
+    useApplesMap: "使用蘋果內嵌地圖"
   },
   feedback: {
     errFeedbackType: "請選擇反饋類型",

+ 2 - 1
Strides-APP/app/i18n/locales/zh.js

@@ -408,7 +408,8 @@ export default {
     refreshInterval: "站点刷新间隔",
     seconds: "秒",
     showMyLocations: "显示我的位置",
-    moveMyLocations: "刷新时移动到我的位置"
+    moveMyLocations: "刷新时移动到我的位置",
+    useApplesMap: "使用苹果地图"
   },
   feedback: {
     errFeedbackType: "请选择反馈类型",

+ 12 - 0
Strides-APP/app/pages/Settings.js

@@ -44,6 +44,7 @@ export default class Settings extends Component {
       settings: {
         alwaysLocation: true,
         moveMyLocation: true,
+        useApplesMap: false,
         refreshInterval: undefined
       },
       userInfo: {
@@ -241,6 +242,17 @@ export default class Settings extends Component {
             value={this.state.settings.moveMyLocation}
             onValueChange={v => this.changeSwitch('moveMyLocation', v)}/>
         </Button>
+        { isIOS &&
+          <Button
+            style={styles.itemButton}
+            viewStyle={styles.itemView}
+            onClick={() => this.changeSwitch('useApplesMap', !this.state.settings.useApplesMap)}>
+            <TextView style={styles.buttonText}>{$t('settings.useApplesMap')}</TextView>
+            <Switch
+              value={this.state.settings.useApplesMap}
+              onValueChange={v => this.changeSwitch('useApplesMap', v)}/>
+          </Button>
+        }
       </View>
     );
   }

+ 7 - 1
Strides-APP/app/pages/bookmark/Bookmarks.js

@@ -71,6 +71,8 @@ export default class Bookmarks extends Component {
             dcConnector: item.dcConnector,
             siteType: item.siteType,
             favorite: item.favorite,
+            upcoming: item.upcoming,
+            labels: item.labels,
             distance: utils.getDistance(item.distance),
             serviceProvider: item.serviceProvider
           });
@@ -105,7 +107,11 @@ export default class Bookmarks extends Component {
   }
 
   intoStation(info) {
-    startPage(PageList.chargeDetailPage, {stationInfo: info, action: "bookmarks"});
+    if (info.upcoming) {
+      toastShort($t("home.upcoming"))
+    } else {
+      startPage(PageList.chargeDetailPage, {stationInfo: info, action: "bookmarks"});
+    }
   }
 
   listItem = (props) => {

+ 1 - 0
Strides-APP/app/pages/home/Home.js

@@ -450,6 +450,7 @@ export default class HomePage extends Component {
           onFavorite={() => this.favoriteSite()}
           onCloseInfo={() => this.onCloseInfo()}
           onLocation={() => this.checkPermission2Geo(true)}
+          useApplesMap={this.settingInfo.useApplesMap}
           showUserLocation={this.state.hasPermission && this.settingInfo.alwaysLocation}
           viewChargeStation={id => this.viewChargeStation(id)}
         />

+ 2 - 0
Strides-APP/app/pages/home/MapUI.js

@@ -18,6 +18,7 @@ export default MapUI = ({
   onFavorite,
   onLocation,
   onCloseInfo,
+  useApplesMap,
   showUserLocation,
   viewChargeStation
 }) => {
@@ -67,6 +68,7 @@ export default MapUI = ({
           region={state.region}
           stopList={state.stopList}
           onMapReady={onMapReady}
+          useApplesMap={useApplesMap}
           onMarkerPress={viewChargeStation}
           showUserLocation={showUserLocation}
         />

+ 62 - 45
Strides-APP/app/pages/home/maps/Cluster.js

@@ -8,35 +8,50 @@ import { Marker } from 'react-native-maps';
 
 
 export const MyMarker = ({id, coordinate, onPress}) => {
-  return (
-    <Marker
-      key={id}
-      zIndex={1}
-      coordinate={coordinate}
-      onPress={onPress}>
-      { coordinate.hasLabel &&
+  if (coordinate.upcoming) {
+    return (
+      <Marker
+        key={id}
+        zIndex={1}
+        coordinate={coordinate}
+        onPress={onPress}>
         <Image
-          style={styles.markerTop}
-          source={require('../../../images/maps/ic_marker_additional.png')}/>
-      }
-      { coordinate.favorite
-        ? coordinate.available
-          ? <Image
-              style={styles.marker}
-              source={require('../../../images/maps/ic_marker_star.png')}/>
-          : <Image
-              style={styles.marker}
-              source={require('../../../images/maps/ic_marker_unstar.png')}/>
-        : coordinate.available
-          ? <Image
-              style={styles.marker}
-              source={require('../../../images/maps/ic_marker.png')}/>
-          : <Image
-              style={styles.marker}
-              source={require('../../../images/maps/ic_marker_un.png')}/>
-      }
-    </Marker>
-  )
+          style={styles.marker}
+          source={require('../../../images/maps/ic_marker_upcoming.png')}/>
+      </Marker>
+    )
+  } else {
+    return (
+      <Marker
+        key={id}
+        zIndex={1}
+        coordinate={coordinate}
+        onPress={onPress}
+        style={ui.center}>
+        { coordinate.hasLabel &&
+          <Image
+            style={styles.markerTop}
+            source={require('../../../images/maps/ic_marker_additional.png')}/>
+        }
+        { coordinate.favorite
+          ? coordinate.available
+            ? <Image
+                style={styles.marker}
+                source={require('../../../images/maps/ic_marker_star.png')}/>
+            : <Image
+                style={styles.marker}
+                source={require('../../../images/maps/ic_marker_unstar.png')}/>
+          : coordinate.available
+            ? <Image
+                style={styles.marker}
+                source={require('../../../images/maps/ic_marker.png')}/>
+            : <Image
+                style={styles.marker}
+                source={require('../../../images/maps/ic_marker_un.png')}/>
+        }
+      </Marker>
+    )
+  }
 }
 
 export const MyCluster = (props) => {
@@ -70,9 +85,8 @@ export const ClusterView = ({pointCount, available=false}) => {
     <ImageBackground
       style={getStyle(pointCount)}
       source={available
-      ? require('../../../images/maps/ic_cluster.png')
-      : require('../../../images/maps/ic_cluster_un.png')}
-    >
+            ? require('../../../images/maps/ic_cluster.png')
+            : require('../../../images/maps/ic_cluster_un.png')}>
       <Text style={available ? styles.textAvailable : styles.textUnavailable}>{pointCount}</Text>
     </ImageBackground>
   );
@@ -80,33 +94,36 @@ export const ClusterView = ({pointCount, available=false}) => {
 
 const styles = StyleSheet.create({
   marker: {
-    width: 29.52,
-    height: 34.28
+    width: 48,
+    height: 48
   },
   markerTop: {
-    width: 29.52,
-    height: 34.28
+    width: 24,
+    height: 24,
+    marginBottom: -2
   },
   small: {
-    width: 29.52,
-    height: 34.28
+    width: 48,
+    height: 48
   },
   middle: {
-    width: 31,
-    height: 36
+    width: 50,
+    height: 50
   },
   large: {
-    width: 34.1,
-    height: 39.6
+    width: 52,
+    height: 52
   },
   textAvailable: {
     color: textLight,
-    fontSize: 16,
-    paddingBottom: 7
+    fontSize: 18,
+    fontWeight: 'bold',
+    paddingBottom: 10
   },
   textUnavailable: {
     color: '#999',
-    fontSize: 16,
-    paddingBottom: 7
+    fontSize: 18,
+    fontWeight: 'bold',
+    paddingBottom: 10
   }
 })

+ 17 - 16
Strides-APP/app/pages/home/maps/Maps3.js

@@ -3,12 +3,13 @@
  * @邠心vbe on 2021/03/18
  */
 import React, { useEffect, useRef } from 'react';
-import { PROVIDER_GOOGLE } from 'react-native-maps';
+import { PROVIDER_DEFAULT, PROVIDER_GOOGLE } from 'react-native-maps';
 import MapView from "react-native-map-clustering";
 import { MyCluster, MyMarker } from './Cluster';
-import VbeClusterMap from 'vbe-cluster-map'
+import VbeClusterMap from 'vbe-cluster-map';
+import app from '../../../../app.json';
 
-export default Maps3 = ({ region, onMapReady, stopList, showUserLocation=true, onMarkerPress }) => {
+export default Maps3 = ({ region, onMapReady, stopList, useApplesMap, showUserLocation=true, onMarkerPress }) => {
   const mapRef = useRef();
   const superClusterRef = useRef();
 
@@ -72,19 +73,19 @@ export default Maps3 = ({ region, onMapReady, stopList, showUserLocation=true, o
   return (
     isIOS
     ? <MapView
-      ref={mapRef}
-      superClusterRef={superClusterRef}
-      style={ui.flex1}
-      minZoom={10}
-      maxZoom={15}
-      radius={45}
-      extent={512}
-      nodeSize={64}
-      provider={PROVIDER_GOOGLE}
-      onMapReady={onMapReady}
-      showsUserLocation={showUserLocation}
-      initialRegion={region}
-      renderCluster={(info) => renderCluster(info)}>
+        ref={mapRef}
+        superClusterRef={superClusterRef}
+        style={ui.flex1}
+        minZoom={5}
+        maxZoom={16}
+        radius={45}
+        extent={app.modules.nationally ? 100 : 512}
+        nodeSize={64}
+        provider={useApplesMap ? PROVIDER_DEFAULT : PROVIDER_GOOGLE}
+        onMapReady={onMapReady}
+        showsUserLocation={showUserLocation}
+        initialRegion={region}
+        renderCluster={(info) => renderCluster(info)}>
       { stopList.map((marker, index) => {
         return (
           <MyMarker

+ 80 - 38
Strides-APP/app/pages/search/ListViewV2.js

@@ -3,10 +3,9 @@
  * @邠心vbe on 2023/02/03
  */
 import React from 'react';
-import { Pressable, StyleSheet, Text, View } from 'react-native';
+import { Pressable, StyleSheet, View } from 'react-native';
 import TextView from '../../components/TextView';
 import utils from '../../utils/utils';
-import Provider from '../charge/Provider';
 import ConnectType from './ConnectType';
 import app from '../../../app.json';
 import Button from '../../components/Button';
@@ -35,48 +34,64 @@ export default ListViewV2 = ({item, index, separators, onPress, onFavorite}) =>
                 <ConnectType color={textCancel} {...item.acConnector}/>
                 <ConnectType color={textCancel} {...item.dcConnector}/>
               </View>
-              <View style={ui.flexc}>
-                <TextView style={[styles.infoStatus, styles.available]}>{item.distance}</TextView>
-                {item.allConnector && item.allConnector.available > 0 &&
-                  <TextView style={[styles.infoStatus, styles.available]}>{$t('charging.statusAvailable')}</TextView>
-                }
-                {item.siteType == "Private" &&
-                  <TextView style={[styles.infoStatus, styles.private]}>{$t('home.statusPrivate')}</TextView>
-                }
-              </View>
             </View>
-            { app.modules.bookmarks &&
+            { item.upcoming
+            ? <View style={[ui.center, $margin(0, 8)]}>
+                <MaterialIcons
+                  name="upcoming"
+                  size={42}
+                  color={colorAccent}
+                  style={styles.upcomingIcon} />
+                <TextView style={styles.upcomingText}>{$t("home.upcoming")}</TextView>
+              </View>
+            : <> 
+              { app.modules.bookmarks &&
+                <Pressable
+                  style={[styles.directIconView, {backgroundColor: item.favorite ? colorPrimary : colorCancel}]}
+                  android_ripple={rippleLess}
+                  onPress={onFavorite}>
+                  <MaterialIcons
+                    name="star"
+                    size={22}
+                    color={colorLight}/>
+                </Pressable>
+              }
               <Pressable
-                style={[styles.directIconView, {backgroundColor: item.favorite ? colorPrimary : colorCancel}]}
+                style={styles.directIconView}
                 android_ripple={rippleLess}
-                onPress={onFavorite}>
-                <MaterialIcons
-                  name="star"
+                onPress={() => {
+                  utils.directMaps(item.latitude, item.longitude, item.address);
+                }}>
+                <MaterialCommunityIcons
+                  name="navigation-variant"
                   size={22}
                   color={colorLight}/>
               </Pressable>
+              {/* <Pressable 
+                style={styles.directView}
+                onPress={() => {
+                  utils.directMaps(item.latitude, item.longitude, item.address);
+                }}>
+                <MaterialIcons
+                  name='directions'
+                  size={32}
+                  color={colorAccent}/>
+              </Pressable> */}
+            </> }
+          </View>
+          <View style={styles.labelRows}>
+            <TextView style={[styles.infoStatus, styles.distance]}>{item.distance}</TextView>
+            {item.allConnector && item.allConnector.available > 0 &&
+              <TextView style={[styles.infoStatus, styles.available]}>{$t('charging.statusAvailable')}</TextView>
+            }
+            {item.siteType == "Private" &&
+              <TextView style={[styles.infoStatus, styles.private]}>{$t('home.statusPrivate')}</TextView>
+            }
+            { utils.isNotEmpty(item?.labels) &&
+              item?.labels.map((label, idx) =>
+                <TextView key={idx} style={[styles.infoStatus, styles.labels]}>{label}</TextView>
+              )
             }
-            <Pressable
-              style={styles.directIconView}
-              android_ripple={rippleLess}
-              onPress={() => {
-                utils.directMaps(item.latitude, item.longitude, item.address);
-              }}>
-              <MaterialCommunityIcons
-                name="navigation-variant"
-                size={22}
-                color={colorLight}/>
-            </Pressable>
-            {/* <Pressable 
-              style={styles.directView}
-              onPress={() => {
-                utils.directMaps(item.latitude, item.longitude, item.address);
-              }}>
-              <MaterialIcons
-                name='directions'
-                size={32}
-                color={colorAccent}/>
-            </Pressable> */}
           </View>
         </View>
       </Button>
@@ -119,17 +134,28 @@ const styles = StyleSheet.create({
     paddingTop: 4,
     paddingBottom: 4
   },
+  labelRows: {
+    flexWrap: 'wrap',
+    alignItems: 'center',
+    flexDirection: 'row'
+  },
   infoStatus: {
+    height: 22,
     fontSize: 12,
     borderRadius: 3,
     marginRight: 5,
+    marginBottom: 5,
     borderWidth: 1,
-    ...$padding(3, 8, 2)
+    ...$padding(0, 8)
   },
   selected: {
     color: textPrimary,
     borderColor: colorAccent
   },
+  distance: {
+    color: '#90DB0A',
+    borderColor: '#90DB0A'
+  },
   available: {
     color: '#90DB0A',
     borderColor: '#90DB0A'
@@ -147,6 +173,11 @@ const styles = StyleSheet.create({
     color: '#FDB702',
     borderColor: '#FDB702'
   },
+  labels: {
+    color: colorLight,
+    borderColor: colorPrimary,
+    backgroundColor: colorPrimary
+  },
   connectView: {
     paddingTop: 4,
     paddingBottom: 8,
@@ -185,4 +216,15 @@ const styles = StyleSheet.create({
     justifyContent: 'center',
     backgroundColor: colorAccent
   },
+  upcomingIcon: {
+    marginLeft: 8,
+    opacity: .3
+  },
+  upcomingText: {
+    color: colorAccent,
+    fontSize: 10,
+    opacity: .3,
+    marginLeft: 8,
+    marginTop: -3
+  }
 })

+ 8 - 3
Strides-APP/app/pages/search/SearchV2.js

@@ -63,6 +63,8 @@ export default class Search extends Component {
             dcConnector: item.dcConnector,
             siteType: item.siteType,
             favorite: item.favorite,
+            upcoming: item.upcoming,
+            labels: item.labels,
             distance: utils.getDistance(item.distance),
             serviceProvider: item.serviceProvider
           });
@@ -103,7 +105,11 @@ export default class Search extends Component {
   }
 
   intoStation(info) {
-    startPage(PageList.chargeDetailPage, {stationInfo: info, action: 'search', from: PageList.search});
+    if (info.upcoming) {
+      toastShort($t("home.upcoming"))
+    } else {
+      startPage(PageList.chargeDetailPage, {stationInfo: info, action: 'search', from: PageList.search});
+    }
   }
 
   listItem = (props) => {
@@ -263,7 +269,6 @@ const styles = StyleSheet.create({
   },
   directView: {
     zIndex: 1,
-    paddingTop: 4,
     paddingRight: 16,
     alignItems: 'center'
   },
@@ -271,5 +276,5 @@ const styles = StyleSheet.create({
     color: textPrimary,
     fontSize: 12,
     paddingTop: 2
-  },
+  }
 });