瀏覽代碼

Merge branch 'master' of https://git.s.mooo.com/khjde1207/emptyapp

자유해결사 5 年之前
父節點
當前提交
9b05242e92

+ 9 - 0
ios/Podfile.lock

@@ -116,6 +116,11 @@ PODS:
     - React
   - react-native-keep-awake (4.0.0):
     - React
+  - react-native-video (5.0.0):
+    - React
+    - react-native-video/Video (= 5.0.0)
+  - react-native-video/Video (5.0.0):
+    - React
   - React-RCTActionSheet (0.60.3):
     - React-Core (= 0.60.3)
   - React-RCTAnimation (0.60.3):
@@ -171,6 +176,7 @@ DEPENDENCIES:
   - react-native-fbsdk (from `../node_modules/react-native-fbsdk`)
   - react-native-kakao (from `../node_modules/react-native-kakao`)
   - react-native-keep-awake (from `../node_modules/react-native-keep-awake`)
+  - react-native-video (from `../node_modules/react-native-video`)
   - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
   - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
   - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
@@ -230,6 +236,8 @@ EXTERNAL SOURCES:
     :path: "../node_modules/react-native-kakao"
   react-native-keep-awake:
     :path: "../node_modules/react-native-keep-awake"
+  react-native-video:
+    :path: "../node_modules/react-native-video"
   React-RCTActionSheet:
     :path: "../node_modules/react-native/Libraries/ActionSheetIOS"
   React-RCTAnimation:
@@ -289,6 +297,7 @@ SPEC CHECKSUMS:
   react-native-fbsdk: ee254012cfb13cdfea4fc422d046d56dec8c750b
   react-native-kakao: 6c5ee067676951227718388ce170c412af8f2aa8
   react-native-keep-awake: 0de4bd66de0c23178107dce0c2fcc3354b2a8e94
+  react-native-video: 44c6befbc1526283ca1919891fcebe4680feade4
   React-RCTActionSheet: 08864c609d9f959abf3d51fdd93f8bc6e91f21eb
   React-RCTAnimation: a4547e9fac2627ded3df9d302f5558b475faf819
   React-RCTBlob: 62d5c263a2adb8f7a2cafd601beba18a2d99cbbb

+ 20 - 0
package-lock.json

@@ -4902,6 +4902,11 @@
         "object.assign": "^4.1.0"
       }
     },
+    "keymirror": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/keymirror/-/keymirror-0.1.1.tgz",
+      "integrity": "sha1-kYiJ6hP40KQufFVyUO7nE63JXDU="
+    },
     "kind-of": {
       "version": "6.0.2",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
@@ -7268,6 +7273,16 @@
         }
       }
     },
+    "react-native-video": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/react-native-video/-/react-native-video-5.0.0.tgz",
+      "integrity": "sha512-nSG7Zkc0SE2Pa/sKWvMEPUc9Zlo0iVOFTac0GcXd/U5vTsm4L28leQzJ8K/s+Yc5xfCYaeb9bIWROqw2oiB9Ig==",
+      "requires": {
+        "keymirror": "^0.1.1",
+        "prop-types": "^15.5.10",
+        "shaka-player": "^2.4.4"
+      }
+    },
     "react-navigation": {
       "version": "3.11.1",
       "resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-3.11.1.tgz",
@@ -7799,6 +7814,11 @@
       "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
       "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
     },
+    "shaka-player": {
+      "version": "2.5.4",
+      "resolved": "https://registry.npmjs.org/shaka-player/-/shaka-player-2.5.4.tgz",
+      "integrity": "sha512-r7s2xauV4id0jUzAEtE2+E+0keOfrdkk2mZhiDLs9CrhA9IR0hqrOZLLzthNP4/yF5oBmNcAZU0/qWPwlawHEA=="
+    },
     "shebang-command": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",

+ 1 - 0
package.json

@@ -24,6 +24,7 @@
     "react-native-naver-login": "^1.3.0",
     "react-native-reanimated": "^1.1.0",
     "react-native-vector-icons": "^6.6.0",
+    "react-native-video": "^5.0.0",
     "react-navigation": "^3.11.1",
     "rn-class": "^1.0.20",
     "use-memo-one": "^1.1.1"

+ 269 - 211
src/components/Player.js

@@ -1,4 +1,4 @@
-import React, { useState, useEffect, useRef, useMemo } from 'react';
+import React, { useState, useEffect, useRef, useMemo, useContext } from 'react';
 import {
   View,
   Text,
@@ -22,6 +22,8 @@ import PlayerControls from './PlayerControls';
 import PlayerContents from './PlayerContents';
 import PlayerHeader from './PlayerHeader';
 import { getInset } from 'react-native-safe-area-view';
+import Video from 'react-native-video';
+import { PlayerDispatchContext, PlayerStateContext } from './PlayerReducer';
 
 const { width, height } = Dimensions.get('window');
 const statusBarHeight = getStatusBarHeight(true);
@@ -161,7 +163,7 @@ export default props => {
   const destination = tabY - minHeight - statusBarHeight;
   const [currentPlayerValue, setCurrentPlayerValue] = useState(0);
   const [isPlay, setPlay] = useState(false);
-
+  const {playerData} = props.Pages;
   const {
     onGestureEvent,
     translateY,
@@ -299,240 +301,296 @@ export default props => {
   }, []);
 
   useEffect(() => {
-    return () => {};
-  });
+    playerDispatch({type:'currentTime', setCurrentTime: 0});
+    return () => {
+      playerDispatch({type:'currentTime', setCurrentTime: 0});
+    };
+  },[playerData.soundURI]);
 
   const slideUp = () => {};
+
+  const player = useRef(null);
+  
+  const playerDispatch = useContext(PlayerDispatchContext);
+  const { uri, paused, muted } = useContext(PlayerStateContext);
+  const playerOnBuffer = (data) => {
+    //console.log(data)
+  }
+  const playerOnError = (e) => {
+    console.log(e);
+  }
+  const playerOnLoad = (data) => {
+    //console.log(data.duration)
+    playerDispatch({type:'paused', setPaused:false});
+    playerDispatch({type:'duration', setDuraton: Math.floor(data.duration)});
+  }
+  const playerOnProgress = (data) => {
+    //console.log(data.currentTime)
+    playerDispatch({type:'currentTime', setCurrentTime: data.currentTime});
+  }
+  const onLoadStart = () => {
+    //console.log('onload start');
+    playerDispatch({type:'player', player: player});
+  }
+  const playerOnEnd = () => {
+    //console.log('end');
+  }
+  const onSeek = (data) => {
+    //console.log(data)
+    if(data.seekTime===0 && data.currentTime===0) {
+      playerDispatch({type:'paused', setPaused: true});
+      playerDispatch({type:'currentTime', setCurrentTime: 0});
+    }
+  }
   return (
-    <>
-    {/* <C.View
-        style={{ ...StyleSheet.absoluteFillObject, zIndex: 1000, marginTop:getStatusBarHeight(true) }}
-        cls="h20 bgc-rgba-white-0_5"
-      >
-        <C.Text cls="f5 ta-c bgc-rgba-red-0_5">테스트용 Component</C.Text>
-        <C.View cls="h10 ai-c bgc-rgba-blue-0_5">
-          <Slider
-            style={{ width: '95%' }}
-            trackStyle={{ height: 2 }}
-            thumbTintColor="#333"
-            thumbStyle={{ width: 10, height: 5 }}
-            value={currentPlayerValue}
-            onValueChange={value => setCurrentPlayerValue(value)}
-          />
-          <C.View cls="w95 jc-sb flx-row">
-            <C.Text>Time : {currentPlayerValue}</C.Text>
-          </C.View>
-        </C.View>
-        <C.TouchableOpacity 
-          cls="h5 bgc-rgba-black-0_5"
-          onPress={() => {
-            setPlay(!isPlay);
-          }}
-        >
-          <C.Text cls="f5 ta-c rgba-white-0_5">Click Test</C.Text>
-        </C.TouchableOpacity>
-      </C.View> */}
-      <PanGestureHandler
-        onHandlerStateChange={onGestureEvent}
-        activeOffsetY={[-10, 10]}
-        onGestureEvent={onGestureEvent}
-      >
-        <Animated.View
-          style={{
-            ...StyleSheet.absoluteFillObject,
-            zIndex: 10,
-            marginTop: statusBarHeight,
-            transform: [{ translateY }],
-            alignItems: 'center',
-            height: mainPlayerContainerHeight
-          }}
-        >
-          <Animated.View
-            style={{
-              padding: 0,
-              backgroundColor: 'white',
-              width: playContainerWidth,
-              borderRadius: playerBoderRadius
-            }}
+        <>
+        {/* <C.View
+            style={{ ...StyleSheet.absoluteFillObject, zIndex: 1000, marginTop:getStatusBarHeight(true) }}
+            cls="h20 bgc-rgba-white-0_5"
           >
-            <Animated.View
-              style={[
-                Platform.OS === 'android'
-                  ? { borderColor: '#eee' }
-                  : { borderColor: 'white' },
-                {
-                  ...StyleSheet.absoluteFillObject,
-                  borderWidth: 1,
-                  borderRadius: 15,
-                  opacity: playerControlOpaciy,
-                  backgroundColor: 'white'
-                },
-                shadow2
-              ]}
-            >
-              <PlayerControls
-                {...props}
-                currentPlayerValue={currentPlayerValue}
-                setCurrentPlayerValue={setCurrentPlayerValue}
+            <C.Text cls="f5 ta-c bgc-rgba-red-0_5">테스트용 Component</C.Text>
+            <C.View cls="h10 ai-c bgc-rgba-blue-0_5">
+              <Slider
+                style={{ width: '95%' }}
+                trackStyle={{ height: 2 }}
+                thumbTintColor="#333"
+                thumbStyle={{ width: 10, height: 5 }}
+                value={currentPlayerValue}
+                onValueChange={value => setCurrentPlayerValue(value)}
               />
-            </Animated.View>
+              <C.View cls="w95 jc-sb flx-row">
+                <C.Text>Time : {currentPlayerValue}</C.Text>
+              </C.View>
+            </C.View>
+            <C.TouchableOpacity 
+              cls="h5 bgc-rgba-black-0_5"
+              onPress={() => {
+                setPlay(!isPlay);
+              }}
+            >
+              <C.Text cls="f5 ta-c rgba-white-0_5">Click Test</C.Text>
+            </C.TouchableOpacity>
+          </C.View> */}
+          <PanGestureHandler
+            onHandlerStateChange={onGestureEvent}
+            activeOffsetY={[-10, 10]}
+            onGestureEvent={onGestureEvent}
+          >
             <Animated.View
               style={{
-                opacity: PlayerHeadOpacity,
-                backgroundColor: 'rgba(255,255,255,0)',
-                width: PlayerHeadWidth,
-                height: PlayerHeadHeight
+                ...StyleSheet.absoluteFillObject,
+                zIndex: 10,
+                marginTop: statusBarHeight,
+                transform: [{ translateY }],
+                alignItems: 'center',
+                height: mainPlayerContainerHeight
               }}
             >
-              <PlayerHeader {...props} visibleMenu={setModalVisible} />
-            </Animated.View>
-            <Animated.View style={{ width: videoWidth, height: videoHeight }}>
-              <Animated.Image
-                resizeMode="contain"
-                style={{ flex: 1, margin: 10, width: null, height: null }}
-                source={props.Pages.img}
-              />
+              <Animated.View
+                style={{
+                  padding: 0,
+                  backgroundColor: 'white',
+                  width: playContainerWidth,
+                  borderRadius: playerBoderRadius
+                }}
+              >
+                <Animated.View
+                  style={[
+                    Platform.OS === 'android'
+                      ? { borderColor: '#eee' }
+                      : { borderColor: 'white' },
+                    {
+                      ...StyleSheet.absoluteFillObject,
+                      borderWidth: 1,
+                      borderRadius: 15,
+                      opacity: playerControlOpaciy,
+                      backgroundColor: 'white'
+                    },
+                    shadow2
+                  ]}
+                >
+                  <PlayerControls
+                    {...props}
+                  />
+                </Animated.View>
+                <Animated.View
+                  style={{
+                    opacity: PlayerHeadOpacity,
+                    backgroundColor: 'rgba(255,255,255,0)',
+                    width: PlayerHeadWidth,
+                    height: PlayerHeadHeight
+                  }}
+                >
+                  <PlayerHeader {...props} visibleMenu={setModalVisible} />
+                </Animated.View>
+                <Animated.View style={{ width: videoWidth, height: videoHeight }}>
+                  <Animated.Image
+                    resizeMode="contain"
+                    style={{ flex: 1, margin: 10, width: null, height: null }}
+                    source={props.Pages.img}
+                    />
+                  <Video
+                    source={{uri:playerData.soundURI}}
+                    style={StyleSheet.absoluteFill}
+                    ref={player}
+                    //rate={this.state.rate}
+                    paused={paused}
+                    //volume={this.state.volume}
+                    muted={muted}
+                    //ignoreSilentSwitch={this.state.ignoreSilentSwitch}
+                    resizeMode='contain'
+                    onLoad={playerOnLoad}
+                    onLoadStart={onLoadStart}
+                    onBuffer={playerOnBuffer}
+                    onProgress={playerOnProgress}
+                    onSeek={onSeek}
+                    onError={playerOnError}
+                    onEnd={playerOnEnd}
+                    //poster='https://baconmockup.com/300/200/'
+                    //repeat={true}
+                    //filter={this.state.filter}
+                    //filterEnabled={this.state.filterEnabled}
+                    audioOnly={true}
+                  />
+                </Animated.View>
+              </Animated.View>
+              <Animated.View
+                style={{
+                  backgroundColor: 'white',
+                  width: playContainerWidth,
+                  height: playerContainerHeight
+                }}
+              >
+                <Animated.View style={{ opacity }}>
+                  <PlayerContents
+                    {...props}
+                  />
+                </Animated.View>
+              </Animated.View>
             </Animated.View>
-          </Animated.View>
-          <Animated.View
-            style={{
-              backgroundColor: 'white',
-              width: playContainerWidth,
-              height: playerContainerHeight
+          </PanGestureHandler>
+          <Modal
+            isVisible={modalVisible === 'detail'}
+            onSwipeComplete={() => {
+              setModalVisible(null);
             }}
+            swipeDirection="left"
+            //deviceHeight={height}
+            deviceWidth={width}
+            style={{ margin: 0 }}
+            backdropColor="white"
+            backdropOpacity={1}
+            animationIn="slideInLeft"
+            animationOut="slideOutLeft"
           >
-            <Animated.View style={{ opacity }}>
-              <PlayerContents
-                {...props}
-                currentPlayerValue={currentPlayerValue}
-                setCurrentPlayerValue={setCurrentPlayerValue}
-              />
-            </Animated.View>
-          </Animated.View>
-        </Animated.View>
-      </PanGestureHandler>
-      <Modal
-        isVisible={modalVisible === 'detail'}
-        onSwipeComplete={() => {
-          setModalVisible(null);
-        }}
-        swipeDirection="left"
-        //deviceHeight={height}
-        deviceWidth={width}
-        style={{ margin: 0 }}
-        backdropColor="white"
-        backdropOpacity={1}
-        animationIn="slideInLeft"
-        animationOut="slideOutLeft"
-      >
-        <C.View cls="w90 h100 bgc-rgba-black-0_5">
-          <ScrollView style={{ flex: 1, marginTop: '10%' }}>
-            <C.Text cls="flx1 ta-c">{props.Pages.subtitle}</C.Text>
-            <C.View cls="flx2 ph5 mt5">
-              <C.Text cls="fw-b">{props.Pages.subtitle}</C.Text>
-              <C.Text cls="mt2">{props.Pages.contens}</C.Text>
-              <C.Text cls="mt3" numberOfLines={1}>
-                by {props.Pages.subtitle.replace(/\r\n|\n|\r/gm, ' ')}
-              </C.Text>
-              <C.Text cls="mt5 as-e" numberOfLines={1}>
-                March 19
-              </C.Text>
+            <C.View cls="w90 h100 bgc-rgba-black-0_5">
+              <ScrollView style={{ flex: 1, marginTop: '10%' }}>
+                <C.Text cls="flx1 fw-b ta-c">{playerData.title}</C.Text>
+                <C.View cls="flx2 ph5 mt5">
+                  <C.Text cls="fw-b">{playerData.subtitle}</C.Text>
+                  <C.Text cls="mt2">{playerData.contents}</C.Text>
+                  <C.Text cls="mt3" numberOfLines={1}>
+                    by {playerData.author.replace(/\r\n|\n|\r/gm, ' ')}
+                  </C.Text>
+                  <C.Text cls="mt5 as-e" numberOfLines={1}>
+                    {playerData.date}
+                  </C.Text>
+                </C.View>
+              </ScrollView>
             </C.View>
-          </ScrollView>
-        </C.View>
-        <TouchableOpacity
-          style={[
-            StyleSheet.absoluteFillObject,
-            {
-              width: '90%',
-              justifyContent: 'center',
-              paddingRight: '5%',
-              alignItems: 'flex-end'
-            }
-          ]}
-          onPress={() => {
-            setModalVisible(null);
-          }}
-        >
-          <C.EL.Icon
-            color="rgb(10,132,255)"
-            {...C.n2cls('size10')}
-            type="ionicon"
-            name="md-arrow-dropleft"
-          />
-        </TouchableOpacity>
-      </Modal>
-
-      <Modal isVisible={modalVisible === 'share'} style={{ margin: 0 }}>
-        <View
-          style={{
-            flex: 1,
-            justifyContent: 'center',
-            alignItems: 'center',
-            backgroundColor: 'rgb(242,242,247)'
-          }}
-        >
-          <ScrollView>
-            <View style={{ height: statusBarHeight }} />
-            <View style={{ marginHorizontal: '5%', alignItems: 'flex-end' }}>
+            <TouchableOpacity
+              style={[
+                StyleSheet.absoluteFillObject,
+                {
+                  width: '90%',
+                  justifyContent: 'center',
+                  paddingRight: '5%',
+                  alignItems: 'flex-end'
+                }
+              ]}
+              onPress={() => {
+                setModalVisible(null);
+              }}
+            >
               <C.EL.Icon
-                color="black"
+                color="rgb(10,132,255)"
                 {...C.n2cls('size10')}
                 type="ionicon"
-                name="md-close"
-                onPress={() => {
-                  setModalVisible(null);
-                }}
+                name="md-arrow-dropleft"
               />
-            </View>
+            </TouchableOpacity>
+          </Modal>
 
+          <Modal isVisible={modalVisible === 'share'} style={{ margin: 0 }}>
             <View
               style={{
-                //...shadowImage,
-                //backgroundColor: 'white',
-                marginHorizontal: '5%',
-                width: width * 0.8,
-                height: (width * 0.8) / 1.78
+                flex: 1,
+                justifyContent: 'center',
+                alignItems: 'center',
+                backgroundColor: 'rgb(242,242,247)'
               }}
             >
-              <Image
-                resizeMode="contain"
-                style={{
-                  flex: 1,
-                  marginVertical: 10,
-                  width: null,
-                  height: null
-                }}
-                source={props.Pages.img}
-              />
-            </View>
-            <C.View cls="flx-row jc-sa ai-t mt2">
-              <C.Text cls="fw-b">{'Spring of Music'}</C.Text>
-              <C.Text cls="fw-b">{`18min`}</C.Text>
-            </C.View>
+              <ScrollView>
+                <View style={{ height: statusBarHeight }} />
+                <View style={{ marginHorizontal: '5%', alignItems: 'flex-end' }}>
+                  <C.EL.Icon
+                    color="black"
+                    {...C.n2cls('size10')}
+                    type="ionicon"
+                    name="md-close"
+                    onPress={() => {
+                      setModalVisible(null);
+                    }}
+                  />
+                </View>
 
-            <View style={{ height: minHeight }} />
+                <View
+                  style={{
+                    //...shadowImage,
+                    //backgroundColor: 'white',
+                    marginHorizontal: '5%',
+                    width: width * 0.8,
+                    height: (width * 0.8) / 1.78
+                  }}
+                >
+                  <Image
+                    resizeMode="contain"
+                    style={{
+                      flex: 1,
+                      marginVertical: 10,
+                      width: null,
+                      height: null
+                    }}
+                    source={props.Pages.img}
+                  />
+                </View>
+                <C.View cls="flx-row jc-sa ai-t mt2">
+                  <C.Text cls="fw-b">{'Spring of Music'}</C.Text>
+                  <C.Text cls="fw-b">{`18min`}</C.Text>
+                </C.View>
 
-            <TouchableOpacity
-              onPress={onShare}
-              style={{ marginHorizontal: '5%', alignItems: 'center' }}
-            >
-              <View style={[s.sharContainer]}>
-                <C.EL.Icon
-                  color="black"
-                  {...C.n2cls('size10')}
-                  type="ionicon"
-                  name="md-share"
-                />
-                <C.Text cls="f2.5">공유하기, 메세지 보내기</C.Text>
-              </View>
-            </TouchableOpacity>
+                <View style={{ height: minHeight }} />
+
+                <TouchableOpacity
+                  onPress={onShare}
+                  style={{ marginHorizontal: '5%', alignItems: 'center' }}
+                >
+                  <View style={[s.sharContainer]}>
+                    <C.EL.Icon
+                      color="black"
+                      {...C.n2cls('size10')}
+                      type="ionicon"
+                      name="md-share"
+                    />
+                    <C.Text cls="f2.5">공유하기, 메세지 보내기</C.Text>
+                  </View>
+                </TouchableOpacity>
 
-            <View style={{ height: minHeight }} />
-          </ScrollView>
-        </View>
-      </Modal>
-    </>
+                <View style={{ height: minHeight }} />
+              </ScrollView>
+            </View>
+          </Modal>
+        </>
   );
 };
 

+ 45 - 18
src/components/PlayerContents.js

@@ -1,51 +1,78 @@
-import React, { useState } from 'react';
-import { ScrollView, Text } from 'react-native';
+import React, { useState, useContext } from 'react';
+import { ScrollView, Text, StyleSheet } from 'react-native';
 import { Icon, Slider } from 'react-native-elements';
 import C from 'rn-class';
+import {PlayerStateContext, PlayerDispatchContext, playerCommon} from './PlayerReducer';
 
 export default props => {
   const { Pages, currentPlayerValue, setCurrentPlayerValue} = props;
   const [curPlayerValue, setCurPlayerValue] = useState(0);
   const [isPlay, setPlay] = useState(false);
+  const playerDispatch = useContext(PlayerDispatchContext);
+  const playerState = useContext(PlayerStateContext);
+  const {paused, player, duration, currentTime} = playerState;
+  const { secondsTohhmmss } = playerCommon;
+  const {playerData} = Pages;
   const onSetPlay = () => {
-    setPlay(!isPlay);
+    //setPlay(!isPlay);
+    playerDispatch({type:'paused', setPaused:!paused});
+    //console.log(player);
   };
+  const onStop = () => {
+    playerDispatch({type:'stop'});
+  }
+  // const getpercent = () => {
+  //   console.log((parseFloat(currentTime) / parseFloat(duration))*100-1)
+  //   if(currentTime>0) {
+  //     return (parseFloat(currentTime) / parseFloat(duration))*100
+  //   }
+  // }
+  const onForwardRewind = (type) => {
+    if(type==='rewind') {
+      playerDispatch({type: 'seek', seekValue: currentTime - 15})
+    }
+    if(type==='forward') {
+      playerDispatch({type: 'seek', seekValue: currentTime + 15})
+    }
+  }
   return (
     <ScrollView>
-      <C.Text cls="flx1 ta-c">{Pages.subtitle}</C.Text>
+      <C.Text cls="flx1 ta-c">{playerData.title}</C.Text>
       <C.View cls="flx2 ph5 mt5">
-        <C.Text cls="fw-b">{Pages.subtitle}</C.Text>
+        <C.Text cls="fw-b">{playerData.subtitle}</C.Text>
         <C.Text cls="mt2" numberOfLines={10}>
-          {Pages.contens}
+          {playerData.contents}
         </C.Text>
         <C.Text cls="mt3" numberOfLines={1}>
-          by {Pages.subtitle.replace(/\r\n|\n|\r/gm, ' ')}
+          by {playerData.author.replace(/\r\n|\n|\r/gm, ' ')}
         </C.Text>
         <C.Text cls="mt5 as-e" numberOfLines={1}>
-          March 19
+          {playerData.date}
         </C.Text>
       </C.View>
       <C.View cls="flx1 flx-row jc-sa ai-c mt5">
-        <C.EL.Icon {...C.n2cls('size8')} type="ionicon" name="md-rewind" />
-        { isPlay
+        <C.EL.Icon {...C.n2cls('size8')} type="ionicon" name="md-rewind" onPress={()=>{onForwardRewind('rewind')}} />
+        { paused===false
           ?<C.EL.Icon {...C.n2cls('size10')} type="ionicon" name="md-pause" onPress={onSetPlay} />
           :<C.EL.Icon {...C.n2cls('size10')} type="ionicon" name="md-play" onPress={onSetPlay} />
         }
-        <C.EL.Icon {...C.n2cls('size8')} type="ionicon" name="md-fastforward" />
-        <C.EL.Icon {...C.n2cls('size10')} type="ionicon" name="md-square" />
+        <C.EL.Icon {...C.n2cls('size8')} type="ionicon" name="md-fastforward" onPress={()=>{onForwardRewind('forward')}} />
+        <C.EL.Icon {...C.n2cls('size10')} type="ionicon" name="md-square" onPress={onStop}/>
       </C.View>
       <C.View cls="flx1 ai-c mt2">
+      {/* <C.Text cls="as-s" style={{ ...StyleSheet.absoluteFill, backgroundColor:'red', width:50, textAlign:'center', left:`${getpercent()-5}%`}}> {Math.floor(currentTime)}</C.Text> */}
         <Slider
           style={{ width: '95%' }}
-          trackStyle={{height:2}}
+          trackStyle={{height:4}}
           thumbTintColor="#333"
-          thumbStyle={{ width: 10, height: 5 }}
-          value={currentPlayerValue}
-          onValueChange={value => setCurrentPlayerValue(value)}
+          thumbStyle={{ width: 15, height: 10 }}
+          maximumValue={duration}
+          value={currentTime}
+          onValueChange={value => playerDispatch({type: 'seek', seekValue: Math.floor(value)})}
         />
         <C.View cls="w95 jc-sb flx-row">
-          <C.Text>Time : {currentPlayerValue}</C.Text>
-          <C.Text>{`2:50`}</C.Text>
+          <C.Text>{secondsTohhmmss(currentTime)}</C.Text>
+          <C.Text>{secondsTohhmmss(duration)}</C.Text>
         </C.View>
       </C.View>
       <C.View cls="h50" />

+ 17 - 8
src/components/PlayerControls.js

@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useState, useContext } from 'react';
 import {
   View,
   StyleSheet,
@@ -9,6 +9,7 @@ import {
 } from 'react-native';
 import { Icon, Slider } from 'react-native-elements';
 import C from 'rn-class';
+import {PlayerStateContext, PlayerDispatchContext, playerCommon} from './PlayerReducer';
 
 const { width } = Dimensions.get('window');
 
@@ -18,9 +19,16 @@ export default PlayerControls = props => {
   const { Pages, closePlayer, currentPlayerValue, setCurrentPlayerValue} = props;
   const [curPlayerValue, setCurPlayerValue] = useState(0);
   const [isPlay, setPlay] = useState(false);
+  const playerDispatch = useContext(PlayerDispatchContext);
+  const playerState = useContext(PlayerStateContext);
+  const {paused, player, duration, currentTime} = playerState;
+  const { secondsTohhmmss } = playerCommon;
+  const {playerData} = Pages;
+
   const onSetPlay = () => {
-    setPlay(!isPlay);
-  }
+    //setPlay(!isPlay);
+    playerDispatch({type:'paused', setPaused:!paused});
+  };
   const getThumbTopFromStyleHeight = (styleHeight=40, trackHeight=4) => {
     const thumbTop = (styleHeight / 2) + (trackHeight / 2) + 
     (Platform.OS==='android'&&(styleHeight<40||trackHeight<4)?0.5:0);
@@ -37,20 +45,21 @@ export default PlayerControls = props => {
         <View style={styles.placeholder} />
         <C.View cls="flx2">
           <C.View cls="flx-row jc-sb">
-            <Text numerOfLine={1}>{Pages.subtitle.replace(/\r\n|\n|\r/gm,' ')}</Text>
-            <Text>{`2:50`}</Text>
+            <Text numerOfLine={1}>{playerData.title.replace(/\r\n|\n|\r/gm,' ')}</Text>
+            <Text>{secondsTohhmmss(duration)}</Text>
           </C.View>
           <Slider
             style={sliderLayout.sh}
             trackStyle={sliderLayout.th}
             thumbTintColor="#333"
             thumbStyle={{width:10, height:5, ...sliderLayout.tt}}
-            value={currentPlayerValue}
-            onValueChange={value => setCurrentPlayerValue(value)}
+            maximumValue={duration}
+            value={currentTime}
+            onValueChange={value => playerDispatch({type: 'seek', seekValue: Math.floor(value)})}
           />
         </C.View>
         <C.View cls="flx0.5 jc-sa ai-sa flx-row">
-          { isPlay
+          { paused===false
             ?<C.EL.Icon {...C.n2cls("size8")} type="ionicon" name="md-pause" onPress={onSetPlay} />
             :<C.EL.Icon {...C.n2cls("size8")} type="ionicon" name="md-play" onPress={onSetPlay} />
           }

+ 8 - 3
src/components/PlayerHeader.js

@@ -1,17 +1,22 @@
-import React, { useState } from 'react';
+import React, { useState, useContext } from 'react';
 import {
   View,
   StyleSheet
 } from 'react-native';
 import { Icon, Slider } from 'react-native-elements';
 import C from 'rn-class';
+import {PlayerStateContext, PlayerDispatchContext} from './PlayerReducer';
 
 export default PlayerHead = props => {
   const { closePlayer, visibleMenu} = props;
   const [isMute, setIsMute] = useState(false);
+  const playerDispatch = useContext(PlayerDispatchContext);
+  const playerState = useContext(PlayerStateContext);
+  const {paused, muted, player, duration, currentTime} = playerState;
 
   const setMute = () => {
-    setIsMute(!isMute);
+    //setIsMute(!isMute);
+    playerDispatch({type:'muted'});
   }
   const iconsize = {...C.n2cls('size7')};
 
@@ -23,7 +28,7 @@ export default PlayerHead = props => {
         <C.EL.Icon {...iconsize} color="rgb(255,45,85)" type="ionicon" name="md-heart" />
       </C.View>
       <C.View cls="flx-row flx0.3 ai-e jc-sa">
-        { isMute
+        { muted
           ?<C.EL.Icon {...iconsize} type="ionicon" name="md-volume-off" onPress={setMute} />
           :<C.EL.Icon {...iconsize} type="ionicon" name="md-volume-high" onPress={setMute} />
         }

+ 100 - 0
src/components/PlayerReducer.js

@@ -0,0 +1,100 @@
+import React, {createContext, useReducer} from 'react';
+
+const PlayerStateContext = createContext();
+const PlayerDispatchContext = createContext();
+
+const initialPlayerState = {
+    volume: 1,
+    muted: false,
+    duration: 0.0,
+    currentTime: 0.0,
+    currentPosition: 0.0,
+    paused: true,
+    uri: 'https://sample-videos.com/audio/mp3/crowd-cheering.mp3',
+    player: null
+};
+
+const playerReducer = (state, action) => {
+    switch(action.type) {
+      case 'muted':
+        return {
+          ...state,
+          muted: !state.muted
+        };
+      case 'paused':
+        return {
+          ...state,
+          paused: action.setPaused
+        };
+      case 'uri':
+        return {
+          ...state,
+          uri: action.setUri
+        };
+      case 'duration':
+        return {
+          ...state,
+          duration: action.setDuraton
+        };
+      case 'currentTime':
+        return {
+          ...state,
+          currentTime: action.setCurrentTime
+        };
+      case 'currentPosition':
+        return {
+          ...state,
+          currentPosition: action.setCurrentPosition
+        };
+      case 'player':
+        return {
+          ...state,
+          player: action.player
+        };
+      case 'seek':
+        state.player && state.player.current.seek(action.seekValue);
+        return state;
+      case 'stop':
+        state.player && state.player.current.seek(0);
+        return state;            
+      default: throw new Error('Action type is not match');  
+    }
+};
+
+const PlayerConextProvider = ({children}) => {
+  const [playerState, playerDispatch] = useReducer(playerReducer, initialPlayerState);
+  return (
+    <PlayerDispatchContext.Provider value={playerDispatch}>
+      <PlayerStateContext.Provider value={playerState}>
+        {children}
+      </PlayerStateContext.Provider>
+    </PlayerDispatchContext.Provider>
+
+  );
+}
+
+/**
+ *  Player Common Function
+ */
+
+const secondsTohhmmss = (seconds, timeFormat='hmmss') => {
+  const format = val => `0${Math.floor(val)}`.slice(-2);
+  const hours = seconds / 3600;
+  const minutes = (seconds % 3600) / 60;
+
+  if(timeFormat==='mmss' || ~~hours===0) {
+    return [minutes, seconds % 60].map(format).join(':');
+  }
+  if(timeFormat==='hmmss') {
+    return `${~~hours}:${[minutes, seconds % 60].map(format).join(':')}`;
+  }
+  if(timeFormat==='hhmmss') {
+    return [hours, minutes, seconds % 60].map(format).join(':');
+  }
+}
+
+const playerCommon = {
+  secondsTohhmmss: secondsTohhmmss
+};
+
+export { PlayerDispatchContext, PlayerStateContext, PlayerConextProvider, playerCommon }

+ 770 - 0
src/data/dummy.js

@@ -0,0 +1,770 @@
+export {BTNS, BTNS_ORG};
+
+const BTNS_ORG = [
+  [
+      {title: "行" ,subtitle : "working \nmeditation" , contensTitle : "행선" , contensSubTitle : "" , contens:"하루 20분 정도 걸으면서 하는 행선은 좌선 1시간 이상의 효과를 가져옵니다.", img : require("../res/Working_meditation.png")},
+      {title: "住" ,subtitle : "standing \nmeditation", contensTitle : "주선" , contensSubTitle : "" , contens:"일상생활 속에 잠시 머무름은 인생에서 쉬어가는 의미를 가집니다. 바쁜 일상 속에서 잠시 머무름을 가지고 짧게 마음의 고요함을 찾으시길 바랍니다.", img : require("../res/Standing_meditation.png")},
+      {title: "坐" ,subtitle : "seat and \nmeditation", contensTitle : "좌선" , contensSubTitle : "" , contens:"가부좌가 아니더라도 일상생활 속에서 편한 자세로 앉아서 정신을 집중하여 무념무상의 상태로 들어가는 선수행을 말합니다.", img : require("../res/Seatand_meditation.png")},
+      {title: "卧" ,subtitle : "Lying \nmeditation"   , contensTitle : "와선" , contensSubTitle : "" , contens:"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", img : require("../res/Lying_meditation.png")},
+      {title: "身" ,subtitle : "body"                 },  
+  ],
+  [
+      {title:"사랑", subtitle : "Love",     contensTitle : "사랑" , contensSubTitle : "(애별리고)" , contens:"우리는 우리와 가까운, 우리가 원하는, 우리가 좋아하는, 우리를 편리하게 해 주고 행복하게 해 주던 많은 것들과 이별을 해야 하는 괴로움을 버려야 합니다.", img : require("../res/Working_meditation.png")},
+      {title:"미움", subtitle : "Hate",     contensTitle : "미움" , contensSubTitle : "(원증회고)" , contens:"싫어하는 것을 해야 하는 것, 싫어하는 사람과 함께 있는 것이란 얼마나 큰 괴로움인가. 이는 가장 큰 괴로움이며 여기서 벗어나야 합니다.", img : require("../res/Standing_meditation.png")},
+      {title:"탐욕", subtitle : "Avarice",  contensTitle : "탐욕" , contensSubTitle : "(구부득고)" , contens:"좋아하는 사람, 물건, 재산, 명예, 권력, 지위, 출세, 행복, 건강 등 얻고자 하고 바라지만 마음대로 구할 수 없는데서 괴로움은 시작된다.", img : require("../res/Seatand_meditation.png")},
+      {title:"탐식", subtitle : "Voracity", contensTitle : "탐식" , contensSubTitle : "(구부득고)" , contens:"현대사회에서 물질적 풍요와 상반되게 정신적 빈곤으로 인한 강박장애, 불안장애 같은 정신적 증상은 얻고자 하는 욕심으로 인하여 나타나는 화병의 일환", img : require("../res/Lying_meditation.png")},
+      {title: "心" , subtitle : "Mind"},  
+  ]
+]
+
+const BTNS = [
+  [
+    {
+      id:1,
+      group:1,
+      title: '行',
+      subtitle: 'working \nmeditation',
+      contensTitle: '행선',
+      contensSubTitle: '',
+      contens:
+        '하루 20분 정도 걸으면서 하는 행선은 좌선 1시간 이상의 효과를 가져옵니다.',
+      img: require('../res/Working_meditation.png'),
+      children: [
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title1',
+          subtitle:'subtitle1',
+          author: 'Author1',
+          contents:'content1',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/14%20Clementi%20Piano%20Sonata%20in%20D%20major,%20Op%2025%20No%206%20-%20Movement%202%20Un%20poco%20andante.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title2',
+          subtitle:'subtitle2',
+          author: 'Author2',
+          contents:'content2',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/3%20Schubert%20String%20Quartet%20No%2014%20in%20D%20minor%20Death%20and%20the%20Maiden,%20D810%20-%20Movement%203%20Scherzo%20Allegro%20molto.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title3',
+          subtitle:'subtitle3',
+          author: 'Author3',
+          contents:'content3',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title4',
+          subtitle:'subtitle4',
+          author: 'Author4',
+          contents:'content4',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title5',
+          subtitle:'subtitle5',
+          author: 'Author5',
+          contents:'content5',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title6',
+          subtitle:'subtitle6',
+          author: 'Author6',
+          contents:'content6',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title7',
+          subtitle:'subtitle7',
+          author: 'Author7',
+          contents:'content7',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title8',
+          subtitle:'subtitle8',
+          author: 'Author8',
+          contents:'content8',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        }                                                        
+      ]
+    },
+    {
+      id:2,
+      group:1,
+      title: '住',
+      subtitle: 'standing \nmeditation',
+      contensTitle: '주선',
+      contensSubTitle: '',
+      contens:
+        '일상생활 속에 잠시 머무름은 인생에서 쉬어가는 의미를 가집니다. 바쁜 일상 속에서 잠시 머무름을 가지고 짧게 마음의 고요함을 찾으시길 바랍니다.',
+      img: require('../res/Standing_meditation.png'),
+      children: [
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title1',
+          subtitle:'subtitle1',
+          author: 'Author1',
+          contents:'content1',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/14%20Clementi%20Piano%20Sonata%20in%20D%20major,%20Op%2025%20No%206%20-%20Movement%202%20Un%20poco%20andante.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title2',
+          subtitle:'subtitle2',
+          author: 'Author2',
+          contents:'content2',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/3%20Schubert%20String%20Quartet%20No%2014%20in%20D%20minor%20Death%20and%20the%20Maiden,%20D810%20-%20Movement%203%20Scherzo%20Allegro%20molto.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title3',
+          subtitle:'subtitle3',
+          author: 'Author3',
+          contents:'content3',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title4',
+          subtitle:'subtitle4',
+          author: 'Author4',
+          contents:'content4',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title5',
+          subtitle:'subtitle5',
+          author: 'Author5',
+          contents:'content5',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title6',
+          subtitle:'subtitle6',
+          author: 'Author6',
+          contents:'content6',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title7',
+          subtitle:'subtitle7',
+          author: 'Author7',
+          contents:'content7',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title8',
+          subtitle:'subtitle8',
+          author: 'Author8',
+          contents:'content8',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        }                                                        
+      ]
+    },
+    {
+      id:3,
+      group:1,
+      title: '坐',
+      subtitle: 'seat and \nmeditation',
+      contensTitle: '좌선',
+      contensSubTitle: '',
+      contens:
+        '가부좌가 아니더라도 일상생활 속에서 편한 자세로 앉아서 정신을 집중하여 무념무상의 상태로 들어가는 선수행을 말합니다.',
+      img: require('../res/Seatand_meditation.png'),
+      children: [
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title1',
+          subtitle:'subtitle1',
+          author: 'Author1',
+          contents:'content1',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/14%20Clementi%20Piano%20Sonata%20in%20D%20major,%20Op%2025%20No%206%20-%20Movement%202%20Un%20poco%20andante.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title2',
+          subtitle:'subtitle2',
+          author: 'Author2',
+          contents:'content2',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/3%20Schubert%20String%20Quartet%20No%2014%20in%20D%20minor%20Death%20and%20the%20Maiden,%20D810%20-%20Movement%203%20Scherzo%20Allegro%20molto.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title3',
+          subtitle:'subtitle3',
+          author: 'Author3',
+          contents:'content3',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title4',
+          subtitle:'subtitle4',
+          author: 'Author4',
+          contents:'content4',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title5',
+          subtitle:'subtitle5',
+          author: 'Author5',
+          contents:'content5',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title6',
+          subtitle:'subtitle6',
+          author: 'Author6',
+          contents:'content6',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title7',
+          subtitle:'subtitle7',
+          author: 'Author7',
+          contents:'content7',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title8',
+          subtitle:'subtitle8',
+          author: 'Author8',
+          contents:'content8',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        }                                                        
+      ]
+    },
+    {
+      id:4,
+      group:1,
+      title: '卧',
+      subtitle: 'Lying \nmeditation',
+      contensTitle: '와선',
+      contensSubTitle: '',
+      contens: 'OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO',
+      img: require('../res/Lying_meditation.png'),
+      children: [
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title1',
+          subtitle:'subtitle1',
+          author: 'Author1',
+          contents:'content1',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/14%20Clementi%20Piano%20Sonata%20in%20D%20major,%20Op%2025%20No%206%20-%20Movement%202%20Un%20poco%20andante.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title2',
+          subtitle:'subtitle2',
+          author: 'Author2',
+          contents:'content2',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/3%20Schubert%20String%20Quartet%20No%2014%20in%20D%20minor%20Death%20and%20the%20Maiden,%20D810%20-%20Movement%203%20Scherzo%20Allegro%20molto.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title3',
+          subtitle:'subtitle3',
+          author: 'Author3',
+          contents:'content3',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title4',
+          subtitle:'subtitle4',
+          author: 'Author4',
+          contents:'content4',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title5',
+          subtitle:'subtitle5',
+          author: 'Author5',
+          contents:'content5',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title6',
+          subtitle:'subtitle6',
+          author: 'Author6',
+          contents:'content6',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title7',
+          subtitle:'subtitle7',
+          author: 'Author7',
+          contents:'content7',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title8',
+          subtitle:'subtitle8',
+          author: 'Author8',
+          contents:'content8',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        }                                                        
+      ]
+    },
+    { parent:1, title: '身', subtitle: 'body' }
+  ],
+  [
+    {
+      id:1,
+      group:2,
+      title: '사랑',
+      subtitle: 'Love',
+      contensTitle: '사랑',
+      contensSubTitle: '(애별리고)',
+      contens:
+        '우리는 우리와 가까운, 우리가 원하는, 우리가 좋아하는, 우리를 편리하게 해 주고 행복하게 해 주던 많은 것들과 이별을 해야 하는 괴로움을 버려야 합니다.',
+      img: require('../res/Working_meditation.png'),
+      children: [
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title1',
+          subtitle:'subtitle1',
+          author: 'Author1',
+          contents:'content1',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/14%20Clementi%20Piano%20Sonata%20in%20D%20major,%20Op%2025%20No%206%20-%20Movement%202%20Un%20poco%20andante.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title2',
+          subtitle:'subtitle2',
+          author: 'Author2',
+          contents:'content2',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/3%20Schubert%20String%20Quartet%20No%2014%20in%20D%20minor%20Death%20and%20the%20Maiden,%20D810%20-%20Movement%203%20Scherzo%20Allegro%20molto.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title3',
+          subtitle:'subtitle3',
+          author: 'Author3',
+          contents:'content3',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title4',
+          subtitle:'subtitle4',
+          author: 'Author4',
+          contents:'content4',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title5',
+          subtitle:'subtitle5',
+          author: 'Author5',
+          contents:'content5',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title6',
+          subtitle:'subtitle6',
+          author: 'Author6',
+          contents:'content6',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title7',
+          subtitle:'subtitle7',
+          author: 'Author7',
+          contents:'content7',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Working_meditation.png'),
+          title:'title8',
+          subtitle:'subtitle8',
+          author: 'Author8',
+          contents:'content8',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        }                                                        
+      ]
+    },
+    {
+      id:2,
+      group:2,
+      title: '미움',
+      subtitle: 'Hate',
+      contensTitle: '미움',
+      contensSubTitle: '(원증회고)',
+      contens:
+        '싫어하는 것을 해야 하는 것, 싫어하는 사람과 함께 있는 것이란 얼마나 큰 괴로움인가. 이는 가장 큰 괴로움이며 여기서 벗어나야 합니다.',
+      img: require('../res/Standing_meditation.png'),
+      children: [
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title1',
+          subtitle:'subtitle1',
+          author: 'Author1',
+          contents:'content1',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/14%20Clementi%20Piano%20Sonata%20in%20D%20major,%20Op%2025%20No%206%20-%20Movement%202%20Un%20poco%20andante.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title2',
+          subtitle:'subtitle2',
+          author: 'Author2',
+          contents:'content2',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/3%20Schubert%20String%20Quartet%20No%2014%20in%20D%20minor%20Death%20and%20the%20Maiden,%20D810%20-%20Movement%203%20Scherzo%20Allegro%20molto.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title3',
+          subtitle:'subtitle3',
+          author: 'Author3',
+          contents:'content3',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title4',
+          subtitle:'subtitle4',
+          author: 'Author4',
+          contents:'content4',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title5',
+          subtitle:'subtitle5',
+          author: 'Author5',
+          contents:'content5',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title6',
+          subtitle:'subtitle6',
+          author: 'Author6',
+          contents:'content6',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title7',
+          subtitle:'subtitle7',
+          author: 'Author7',
+          contents:'content7',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Standing_meditation.png'),
+          title:'title8',
+          subtitle:'subtitle8',
+          author: 'Author8',
+          contents:'content8',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        }                                                        
+      ]
+    },
+    {
+      id:3,
+      group:2,
+      title: '탐욕',
+      subtitle: 'Avarice',
+      contensTitle: '탐욕',
+      contensSubTitle: '(구부득고)',
+      contens:
+        '좋아하는 사람, 물건, 재산, 명예, 권력, 지위, 출세, 행복, 건강 등 얻고자 하고 바라지만 마음대로 구할 수 없는데서 괴로움은 시작된다.',
+      img: require('../res/Seatand_meditation.png'),
+      children: [
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title1',
+          subtitle:'subtitle1',
+          author: 'Author1',
+          contents:'content1',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/14%20Clementi%20Piano%20Sonata%20in%20D%20major,%20Op%2025%20No%206%20-%20Movement%202%20Un%20poco%20andante.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title2',
+          subtitle:'subtitle2',
+          author: 'Author2',
+          contents:'content2',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/3%20Schubert%20String%20Quartet%20No%2014%20in%20D%20minor%20Death%20and%20the%20Maiden,%20D810%20-%20Movement%203%20Scherzo%20Allegro%20molto.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title3',
+          subtitle:'subtitle3',
+          author: 'Author3',
+          contents:'content3',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title4',
+          subtitle:'subtitle4',
+          author: 'Author4',
+          contents:'content4',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title5',
+          subtitle:'subtitle5',
+          author: 'Author5',
+          contents:'content5',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title6',
+          subtitle:'subtitle6',
+          author: 'Author6',
+          contents:'content6',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title7',
+          subtitle:'subtitle7',
+          author: 'Author7',
+          contents:'content7',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Seatand_meditation.png'),
+          title:'title8',
+          subtitle:'subtitle8',
+          author: 'Author8',
+          contents:'content8',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        }                                                        
+      ]
+    },
+    {
+      id:4,
+      group:2,
+      title: '탐식',
+      subtitle: 'Voracity',
+      contensTitle: '탐식',
+      contensSubTitle: '(구부득고)',
+      contens:
+        '현대사회에서 물질적 풍요와 상반되게 정신적 빈곤으로 인한 강박장애, 불안장애 같은 정신적 증상은 얻고자 하는 욕심으로 인하여 나타나는 화병의 일환',
+      img: require('../res/Lying_meditation.png'),
+      children: [
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title1',
+          subtitle:'subtitle1',
+          author: 'Author1',
+          contents:'content1',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/14%20Clementi%20Piano%20Sonata%20in%20D%20major,%20Op%2025%20No%206%20-%20Movement%202%20Un%20poco%20andante.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title2',
+          subtitle:'subtitle2',
+          author: 'Author2',
+          contents:'content2',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/3%20Schubert%20String%20Quartet%20No%2014%20in%20D%20minor%20Death%20and%20the%20Maiden,%20D810%20-%20Movement%203%20Scherzo%20Allegro%20molto.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title3',
+          subtitle:'subtitle3',
+          author: 'Author3',
+          contents:'content3',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title4',
+          subtitle:'subtitle4',
+          author: 'Author4',
+          contents:'content4',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title5',
+          subtitle:'subtitle5',
+          author: 'Author5',
+          contents:'content5',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/18%20MacCunn%20The%20Lay%20of%20the%20Last%20Minstrel%20-%20Part%202%20Final%20chorus%20O%20Caledonia!%20stern%20and%20wild.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title6',
+          subtitle:'subtitle6',
+          author: 'Author6',
+          contents:'content6',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Vaet%20Videns%20Dominus.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title7',
+          subtitle:'subtitle7',
+          author: 'Author7',
+          contents:'content7',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        },
+        {
+          soundURI:'http://www.hyperion-records.co.uk/audiotest/1%20Sullivan%20The%20Lost%20Chord,%20Seated%20one%20day%20at%20the%20organ.MP3',
+          img:require('../res/Lying_meditation.png'),
+          title:'title8',
+          subtitle:'subtitle8',
+          author: 'Author8',
+          contents:'content8',
+          date:'2019-08-20',
+          soundDuration:'1:25:38'
+        }                                                        
+      ]
+    },
+    { parent:2, title: '心', subtitle: 'Mind' }
+  ]
+];

+ 5 - 21
src/pages/_5_Root.js

@@ -6,25 +6,10 @@ import List from './_7_List';
 import TabBar from '../components/TabBar';
 import Player from "../components/Player";
 //import Player from "./PlayerGesture"; 
-
+import { PlayerConextProvider } from '../components/PlayerReducer'
 C.addColor("#d7d7d7", "color-listbg");
+import {BTNS} from '../data/dummy';
 
-const BTNS = [
-    [
-        {title: "行" ,subtitle : "working \nmeditation" , contensTitle : "행선" , contensSubTitle : "" , contens:"하루 20분 정도 걸으면서 하는 행선은 좌선 1시간 이상의 효과를 가져옵니다.", img : require("../res/Working_meditation.png")},
-        {title: "住" ,subtitle : "standing \nmeditation", contensTitle : "주선" , contensSubTitle : "" , contens:"일상생활 속에 잠시 머무름은 인생에서 쉬어가는 의미를 가집니다. 바쁜 일상 속에서 잠시 머무름을 가지고 짧게 마음의 고요함을 찾으시길 바랍니다.", img : require("../res/Standing_meditation.png")},
-        {title: "坐" ,subtitle : "seat and \nmeditation", contensTitle : "좌선" , contensSubTitle : "" , contens:"가부좌가 아니더라도 일상생활 속에서 편한 자세로 앉아서 정신을 집중하여 무념무상의 상태로 들어가는 선수행을 말합니다.", img : require("../res/Seatand_meditation.png")},
-        {title: "卧" ,subtitle : "Lying \nmeditation"   , contensTitle : "와선" , contensSubTitle : "" , contens:"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO", img : require("../res/Lying_meditation.png")},
-        {title: "身" ,subtitle : "body"                 },  
-    ],
-    [
-        {title:"사랑", subtitle : "Love",     contensTitle : "사랑" , contensSubTitle : "(애별리고)" , contens:"우리는 우리와 가까운, 우리가 원하는, 우리가 좋아하는, 우리를 편리하게 해 주고 행복하게 해 주던 많은 것들과 이별을 해야 하는 괴로움을 버려야 합니다.", img : require("../res/Working_meditation.png")},
-        {title:"미움", subtitle : "Hate",     contensTitle : "미움" , contensSubTitle : "(원증회고)" , contens:"싫어하는 것을 해야 하는 것, 싫어하는 사람과 함께 있는 것이란 얼마나 큰 괴로움인가. 이는 가장 큰 괴로움이며 여기서 벗어나야 합니다.", img : require("../res/Standing_meditation.png")},
-        {title:"탐욕", subtitle : "Avarice",  contensTitle : "탐욕" , contensSubTitle : "(구부득고)" , contens:"좋아하는 사람, 물건, 재산, 명예, 권력, 지위, 출세, 행복, 건강 등 얻고자 하고 바라지만 마음대로 구할 수 없는데서 괴로움은 시작된다.", img : require("../res/Seatand_meditation.png")},
-        {title:"탐식", subtitle : "Voracity", contensTitle : "탐식" , contensSubTitle : "(구부득고)" , contens:"현대사회에서 물질적 풍요와 상반되게 정신적 빈곤으로 인한 강박장애, 불안장애 같은 정신적 증상은 얻고자 하는 욕심으로 인하여 나타나는 화병의 일환", img : require("../res/Lying_meditation.png")},
-        {title: "心" , subtitle : "Mind"},  
-    ]
-]
 const tabPosition = {x:0, y:0, w:0, h:0};
 
 export default (props)=>{
@@ -66,10 +51,9 @@ export default (props)=>{
         <C.View cls="flx1 bgc-color-white"> 
             <C.Comp.Header  {...props}/>
             <Page   {...props} Pages={sel_idx == -1 ? {} : BTNS[targetIdx][sel_idx]}  startPlay={startPlay} bPlay={bPlay}/>
-            
-            {bPlay ? <Player {...props} Pages={curPlayInfo} tabPosition={tabPosition} closePlayer={()=>setbPlay(false)}/>  : null}
-            {/* {bPlay ? <C.View cls="flx0.1"/>  : null} */}
-
+            <PlayerConextProvider>
+                {bPlay ? <Player {...props} Pages={curPlayInfo} tabPosition={tabPosition} closePlayer={()=>setbPlay(false)}/>  : null}
+            </PlayerConextProvider>
             <TabBar setTabPosition={setTabPosition} onTabPress={onTabPress} BTNS={BTNS}/>  
         </C.View> 
     )  

+ 14 - 5
src/pages/_7_List.js

@@ -8,9 +8,11 @@ C.addColor("#d7d7d7", "color-listbg");
 export default (props)=>{ 
     let onClickPlay = (p)=>{ 
         // props.navigation.push('Player');
-        props.startPlay(props);
+        const tmp = props;
+        tmp.Pages.playerData = p;
+        tmp.Pages.playerData.contents = tmp.Pages.playerData.contents + tmp.Pages.contens;
+        props.startPlay(tmp);
     }
-
     return (
         <C.View cls="flx1 bgc-color-white"> 
             <C.View cls="w100% ai-c flx1">     
@@ -27,12 +29,19 @@ export default (props)=>{
                     </C.View> 
                  
                  <C.View cls="w100 flx-w jc-c flx-row">
+                        {/* <Imgs onClickPlay={onClickPlay} ></Imgs>
                         <Imgs onClickPlay={onClickPlay} ></Imgs>
                         <Imgs onClickPlay={onClickPlay} ></Imgs>
                         <Imgs onClickPlay={onClickPlay} ></Imgs>
                         <Imgs onClickPlay={onClickPlay} ></Imgs>
-                        <Imgs onClickPlay={onClickPlay} ></Imgs>
-                        <Imgs onClickPlay={onClickPlay} ></Imgs>
+                        <Imgs onClickPlay={onClickPlay} ></Imgs> */}
+                        {
+                            props.Pages.children.map((v,i) => {
+                                return (<Imgs key={`i${v.title}`} soundDuration={v.soundDuration} onClickPlay={()=>{
+                                    onClickPlay(v)
+                                }} />);
+                            })
+                        }
                  </C.View>
                  {
                      props.bPlay ? 
@@ -70,7 +79,7 @@ const Imgs = (props)=>{
                 </C.ImageBackground>
                 <C.View cls="flx1 ai-e mh2">  
                     <C.Text> 
-                        10:00
+                        {props.soundDuration}
                     </C.Text>
                 </C.View>
         </C.View>