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

feature: nftunes radio loads 1st song via cache for fast playback and other ux and perf fixes #513

Merged
merged 2 commits into from
Sep 2, 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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "explorer-dapp",
"description": "Itheum Explorer is a DApp for the public to explore and visualize data within the Itheum protocol",
"version": "1.21.0",
"version": "1.21.1",
"author": "Itheum",
"license": "GPL-3.0-or-later",
"dependencies": {
Expand Down
Binary file removed src/assets/img/nf-tunes/platforms-logo/drip.png
Binary file not shown.
Binary file not shown.
Binary file removed src/assets/img/nf-tunes/platforms-logo/itheum.png
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed src/assets/img/nf-tunes/platforms-logo/tensor.png
Binary file not shown.
Binary file not shown.
Binary file removed src/assets/img/nf-tunes/platforms-logo/xoxno.png
Binary file not shown.
Binary file removed src/assets/img/spreadsheet-nfts/banner.jpg
Binary file not shown.
Binary file added src/assets/img/spreadsheet-nfts/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 35 additions & 6 deletions src/components/AudioPlayer/RadioPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "./AudioPlayer.css";
import DEFAULT_SONG_IMAGE from "assets/img/audio-player-image.png";
import DEFAULT_SONG_LIGHT_IMAGE from "assets/img/audio-player-light-image.png";
import { toastError } from "libs/utils";
import { useAppsStore } from "store/apps";
import { Button } from "../../libComponents/Button";

type RadioPlayerProps = {
Expand All @@ -27,6 +28,7 @@ export const RadioPlayer = (props: RadioPlayerProps) => {
const [duration, setDuration] = useState("00:00");
const [isLoaded, setIsLoaded] = useState(false);
const [songSource, setSongSource] = useState<{ [key: number]: string }>({}); // map to keep the already fetched songs
const appsStore = useAppsStore();

useEffect(() => {
audio.addEventListener("ended", function () {
Expand Down Expand Up @@ -106,13 +108,40 @@ export const RadioPlayer = (props: RadioPlayerProps) => {
[index]: "Fetching", // update the value of specific key
}));

const blob = await fetch(songs[index - 1].stream).then((r) => r.blob());
const blobUrl = URL.createObjectURL(blob);
let errMsg = null;
let blobUrl = "";

try {
const trackIndex = index - 1;
const nfTunesRadioFirstTrackCachedBlob = appsStore.nfTunesRadioFirstTrackCachedBlob;

// if we have cached the first song blob when Explorer loaded, then just load that from the cache direct to start the playback fast
if (trackIndex === 0 && nfTunesRadioFirstTrackCachedBlob && nfTunesRadioFirstTrackCachedBlob.trim() !== "") {
blobUrl = nfTunesRadioFirstTrackCachedBlob;
console.log(`Track ${trackIndex} Loaded from cache`);
console.log("nfTunesRadioFirstTrackCachedBlob ", nfTunesRadioFirstTrackCachedBlob);
} else {
console.log(`Track ${trackIndex} Loading on-Demand`);
const blob = await fetch(songs[trackIndex].stream).then((r) => r.blob());
blobUrl = URL.createObjectURL(blob);
}

console.log("blobUrl ", blobUrl);
} catch (error: any) {
errMsg = error.toString();
}

setSongSource((prevState) => ({
...prevState, // keep all other key-value pairs
[index]: blobUrl, // update the value of specific key
}));
if (!errMsg) {
setSongSource((prevState) => ({
...prevState, // keep all other key-value pairs
[index]: blobUrl, // update the value of specific key
}));
} else {
setSongSource((prevState) => ({
...prevState,
[index]: "Error: " + errMsg,
}));
}
} catch (err) {
setSongSource((prevState) => ({
...prevState,
Expand Down
47 changes: 35 additions & 12 deletions src/components/Layout/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import { useWallet } from "@solana/wallet-adapter-react";
import { Home, Menu, Store, Wallet, Gamepad2, AreaChart } from "lucide-react";
import { Link } from "react-router-dom";
Expand All @@ -7,13 +7,7 @@ import logo192 from "assets/img/logo192.png";
import { SolBitzDropdown } from "components/BitzDropdown/SolBitzDropdown";
import { CopyAddress } from "components/CopyAddress";
import { useGetAccount, useGetIsLoggedIn } from "hooks";
import { cn, sleep } from "libs/utils";
import { APP_MAPPINGS } from "libs/utils/constant";
import { returnRoute } from "pages/Home";
import { routeNames } from "routes";
import { useLocalStorageStore } from "store/LocalStorageStore.ts";
import { SwitchButton } from "./SwitchButton";
import { Button } from "../../libComponents/Button";
import { Button } from "libComponents/Button";
import {
DropdownMenu,
DropdownMenuContent,
Expand All @@ -22,16 +16,24 @@ import {
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "../../libComponents/DropdownMenu";
} from "libComponents/DropdownMenu";
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from "../../libComponents/NavigationMenu";
import { useAccountStore } from "../../store/account";
} from "libComponents/NavigationMenu";
import { cn, sleep } from "libs/utils";
import { APP_MAPPINGS } from "libs/utils/constant";
import { returnRoute } from "pages/Home";
import { routeNames } from "routes";
import { useAccountStore } from "store/account";
import { useAppsStore } from "store/apps";
import { useLocalStorageStore } from "store/LocalStorageStore.ts";
import { SwitchButton } from "./SwitchButton";
import { getNFTuneFirstTrackBlobData } from "../../pages/AppMarketplace/NFTunes";
import { MvxBitzDropdown } from "../BitzDropdown/MvxBitzDropdown";
import { PlayBitzModal } from "../PlayBitzModal/PlayBitzModal";

Expand All @@ -43,8 +45,29 @@ export const Navbar = () => {
const { address: addressMvx } = useGetAccount();
const bitzBalance = useAccountStore((state: any) => state.bitzBalance);
const setDefaultChain = useLocalStorageStore((state) => state.setDefaultChain);

const [showPlayBitzModal, setShowPlayBitzModal] = useState<boolean>(false);
const appsStore = useAppsStore();
const updateNfTunesRadioFirstTrackCachedBlob = appsStore.updateNfTunesRadioFirstTrackCachedBlob;

useEffect(() => {
// lets get the 1st song blob for NFTunes Radio, so we can store in the "browser" cache for fast playback
// ... we do it here as the NavBar loads first always
async function cacheFirstNFTuneRadioTrack() {
const nfTunesRadioFirstTrackCachedBlob = appsStore.nfTunesRadioFirstTrackCachedBlob;

if (nfTunesRadioFirstTrackCachedBlob === "") {
const trackBlobUrl = await getNFTuneFirstTrackBlobData();

if (trackBlobUrl !== "") {
console.log("NFTune Radio 1st Song Data Cached...");
}

updateNfTunesRadioFirstTrackCachedBlob(trackBlobUrl || "");
}
}

cacheFirstNFTuneRadioTrack();
}, []);

return (
<div className="flex flex-row justify-between items-center xl:mx-[7.5rem] md:mx-[4rem] h-20">
Expand Down
32 changes: 12 additions & 20 deletions src/pages/AppMarketplace/NFPodcast/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@ import { motion } from "framer-motion";
import { Music, Music2 } from "lucide-react";
import { Link } from "react-router-dom";
import { NF_PODCAST_TOKENS } from "appsConfig";
import musicNoteBlack from "assets/img/nf-tunes/music-note-black.png";
import musicNote from "assets/img/nf-tunes/music-note-white.png";
import disk from "assets/img/nf-tunes-logo-disk.png";
import stick from "assets/img/nf-tunes-logo-stick.png";
import backCube from "assets/img/zstorage/back.png";
import cubes from "assets/img/zstorage/cubes.png";
import dataLines from "assets/img/zstorage/data-lines.png";
import frontCube from "assets/img/zstorage/front.png";
import vault from "assets/img/zstorage/vault-dots.png";
import { MvxDataNftCard, Loader } from "components";
import { AudioPlayer } from "components/AudioPlayer/AudioPlayer";
import { HeaderComponent } from "components/Layout/HeaderComponent";
Expand All @@ -15,16 +23,7 @@ import { useGetPendingTransactions } from "hooks";
import { Button } from "libComponents/Button";
import { BlobDataType, ExtendedViewDataReturnType } from "libs/types";
import { decodeNativeAuthToken, getApiDataMarshal, toastError } from "libs/utils";
import { scrollToSection } from "libs/utils";
import { useNftsStore } from "store/nfts";
import musicNoteBlack from "../../../assets/img/nf-tunes/music-note-black.png";
import musicNote from "../../../assets/img/nf-tunes/music-note-white.png";
import stick from "../../../assets/img/nf-tunes-logo-stick.png";
import backCube from "../../../assets/img/zstorage/back.png";
import cubes from "../../../assets/img/zstorage/cubes.png";
import dataLines from "../../../assets/img/zstorage/data-lines.png";
import frontCube from "../../../assets/img/zstorage/front.png";
import vault from "../../../assets/img/zstorage/vault-dots.png";

export const NFPodcast = () => {
const { theme } = useTheme();
Expand Down Expand Up @@ -153,30 +152,23 @@ export const NFPodcast = () => {
<div className="flex flex-col justify-center items-center xl:items-start h-[100vsh] w-[100%] pt-8 xl:pt-16 mb-16 xl:mb-32 pl-4 ">
<div className="flex flex-col w-full xl:w-[60%] gap-6">
<div className="flex-row flex items-center">
<span className="text-5xl xl:text-[8rem] text-primary">NF-Podcast</span>
<span className="text-4xl xl:text-[6rem] text-primary">NF-Podcast</span>
<img className="max-h-[30%] mb-6" src={currentTheme === "dark" ? musicNote : musicNoteBlack} />
</div>
<div className="flex flex-row justify-between">
<span className="text-base md:text-2xl text-primary text-light w-[70%]">
<span className="text-base md:text-xl text-primary text-light w-[70%]">
Empowering content creators to engage with their communities and discover alternative avenues for content distribution
</span>
</div>

<button
onClick={() => scrollToSection("data-nfts")}
className="hover:scale-110 transition duration-700 text-sm md:text-xl p-2 md:p-4 rounded-lg max-w-[50%] xl:max-w-[35%] text-white
bg-gradient-to-br from-[#737373] from-5% via-[#A76262] via-40% to-[#5D3899] to-100%">
Visualize NF-Podcasts
</button>
</div>

<div className="flex flex-col xl:flex-row w-full justify-between items-center h-full">
<div className="p-6 pl-32">
<Music className="md:scale-[2] mb-8 ml-[14%] text-primary" />
</div>

<div className="relative min-h-[10rem] h-full w-full xl:-mt-[15%] -z-10">
<div className="absolute w-[60%] max-w-[500px] -mt-[10%] left-[20%] xl:left-[35%] h-[300px] xl:h-[500px] bg-gradient-to-br from-[#737373] from-20% via-[#A76262] via-40% to-[#5D3899] to-80% rounded-full filter blur-2xl opacity-25 "></div>
<div className="relative min-h-[10rem] h-full w-full xl:-mt-[5%] -z-10">
<div className="absolute w-[60%] max-w-[500px] -mt-[10%] left-[20%] xl:left-[35%] h-[300px] xl:h-[500px] bg-gradient-to-br from-[#737373] from-20% via-[#A76262] via-40% to-[#5D3899] to-80% rounded-full filter blur-2xl opacity-25 "></div>
<img className="animate-spin-slow w-[60%] left-[20%] xl:left-[40%] max-w-[350px] absolute" src={disk} alt="disk" />
<img className="absolute left-[60%] lg:left-[50%] xl:left-[70%] top-[-30px] xl:top-[-50px] w-[30%] max-w-[200px]" src={stick} alt="stick" />
</div>
Expand Down
Loading