surstrommed hace 3 años
padre
commit
fd3d39721d

+ 63 - 31
src/App.js

@@ -9,13 +9,14 @@ import {
   authReducer,
   localStoredReducer,
   playerReducer,
+  routeReducer,
 } from "./reducers/index";
 import { Sidebar } from "./components/Sidebar";
 import "./App.scss";
 import createSagaMiddleware from "redux-saga";
 import { all, takeEvery, put, call, select } from "redux-saga/effects";
 import * as actions from "./actions";
-import { CAudioController } from "./components/AudioController";
+import { gql } from "./helpers";
 export const history = createBrowserHistory();
 
 const sagaMiddleware = createSagaMiddleware();
@@ -25,10 +26,33 @@ export const store = createStore(
     promise: localStoredReducer(promiseReducer, "promise"),
     auth: localStoredReducer(authReducer, "auth"),
     player: localStoredReducer(playerReducer, "player"),
+    route: localStoredReducer(routeReducer, "route"),
+    // изменить условия на страницах на отображения по роутам
   }),
   applyMiddleware(sagaMiddleware)
 );
 
+function* rootSaga() {
+  yield all([
+    promiseWatcher(),
+    aboutMeWatcher(),
+    routeWatcher(),
+    loginWatcher(),
+    registerWatcher(),
+    findTracksWatcher(),
+    setAvatarWatcher(),
+    setNicknameWatcher(),
+    setEmailWatcher(),
+    setNewPasswordWatcher(),
+    audioPlayWatcher(),
+    audioPauseWatcher(),
+    audioVolumeWatcher(),
+    audioLoadWatcher(),
+  ]);
+}
+
+sagaMiddleware.run(rootSaga);
+
 function* promiseWorker(action) {
   const { name, promise } = action;
   yield put(actions.actionPending(name));
@@ -48,14 +72,38 @@ function* promiseWatcher() {
 function* aboutMeWorker() {
   // let { id } = getState().auth.payload.sub;
   // await dispatch(actionFindUser(id));
-  let { id } = yield select().auth?.payload?.sub;
-  yield call(promiseWatcher, actions.actionFindUser(id));
+  let { auth } = yield select();
+  if (auth) {
+    let { id } = auth?.payload?.sub;
+    yield call(promiseWatcher, actions.actionFindUser(id));
+  }
 }
 
 function* aboutMeWatcher() {
   yield takeEvery("ABOUT_ME", aboutMeWorker);
 }
 
+if (localStorage.authToken) {
+  store.dispatch(actions.actionAboutMe());
+}
+
+const queries = {};
+
+function* routeWorker({ match }) {
+  console.log(match);
+  if (match.path in queries) {
+    const { name, query, variables } = queries[match.path](match);
+    yield call(
+      promiseWorker,
+      actions.actionPromise(name, gql(query, variables))
+    );
+  }
+}
+
+function* routeWatcher() {
+  yield takeEvery("ROUTE", routeWorker);
+}
+
 function* loginWorker({ login, password }) {
   let token = yield call(promiseWorker, actions.actionLogin(login, password));
   if (token) {
@@ -105,12 +153,14 @@ function* setAvatarWorker({ file }) {
   //   await dispatch(actionUserUpdate({ _id: id, avatar: { _id } }));
   //   await dispatch(actionAboutMe());
   // };
-  let { _id } = yield call(promiseWatcher, actions.actionSetAvatar(file));
+  let { _id } = yield call(promiseWatcher, actions.actionUploadFile(file)); //upload file
   let { id } = yield select().auth.payload.sub;
+  console.log("Set avatar");
   yield call(
     promiseWatcher,
     actions.actionUserUpdate({ _id: id, avatar: { _id } })
   );
+  yield put(actions.actionAboutMe());
 }
 
 function* setAvatarWatcher() {
@@ -153,9 +203,17 @@ function* setNewPasswordWatcher() {
   yield takeEvery("SET_NEW_PASSWORD", setNewPasswordWorker);
 }
 
+function* audioLoadWorker({ track, duration, playlist, playlistIndex }) {
+  yield put(actions.actionLoadAudio(track, duration, playlist, playlistIndex));
+}
+
+function* audioLoadWatcher() {
+  yield takeEvery("LOAD_TRACK", audioLoadWorker);
+}
+
 function* audioPlayWorker({ isPlaying }) {
+  console.log("Play track");
   yield put(actions.actionPlayAudio(isPlaying));
-  yield put(actions.actionAboutMe());
 }
 
 function* audioPlayWatcher() {
@@ -164,7 +222,6 @@ function* audioPlayWatcher() {
 
 function* audioPauseWorker({ isPaused }) {
   yield put(actions.actionPauseAudio(isPaused));
-  yield put(actions.actionAboutMe());
 }
 
 function* audioPauseWatcher() {
@@ -173,17 +230,12 @@ function* audioPauseWatcher() {
 
 function* audioVolumeWorker({ volume }) {
   yield put(actions.actionVolumeAudio(volume));
-  yield put(actions.actionAboutMe());
 }
 
 function* audioVolumeWatcher() {
   yield takeEvery("VOLUME_TRACK", audioVolumeWorker);
 }
 
-if (localStorage.authToken) {
-  store.dispatch(actions.actionAboutMe());
-}
-
 if (
   localStorage.authToken &&
   (history.location.pathname === "/search" ||
@@ -194,25 +246,6 @@ if (
 
 store.subscribe(() => console.log(store.getState()));
 
-function* rootSaga() {
-  yield all([
-    promiseWatcher(),
-    loginWatcher(),
-    registerWatcher(),
-    aboutMeWatcher(),
-    findTracksWatcher(),
-    setAvatarWatcher(),
-    setNicknameWatcher(),
-    setEmailWatcher(),
-    setNewPasswordWatcher(),
-    audioPlayWatcher(),
-    audioPauseWatcher(),
-    audioVolumeWatcher(),
-  ]);
-}
-
-sagaMiddleware.run(rootSaga);
-
 function App() {
   return (
     <Router history={history}>
@@ -227,5 +260,4 @@ function App() {
   );
 }
 
-// <CAudioController />
 export default App;

+ 2 - 2
src/actions/index.js

@@ -109,11 +109,11 @@ export const actionFindUsers = () =>
     )
   );
 
-export const actionUploadPhoto = (file) => {
+export const actionUploadFile = (file) => {
   let fd = new FormData();
   fd.append("photo", file);
   return actionPromise(
-    "uploadPhoto",
+    "uploadFile",
     fetch(`${backURL}/upload`, {
       method: "POST",
       headers: localStorage.authToken

+ 0 - 1
src/components/AudioController.js

@@ -19,7 +19,6 @@ const AudioController = ({
 }) => {
   const [vol, setVol] = useState(volume);
   const [reproduction, setReproduction] = useState(player?.isPlaying);
-  console.log("audioController", reproduction);
 
   function truncText(text) {
     if (text && text.length > 40) {

+ 5 - 3
src/components/Dropzone.js

@@ -1,14 +1,15 @@
 import React, { useCallback } from "react";
 import { useDropzone } from "react-dropzone";
 import { connect } from "react-redux";
-import { actionSetAvatar } from "../actions";
+import { actionAboutMe, actionSetAvatar } from "../actions";
 
-const MyDropzone = ({ onload }) => {
+const MyDropzone = ({ onload, aboutMe }) => {
   const onDrop = useCallback(
     (acceptedFiles) => {
       onload(acceptedFiles[0]);
+      aboutMe();
     },
-    [onload]
+    [onload, aboutMe]
   );
   const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
 
@@ -29,4 +30,5 @@ const MyDropzone = ({ onload }) => {
 
 export const CMyDropzone = connect(null, {
   onload: actionSetAvatar,
+  aboutMe: actionAboutMe,
 })(MyDropzone);

+ 20 - 0
src/components/ProtectedRoute.js

@@ -0,0 +1,20 @@
+import { CRRoute } from "./RRoute";
+import { connect } from "react-redux";
+
+const ProtectedRoute = ({
+  fallback = "/",
+  roles = ["admin"],
+  auth,
+  component: Component,
+  ...routeProps
+}) => {
+  const WrapperComponent = (componentProps) => {
+    // let {acl} = auth?.
+    return <Component {...componentProps} />;
+  };
+  return <CRRoute {...routeProps} component={WrapperComponent} />;
+};
+
+export const CProtectedRoute = connect((state) => ({ auth: state.auth }))(
+  ProtectedRoute
+);

+ 14 - 0
src/components/RRoute.js

@@ -0,0 +1,14 @@
+import { connect } from "react-redux";
+import { Route } from "react-router-dom";
+
+const RRoute = ({ action, component: Component, ...routeProps }) => {
+  const WrapperComponent = (componentProps) => {
+    action(componentProps.match);
+    return <Component {...componentProps} />;
+  };
+  return <Route {...routeProps} component={WrapperComponent} />;
+};
+
+export const CRRoute = connect(null, {
+  action: (match) => ({ type: "ROUTE", match }),
+})(RRoute);

+ 13 - 17
src/components/Track.js

@@ -22,15 +22,13 @@ const Track = ({
 }) => {
   const [reproduction, setReproduction] = useState(false);
   let track = audio?.url ? `${backURL}/${audio.url}` : undefined;
-  let trackRef = useRef(new Audio(track));
+  let audioTrack = new Audio(track);
 
-  useEffect(() => {
-    if (reproduction) {
-      trackRef.current.play();
-    } else {
-      trackRef.current.pause();
-    }
-  }, [reproduction, playAudio, pauseAudio]);
+  if (reproduction) {
+    audioTrack.play();
+  } else {
+    audioTrack.pause();
+  }
 
   function truncText(text) {
     if (text && text.length > 40) {
@@ -40,14 +38,6 @@ const Track = ({
 
   return (
     <>
-      {reproduction ? (
-        <CAudioController
-          name={audio?.originalFileName}
-          currentTime={trackRef.current.currentTime}
-          duration={player.duration}
-          volume={trackRef.current.volume}
-        />
-      ) : null}
       <div className="d-flex mt-5">
         <div className="customAudio p-2 bg-dark text-white">
           <span className="ml-3 d-inline-block">
@@ -62,7 +52,7 @@ const Track = ({
         <Button
           onClick={() => {
             setReproduction(!reproduction);
-            loadAudio(trackRef.current, trackRef.current.duration);
+            loadAudio(audioTrack, audioTrack.duration);
             reproduction ? pauseAudio(true) : playAudio(true);
           }}
         >
@@ -76,6 +66,12 @@ const Track = ({
           <i className="fas fa-plus"></i>
         </Button>
       </div>
+      <CAudioController
+        name={audio?.originalFileName}
+        currentTime={audioTrack.currentTime}
+        duration={player.duration}
+        volume={player.volume}
+      />
     </>
   );
 };

+ 32 - 0
src/helpers/index.js

@@ -1,3 +1,5 @@
+import { useState } from "react";
+
 export const jwtDecode = (token) => {
   try {
     let arrToken = token.split(".");
@@ -43,3 +45,33 @@ export function validatePassword(password) {
 export function validateNickname(nick) {
   return /^[a-z0-9_-]{3,8}$/.test(nick);
 }
+
+export const useLocalStoredState = (defaultState, localStorageName) => {
+  let payload;
+  try {
+    payload = JSON.parse(localStorage[localStorageName]);
+  } catch {
+    payload = defaultState;
+  }
+  const [state, setState] = useState(payload);
+  return [
+    state,
+    (newState) => {
+      setState(newState);
+      localStorage.setItem(localStorageName, newState);
+    },
+  ];
+};
+
+export const useProxyState = (defaultState) => {
+  const [state, setState] = useState(defaultState);
+  return new Proxy(state, {
+    get(obj, key) {
+      return obj[key];
+    },
+    set(obj, key, value) {
+      setState({ ...obj, [key]: value });
+      return true;
+    },
+  });
+};

+ 7 - 0
src/reducers/index.js

@@ -103,3 +103,10 @@ export const playerReducer = (
   }
   return state;
 };
+
+export function routeReducer(state = {}, { type, match }) {
+  if (type === "ROUTE") {
+    return match;
+  }
+  return state;
+}