192 lines
6.3 KiB
JavaScript
192 lines
6.3 KiB
JavaScript
import React, { useEffect } from "react";
|
|
import { Searchbar, Title } from 'react-native-paper';
|
|
import { ScrollView, ActivityIndicator, StyleSheet, SafeAreaView, FlatList, View } from 'react-native';
|
|
import API from "../API";
|
|
import CourseCard from "../components/CourseCard";
|
|
import { useSnapshot } from 'valtio';
|
|
import GlobalState from '../contexts/GlobalState.js';
|
|
import i18n from "../i18nMessages.js";
|
|
|
|
const getCourses = async (profileObj) => {
|
|
let courses;
|
|
let popular;
|
|
await API.getCourses().then((data) => {
|
|
courses = data.groups;
|
|
popular = [...data.groups].sort((a, b) => {
|
|
return Object.keys(b.subscribed).length - Object.keys(a.subscribed).length;
|
|
});
|
|
});
|
|
let watching = {};
|
|
let watchingProms = [];
|
|
Object.keys(profileObj.data).forEach((videoId) => {
|
|
if (profileObj.data[videoId].profileId) {
|
|
let profileId = profileObj.data[videoId].profileId;
|
|
watchingProms.push(API.getUserProfile(profileId).then(profile => {
|
|
if (!profile.isCourse)
|
|
return 0;
|
|
if (!watching[profileId])
|
|
watching[profileId] = { profile, progress: [], mostRecent: 0 };
|
|
if (watching[profileId].mostRecent < profileObj.data[videoId].ts)
|
|
watching[profileId].mostRecent = profileObj.data[videoId].ts;
|
|
watching[profileId].progress.push(profileObj.data[videoId]);
|
|
}));
|
|
}
|
|
});
|
|
let watchingArray = [];
|
|
await Promise.all(watchingProms).then(() => {
|
|
for (const courseId in watching) {
|
|
watchingArray.push(watching[courseId]);
|
|
}
|
|
watchingArray = watchingArray.sort((a, b) => {
|
|
return b.mostRecent - a.mostRecent;
|
|
});
|
|
});
|
|
return {
|
|
courses: courses.slice(0, 10),
|
|
popular: popular.slice(0, 10),
|
|
watching: watchingArray.slice(0, 10),
|
|
}
|
|
}
|
|
|
|
const storeCoursesCache = async (value) => {
|
|
try {
|
|
const jsonValue = JSON.stringify(value)
|
|
await AsyncStorage.setItem('courses', jsonValue)
|
|
} catch (e) {
|
|
}
|
|
}
|
|
|
|
const getCoursesCache = async () => {
|
|
try {
|
|
const value = await AsyncStorage.getItem('courses')
|
|
if (value !== null) {
|
|
return JSON.parse(value);
|
|
}
|
|
} catch (e) {
|
|
return []
|
|
}
|
|
}
|
|
|
|
const Courses = () => {
|
|
const gState = useSnapshot(GlobalState);
|
|
const viewer = gState.me;
|
|
const [searchQuery, setSearchQuery] = React.useState('');
|
|
const [groups, setGroups] = React.useState([]);
|
|
const [popular, setPopular] = React.useState([]);
|
|
const [watching, setWatching] = React.useState([]);
|
|
const [queryTimer, setQueryTimer] = React.useState(0);
|
|
|
|
useEffect(() => {
|
|
let subscribed = true;
|
|
const getData = async () => {
|
|
await getCoursesCache().then((r) => {
|
|
console.log("Courses Cache");
|
|
setGroups(r.courses || []);
|
|
setPopular(r.popular || []);
|
|
setWatching(r.watching || []);
|
|
});
|
|
let r = await getCourses(viewer);
|
|
console.log("Courses Live");
|
|
if(subscribed){
|
|
setGroups(r.courses || []);
|
|
setPopular(r.popular || []);
|
|
setWatching(r.watching || []);
|
|
}
|
|
storeCoursesCache(r);
|
|
};
|
|
getData();
|
|
return () => {
|
|
subscribed = false;
|
|
}
|
|
}, [])
|
|
|
|
const onChangeSearch = query => {
|
|
setSearchQuery(query);
|
|
if (queryTimer) clearTimeout(queryTimer);
|
|
let timerId = setTimeout(() => {
|
|
if (!query) {
|
|
return API.getCourses('').then((data) => {
|
|
setGroups(data.groups || []);
|
|
});
|
|
}
|
|
API.searchCourses(query).then((data) => {
|
|
setGroups(data.groups || []);
|
|
})
|
|
|
|
}, 300);
|
|
setQueryTimer(timerId);
|
|
};
|
|
const renderProfile = (({ item }) => {
|
|
return (<CourseCard profileObj={item} />);
|
|
});
|
|
const watchingCourse = (({ item }) => {
|
|
return (<CourseCard profileObj={item.profile} />);
|
|
});
|
|
return (
|
|
<SafeAreaView style={styles.container}>
|
|
<Searchbar
|
|
placeholder = {i18n.t("message.searchCourses")}
|
|
onChangeText={onChangeSearch}
|
|
value={searchQuery}
|
|
/>
|
|
{groups.length ? <></> : <ActivityIndicator />}
|
|
<ScrollView>
|
|
{
|
|
watching.length ?
|
|
<View>
|
|
<Title style={styles.title} >{i18n.t("message.continueWatching")}:</Title>
|
|
<FlatList
|
|
horizontal={true}
|
|
data={watching}
|
|
renderItem={watchingCourse}
|
|
keyExtractor={item => item.profile._id}
|
|
initialNumToRender={2}
|
|
/>
|
|
</View> : <></>
|
|
}
|
|
{
|
|
groups.length ?
|
|
<>
|
|
<Title style={styles.title} >{i18n.t("message.recentlyAdded")}:</Title>
|
|
<FlatList
|
|
horizontal={true}
|
|
data={groups}
|
|
renderItem={renderProfile}
|
|
keyExtractor={item => item._id}
|
|
initialNumToRender={2}
|
|
/>
|
|
</> : <></>
|
|
}
|
|
{
|
|
popular.length ?
|
|
<>
|
|
<Title style={styles.title} >{i18n.t("message.popularCourses")}:</Title>
|
|
<FlatList
|
|
horizontal={true}
|
|
data={popular}
|
|
renderItem={renderProfile}
|
|
keyExtractor={item => item._id}
|
|
initialNumToRender={2}
|
|
/>
|
|
</> : <></>
|
|
}
|
|
</ScrollView>
|
|
</SafeAreaView>
|
|
)
|
|
}
|
|
|
|
export default Courses;
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1
|
|
},
|
|
title: {
|
|
padding: 10,
|
|
fontSize: 30,
|
|
marginTop: 15,
|
|
fontWeight: "bold",
|
|
color: "#777"
|
|
}
|
|
});
|