From e900ea62a6ebf1bb1b25ed7e5207f38f0ab05565 Mon Sep 17 00:00:00 2001 From: greenflame089 Date: Tue, 5 Aug 2025 03:42:33 -0400 Subject: [PATCH 1/8] Fix back button --- src/App.tsx | 2 ++ src/hooks/useIframe.tsx | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/hooks/useIframe.tsx diff --git a/src/App.tsx b/src/App.tsx index 4643d25..2f90399 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,7 @@ // @ts-nocheck import { useEffect, useState } from "react"; import { Routes, Route } from "react-router-dom"; +import { useIframe } from './hooks/useIframe' import { StoreList } from "./pages/StoreList/StoreList"; import { ThemeProvider } from "@mui/material/styles"; import { CssBaseline } from "@mui/material"; @@ -26,6 +27,7 @@ function App() { // const themeColor = window._qdnTheme const [theme, setTheme] = useState("dark"); + useIframe() return ( diff --git a/src/hooks/useIframe.tsx b/src/hooks/useIframe.tsx new file mode 100644 index 0000000..09d68c5 --- /dev/null +++ b/src/hooks/useIframe.tsx @@ -0,0 +1,27 @@ +import { useEffect } from "react"; +import { useNavigate } from "react-router-dom"; + +export const useIframe = () => { + const navigate = useNavigate(); + useEffect(() => { + function handleNavigation(event: MessageEvent) { + if (event.data?.action === "NAVIGATE_TO_PATH" && event.data.path) { + console.log("Navigating to path within React app:", event.data.path); + navigate(event.data.path); // Navigate directly to the specified path + + // Send a response back to the parent window after navigation is handled + window.parent.postMessage( + { action: "NAVIGATION_SUCCESS", path: event.data.path }, + "*" + ); + } + } + + window.addEventListener("message", handleNavigation); + + return () => { + window.removeEventListener("message", handleNavigation); + }; + }, [navigate]); + return { navigate }; +}; -- 2.43.0 From db680526fbc25e63fe78b438bf01574717d4f1c3 Mon Sep 17 00:00:00 2001 From: greenflame089 Date: Tue, 5 Aug 2025 05:28:48 -0400 Subject: [PATCH 2/8] Fix add song and playlist buttons --- src/components/AddLibrary.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/components/AddLibrary.tsx b/src/components/AddLibrary.tsx index 358396b..4fb07a2 100644 --- a/src/components/AddLibrary.tsx +++ b/src/components/AddLibrary.tsx @@ -59,15 +59,14 @@ export const AddLibrary: React.FC = ({ <>
-
+
- -

+ +

Add Song

-
+
- -

+ +

Add Playlist

= ({ children, className, }) => { - const username = useSelector((state: RootState) => state?.auth?.user?.name); + const selectedName = useSelector((state: RootState) => state?.auth?.user?.selectedName); + const names = useSelector((state: RootState) => state?.auth?.user?.names || []); const dispatch = useDispatch() - - async function getNameInfo(address: string) { - const response = await fetch("/names/address/" + address); - const nameData = await response.json(); - - if (nameData?.length > 0) { - return nameData[0].name; - } else { - return ""; - } - } + const [openNames, setOpenNames] = useState(false); const askForAccountInformation = useCallback(async () => { try { let account = await qortalRequest({ action: "GET_USER_ACCOUNT" }); - - const name = await getNameInfo(account.address); - dispatch(addUser({ ...account, name })); + const [namesList, primaryName] = await Promise.all([ + getAccountNames(account.address), + getPrimaryAccountName(account.address) + ]); + const chosen = primaryName || (namesList && namesList[0]) || ""; + dispatch(addUser({ + ...account, + names: namesList, + primaryName, + selectedName: chosen, + name: chosen + })); } catch (error) { console.error(error); } @@ -127,9 +128,8 @@ const Header: React.FC = ({
- {!username && ( + {!selectedName && ( <> -
)} + {selectedName && ( +
+ + {openNames && ( +
+ {names.map((n: string) => ( + + ))} +
+ )} +
+ )}
{children} diff --git a/src/pages/Library/Library.tsx b/src/pages/Library/Library.tsx index 52209c7..c11f825 100644 --- a/src/pages/Library/Library.tsx +++ b/src/pages/Library/Library.tsx @@ -1,4 +1,6 @@ import React, { useMemo, useState , useRef, useEffect, useCallback} from 'react' +import { useDispatch } from 'react-redux' +import { clearSongListLibrary } from '../../state/features/globalSlice' import Header from '../../components/Header' import ListItem from '../../components/ListItem' import likeImg from '../../assets/img/liked.png' @@ -17,6 +19,8 @@ import useOnPlay from '../../hooks/useOnPlay' import { MyPlaylists } from '../Playlists/MyPlaylists' export const Library = () => { const initialFetch = useRef(false) + const prevNameRef = useRef(undefined) + const dispatch = useDispatch() const username = useSelector((state: RootState) => state?.auth?.user?.name); const songListLibrary = useSelector((state: RootState) => state?.global.songListLibrary); const [mode, setMode] = useState('songs') @@ -45,13 +49,18 @@ export const Library = () => { }, [username, getYourLibrary]) useEffect(()=> { - if(username && !initialFetch.current){ - fetchMyLibrary() + if (!username) return; + if (prevNameRef.current && prevNameRef.current !== username) { + dispatch(clearSongListLibrary()); + initialFetch.current = false; + fetchMyLibrary(); + } else if (!initialFetch.current) { + fetchMyLibrary(); } + prevNameRef.current = username; + }, [username, fetchMyLibrary, dispatch]) - }, [username]) return ( -
= ({ children, setTheme }) => { const songHash = useSelector((state: RootState) => state.global.songHash); const imageCoverHash = useSelector((state: RootState) => state.global.imageCoverHash); const songListRecent = useSelector((state: RootState) => state.global.imageCoverHash); + useEffect(() => { - if (!user?.name) return; - + if (!user?.selectedName && !user?.name) return; getAvatar(); - }, [user?.name]); - - - - + }, [user?.selectedName, user?.name]); const getAvatar = async () => { try { let url = await qortalRequest({ action: "GET_QDN_RESOURCE_URL", - name: user?.name, + name: user?.selectedName || user?.name, service: "THUMBNAIL", identifier: "qortal_avatar" }); @@ -63,28 +60,24 @@ const GlobalWrapper: React.FC = ({ children, setTheme }) => { isLoadingGlobal, } = useSelector((state: RootState) => state.global); - async function getNameInfo(address: string) { - const response = await fetch("/names/address/" + address); - const nameData = await response.json(); - - if (nameData?.length > 0) { - return nameData[0].name; - } else { - return ""; - } - } - - - - const askForAccountInformation = React.useCallback(async () => { try { let account = await qortalRequest({ action: "GET_USER_ACCOUNT" }); - const name = await getNameInfo(account.address); - dispatch(addUser({ ...account, name })); + const [names, primaryName] = await Promise.all([ + getAccountNames(account.address), + getPrimaryAccountName(account.address) + ]); + const selectedName = primaryName || (names && names[0]) || ""; + dispatch(addUser({ + ...account, + names, + primaryName, + selectedName, + name: selectedName + })); } catch (error) { console.error(error); } -- 2.43.0 From 12ae4814d1a94bd0a65101a0fd402d36720404f9 Mon Sep 17 00:00:00 2001 From: greenflame089 Date: Wed, 6 Aug 2025 15:06:49 -0400 Subject: [PATCH 4/8] Fix text and search bar --- src/components/AddLibrary.tsx | 2 +- src/components/SearchInput.tsx | 67 ++++++++++++++------- src/components/SearchInputPlaylist.tsx | 80 +++++++++++++++----------- src/components/UploadModal.tsx | 24 ++++---- src/components/UploadPlaylistModal.tsx | 26 ++++----- 5 files changed, 118 insertions(+), 81 deletions(-) diff --git a/src/components/AddLibrary.tsx b/src/components/AddLibrary.tsx index 4fb07a2..dd15758 100644 --- a/src/components/AddLibrary.tsx +++ b/src/components/AddLibrary.tsx @@ -105,7 +105,7 @@ export const AddLibrary: React.FC = ({ className="bg-blue-500 text-white px-4 py-2 rounded" onClick={() => { uploadPlaylistModal.onOpen() }} > - Save Playlist + Edit Playlist + )} +
); -} - -export default SearchInput; \ No newline at end of file +}; + +export default SearchInput; diff --git a/src/components/SearchInputPlaylist.tsx b/src/components/SearchInputPlaylist.tsx index a5f190a..f18f275 100644 --- a/src/components/SearchInputPlaylist.tsx +++ b/src/components/SearchInputPlaylist.tsx @@ -1,51 +1,61 @@ - -import { useEffect, useState } from "react"; - - +import { useEffect, useRef } from "react"; import Input from "./Input"; -import { resetQueriedList, resetQueriedListPlaylist, setIsQueryingPlaylist, setQueriedValue, setQueriedValuePlaylist } from "../state/features/globalSlice"; +import { + resetQueriedListPlaylist, + setIsQueryingPlaylist, + setQueriedValuePlaylist, +} from "../state/features/globalSlice"; import { useDispatch, useSelector } from "react-redux"; import { useFetchSongs } from "../hooks/fetchSongs"; import { RootState } from "../state/store"; -import { FaUndoAlt } from "react-icons/fa"; export const SearchInputPlaylist = () => { - const dispatch = useDispatch() - const {getPlaylistsQueried} = useFetchSongs() + const dispatch = useDispatch(); + const { getPlaylistsQueried } = useFetchSongs(); const queriedValuePlaylist = useSelector((state: RootState) => state.global.queriedValuePlaylist); const isQueryingPlaylist = useSelector((state: RootState) => state.global.isQueryingPlaylist); + const inputRef = useRef(null); + useEffect(() => { + inputRef.current?.focus(); + }, []); + const handleInputKeyDown = (event: any) => { - if (event.key === 'Enter') { - dispatch(resetQueriedListPlaylist()) - if(!queriedValuePlaylist){ - dispatch(setIsQueryingPlaylist(false)) + if (event.key === "Enter") { + dispatch(resetQueriedListPlaylist()); + if (!queriedValuePlaylist) { + dispatch(setIsQueryingPlaylist(false)); } else { - dispatch(setIsQueryingPlaylist(true)) - getPlaylistsQueried() + dispatch(setIsQueryingPlaylist(true)); + getPlaylistsQueried(); } - } - } + }; + return ( -
- { - dispatch(setQueriedValuePlaylist(e.target.value)) - }} - value={queriedValuePlaylist} - onKeyDown={handleInputKeyDown} - /> - {isQueryingPlaylist && ( - { - dispatch(resetQueriedListPlaylist()) - dispatch(setIsQueryingPlaylist(false)) - dispatch(setQueriedValuePlaylist('')) - }} /> - )} - +
+
+ dispatch(setQueriedValuePlaylist(e.target.value))} + onKeyDown={handleInputKeyDown} + /> + {queriedValuePlaylist && ( + + )} +
- ); -} +}; diff --git a/src/components/UploadModal.tsx b/src/components/UploadModal.tsx index 49854c2..3ab6120 100644 --- a/src/components/UploadModal.tsx +++ b/src/components/UploadModal.tsx @@ -71,7 +71,7 @@ const UploadModal = () => { }) if (!compressedFile) return const dataURI = await toBase64(compressedFile) - if(!dataURI || typeof dataURI !== 'string') throw new Error('invalid image') + if(!dataURI || typeof dataURI !== 'string') throw new Error('Invalid image') const base64Data = dataURI?.split(',')[1]; return base64Data } catch (error) { @@ -87,7 +87,7 @@ const UploadModal = () => { return; } if(!values.image?.[0]){ - toast.error('Please attach an image cover') + toast.error('Please select a cover image') return; } setIsLoading(true); @@ -185,14 +185,14 @@ const UploadModal = () => { if (songError) { setIsLoading(false); - return toast.error('Failed song upload'); + return toast.error('Failed to publish audio'); } if (imageError) { setIsLoading(false); - return toast.error('Failed image upload'); + return toast.error('Failed to publish image'); } @@ -200,7 +200,7 @@ const UploadModal = () => { setIsLoading(false); - toast.success('Song created!'); + toast.success('Audio published successfully!'); reset(); uploadModal.onClose(); } catch (error) { @@ -214,8 +214,8 @@ const UploadModal = () => { return ( @@ -227,17 +227,17 @@ const UploadModal = () => { id="title" disabled={isLoading} {...register('title', { required: true , maxLength: 35})} - placeholder="Song title" + placeholder="Title" />
- Select a song file + Select an audio file
{
- Select an image + Select a cover image
{ />
diff --git a/src/components/UploadPlaylistModal.tsx b/src/components/UploadPlaylistModal.tsx index 65890a1..e9a1680 100644 --- a/src/components/UploadPlaylistModal.tsx +++ b/src/components/UploadPlaylistModal.tsx @@ -115,7 +115,7 @@ const UploadPlaylistModal = () => { }) if (!compressedFile) return const dataURI = await toBase64(compressedFile) - if(!dataURI || typeof dataURI !== 'string') throw new Error('invalid image') + if(!dataURI || typeof dataURI !== 'string') throw new Error('Invalid image') const base64Data = dataURI?.split(',')[1]; return base64Data } catch (error) { @@ -131,7 +131,7 @@ const UploadPlaylistModal = () => { return; } if(!values.image?.[0] && !prevSavedImg){ - toast.error('Please attach an image cover') + toast.error('Please select a cover image') return; } @@ -189,7 +189,7 @@ const UploadPlaylistModal = () => { filename } // { - // name: username, + // name: username, // service: 'THUMBNAIL', // data64: compressedImg, // identifier: identifier @@ -203,7 +203,7 @@ const UploadPlaylistModal = () => { await qortalRequest(multiplePublish) toast.success('Song created!'); if(newPlaylist?.id){ - //update playlist in store + // Update playlist in store dispatch(addToPlaylistHashMap( { user: newPlaylist?.user ? newPlaylist?.user : username, @@ -259,14 +259,14 @@ const UploadPlaylistModal = () => { if (songError) { setIsLoading(false); - return toast.error('Failed song upload'); + return toast.error('Failed to publish audio'); } if (imageError) { setIsLoading(false); - return toast.error('Failed image upload'); + return toast.error('Failed to publish image'); } @@ -274,7 +274,7 @@ const UploadPlaylistModal = () => { setIsLoading(false); - + toast.success('Playlist published successfully!'); } catch (error) { toast.error('Something went wrong'); } finally { @@ -295,8 +295,8 @@ const UploadPlaylistModal = () => { return ( @@ -308,17 +308,17 @@ const UploadPlaylistModal = () => { id="title" disabled={isLoading} {...register('title', { required: true , maxLength: 35})} - placeholder="Playlist title" + placeholder="Title" />