Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: explore #360

Merged
merged 2 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@
"fflate": "^0.8.2",
"ffmpeg-kit-react-native": "^6.0.2",
"he": "^1.2.0",
"i18next": "^23.10.1",
"i18next": "^23.11.0",
"libmuse": "git+https://github.com/lovegaoshi/muse.git#apm-release",
"lottie-react-native": "^6.7.0",
"lottie-react-native": "^6.7.2",
"lru-cache": "7.14.0",
"md5": "^2.3.0",
"metro": "^0.80.8",
Expand Down Expand Up @@ -124,22 +124,22 @@
"@types/he": "^1.2.3",
"@types/jest": "^29.5.12",
"@types/md5": "^2.3.5",
"@types/node": "^20.12.4",
"@types/node": "^20.12.5",
"@types/react": "^18.2.74",
"@types/react-native": "^0.73.0",
"@types/react-native-background-timer": "^2.0.2",
"@types/react-native-share-menu": "^5.0.5",
"@types/react-native-video": "^5.0.20",
"@types/react-test-renderer": "^18.0.6",
"@types/uuid": "^9.0.8",
"@typescript-eslint/eslint-plugin": "^7.5.0",
"@typescript-eslint/parser": "^7.5.0",
"@typescript-eslint/eslint-plugin": "^7.6.0",
"@typescript-eslint/parser": "^7.6.0",
"@welldone-software/why-did-you-render": "^8.0.1",
"argparse": "^2.0.1",
"babel-jest": "^29.6.4",
"babel-plugin-module-resolver": "^5.0.0",
"cpx": "^1.5.0",
"eslint": "^8.56.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-babel-module": "^5.3.2",
"eslint-plugin-import": "^2.29.1",
Expand All @@ -154,9 +154,9 @@
"react-native-clean-project": "^4.0.1",
"react-native-dotenv": "^3.4.11",
"react-test-renderer": "18.2.0",
"reactotron-react-native": "^5.1.5",
"reactotron-react-native": "^5.1.6",
"rimraf": "^5.0.5",
"typescript": "5.4.3"
"typescript": "5.4.4"
},
"engines": {
"node": ">=18.0.0"
Expand Down
129 changes: 119 additions & 10 deletions src/components/explore/bilibili/View.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Image } from 'expo-image';
import { useTranslation } from 'react-i18next';
import { useNavigation } from '@react-navigation/native';

import { chunkArray } from '@utils/Utils';
import { fetchDynamic } from '@utils/mediafetch/biliDynamic';
import { fetchRanking } from '@utils/mediafetch/biliRanking';
import { styles } from '@components/style';
Expand All @@ -25,13 +26,75 @@ interface BiliCatSongs {

interface BiliSongCardProp {
songs: NoxMedia.Song[];
category: string;
title?: string;
totalSongs?: NoxMedia.Song[];
}

const BiliSongCard = ({
songs = [],
category = 'Dummy Category',
}: BiliSongCardProp) => {
const BiliSongRow = ({ songs = [], title, totalSongs }: BiliSongCardProp) => {
const navigationGlobal = useNavigation();
const playerStyle = useNoxSetting(state => state.playerStyle);
const { playAsSearchList } = usePlayback();

const fontColor = playerStyle.metaData.darkTheme ? 'white' : 'black';

return (
<View
style={{
width: Dimensions.get('window').width,
paddingRight: 10,
paddingLeft: 5,
}}
>
{title && (
<Text style={{ fontSize: 20, color: fontColor, paddingBottom: 5 }}>
{title}
</Text>
)}
<FlatList
showsHorizontalScrollIndicator={false}
data={songs}
horizontal
renderItem={({ item }) => (
<View style={{ paddingHorizontal: 5, flex: 1 }}>
<TouchableOpacity
onPress={() => {
navigationGlobal.navigate(ViewEnum.PLAYER_PLAYLIST as never);
playAsSearchList({ songs: totalSongs || songs, song: item });
}}
>
<Image
style={{ width: 140, height: 140, borderRadius: 5 }}
source={{ uri: item.cover }}
/>
<View style={{ flex: 1 }}>
<Text
style={{
color: fontColor,
paddingLeft: 5,
width: 140,
}}
variant="titleMedium"
numberOfLines={2}
>
{item.name}
</Text>
<Text
style={{ color: 'grey', paddingLeft: 5, width: 140 }}
variant="titleSmall"
numberOfLines={1}
>
{item.singer}
</Text>
</View>
</TouchableOpacity>
</View>
)}
/>
</View>
);
};

const BiliSongCard = ({ songs = [], title, totalSongs }: BiliSongCardProp) => {
const navigationGlobal = useNavigation();
const playerStyle = useNoxSetting(state => state.playerStyle);
const { playAsSearchList } = usePlayback();
Expand All @@ -47,7 +110,7 @@ const BiliSongCard = ({
paddingLeft: 5,
}}
>
<Text style={{ fontSize: 20, color: fontColor }}>{category}</Text>
{title && <Text style={{ fontSize: 20, color: fontColor }}>{title}</Text>}
<FlatList
showsVerticalScrollIndicator={false}
data={songs}
Expand All @@ -57,7 +120,7 @@ const BiliSongCard = ({
style={{ height: 70, flexDirection: 'row' }}
onPress={() => {
navigationGlobal.navigate(ViewEnum.PLAYER_PLAYLIST as never);
playAsSearchList({ songs, song: item });
playAsSearchList({ songs: totalSongs || songs, song: item });
}}
>
<Image
Expand Down Expand Up @@ -110,7 +173,7 @@ const BiliSongCatsCard = ({ songs = {} }: { songs?: BiliCatSongs }) => {
{Object.keys(songs).map(k => (
<BiliSongCard
key={k}
category={t(`BiliCategory.${k}`)}
title={t(`BiliCategory.${k}`)}
songs={songs[Number(k)]}
/>
))}
Expand All @@ -120,7 +183,46 @@ const BiliSongCatsCard = ({ songs = {} }: { songs?: BiliCatSongs }) => {
);
};

const BiliSongsTabCard = ({
songs = {},
title,
}: {
songs?: BiliCatSongs;
title: string;
}) => {
const concatSongs = Object.values(songs).reduce(
(acc, curr) => acc.concat(curr),
[]
);
const splicedSongs: NoxMedia.Song[][] = chunkArray(concatSongs, 4);

return (
<View>
<Text style={{ fontSize: 20, paddingLeft: 5, paddingBottom: 10 }}>
{title}
</Text>
<ScrollView
horizontal
disableIntervalMomentum
snapToInterval={Dimensions.get('window').width * 0.8}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
>
{splicedSongs.map((k, i) => (
<BiliSongCard
key={`BiliRankTab${i}`}
songs={k}
totalSongs={concatSongs}
/>
))}
<View style={{ width: Dimensions.get('window').width * 0.2 }}></View>
</ScrollView>
</View>
);
};

export default () => {
const { t } = useTranslation();
const [biliDynamic, setBiliDynamic] = React.useState<BiliCatSongs>({});
const [biliRanking, setBiliRanking] = React.useState<BiliCatSongs>({});
const [refreshing, setRefreshing] = React.useState(false);
Expand All @@ -129,7 +231,7 @@ export default () => {
const initData = async () =>
Promise.all([
fetchRanking().then(setBiliRanking),
// fetchDynamic().then(setBiliDynamic),
fetchDynamic().then(setBiliDynamic),
]);

const onRefresh = React.useCallback(() => {
Expand Down Expand Up @@ -160,7 +262,14 @@ export default () => {
<Text style={{ paddingHorizontal: 5, fontSize: 20 }}>
Bilibili experimental discover page
</Text>
<BiliSongCatsCard songs={biliRanking} />
<BiliSongsTabCard songs={biliRanking} title={t('BiliCategory.ranking')} />
{Object.keys(biliDynamic).map((k, i) => (
<BiliSongRow
key={`BiliDynamicRow${i}`}
songs={biliDynamic[Number(k)]}
title={t(`BiliCategory.${k}`)}
/>
))}
</ScrollView>
);
};
2 changes: 1 addition & 1 deletion src/enums/MediaFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ MV mv 193 为音乐作品配合拍摄或制作的音乐录影带(Music Video
音乐教学 tutorial 244 以音乐教学为目的的内容 /v/music/tutorial
电音(已下线) electronic 194 以电子合成器、音乐软体等产生的电子声响制作的音乐 /v/music/electronic
*/
export const BiliMusicTid = [28, 31, 59, 193, 29];
export const BiliMusicTid = [28, 31, 59, 193]; // , 29
14 changes: 2 additions & 12 deletions src/utils/ChromeStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { dummyPlaylist, dummyPlaylistList } from '../objects/Playlist';
import { NoxRepeatMode } from '../enums/RepeatMode';
import { PLAYLIST_ENUMS } from '../enums/Playlist';
import AzusaTheme from '../components/styles/AzusaTheme';
import { chunkArray as chunkArrayRaw, arrayToObject } from '../utils/Utils';
import { chunkArray, arrayToObject } from '../utils/Utils';
import {
STORAGE_KEYS,
appID,
Expand Down Expand Up @@ -147,16 +147,6 @@ export const removeCookie = async (site: string) => {
saveItem(STORAGE_KEYS.COOKIES, cookies);
};

/**
* splits an array to chunks of given size.
* @param arr
* @param size
* @returns
*/
const chunkArray = <T>(arr: Array<T>, size = MAX_SONGLIST_SIZE): Array<T[]> => {
return chunkArrayRaw(arr, size);
};

/**
* a generic chunk splitter to store arrays that may exceed 2MB storage limits.
* see known storage limits:
Expand All @@ -170,7 +160,7 @@ const saveChucked = async (
saveToStorage = true
) => {
// splice into chunks
const chuckedObject = chunkArray(objects);
const chuckedObject = chunkArray(objects, MAX_SONGLIST_SIZE);
const chuckedIndices = chuckedObject.map((val, index) => `${key}.${index}`);
chuckedObject.forEach((list, index) => saveItem(chuckedIndices[index], list));
if (saveToStorage) {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const getUniqObjects = <T>(
* @param size
* @returns
*/
export const chunkArray = <T>(arr: Array<T>, size: number): Array<T[]> => {
export const chunkArray = <T>(arr: Array<T>, size = 400): Array<T[]> => {
return arr.reduce(
(chunks, item, index) => {
const chunkIndex = Math.floor(index / size);
Expand Down
Loading
Loading