├── public ├── robots.txt ├── img │ └── favicon.ico ├── manifest.json └── index.html ├── src ├── fonts │ ├── diskopia.ttf │ ├── DISKOPIA2.0.eot │ ├── DISKOPIA2.0.otf │ ├── DISKOPIA2.0.woff │ └── DISKOPIA2.0.svg ├── media │ ├── Vultures.mp3 │ └── vultures.png ├── AlbumArt.jsx ├── Background.jsx ├── App.js ├── index.js ├── AudioPlayer │ └── style.css ├── AudioPlayer.jsx └── style.css ├── .gitignore ├── package.json └── README.md /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caseyjkey/ipfs-music-player/HEAD/public/img/favicon.ico -------------------------------------------------------------------------------- /src/fonts/diskopia.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caseyjkey/ipfs-music-player/HEAD/src/fonts/diskopia.ttf -------------------------------------------------------------------------------- /src/media/Vultures.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caseyjkey/ipfs-music-player/HEAD/src/media/Vultures.mp3 -------------------------------------------------------------------------------- /src/media/vultures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caseyjkey/ipfs-music-player/HEAD/src/media/vultures.png -------------------------------------------------------------------------------- /src/fonts/DISKOPIA2.0.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caseyjkey/ipfs-music-player/HEAD/src/fonts/DISKOPIA2.0.eot -------------------------------------------------------------------------------- /src/fonts/DISKOPIA2.0.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caseyjkey/ipfs-music-player/HEAD/src/fonts/DISKOPIA2.0.otf -------------------------------------------------------------------------------- /src/fonts/DISKOPIA2.0.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caseyjkey/ipfs-music-player/HEAD/src/fonts/DISKOPIA2.0.woff -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | .idea/ 4 | .vscode/ 5 | node_modules/ 6 | build 7 | .DS_Store 8 | *.tgz 9 | my-app* 10 | template/src/__tests__/__snapshots__/ 11 | lerna-debug.log 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | /.changelog 16 | .npm/ 17 | yarn.lock 18 | 19 | # dependencies 20 | /node_modules 21 | /.pnp 22 | .pnp.js 23 | 24 | # testing 25 | /coverage 26 | 27 | # production 28 | /build 29 | 30 | # misc 31 | .DS_Store 32 | .env.local 33 | .env.development.local 34 | .env.test.local 35 | .env.production.local 36 | 37 | npm-debug.log* 38 | yarn-debug.log* 39 | yarn-error.log* 40 | -------------------------------------------------------------------------------- /src/AlbumArt.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | // We almost just want this to be passed in a image object or url and then send out an http request to 3 | // go retreve and render. In the encap player component. 4 | function AlbumArt({ image, width, height }) { 5 | 6 | const [centerX, setCenterX] = useState(window.innerWidth / 2); 7 | const [centerY, setCenterY] = useState((window.innerHeight / 2) - 75); 8 | useEffect(() => { 9 | setCenterX(window.innerWidth / 2); 10 | setCenterY((window.innerHeight / 2) - 75); 11 | }, [centerX, centerY]); 12 | 13 | 14 | const styles = { 15 | left: centerX - 150, 16 | top: centerY - 100 17 | }; 18 | 19 | return( 20 | album cover art 21 | ) 22 | } 23 | 24 | export default AlbumArt; -------------------------------------------------------------------------------- /src/Background.jsx: -------------------------------------------------------------------------------- 1 | import React, {useEffect} from 'react' 2 | 3 | export default function Background() { 4 | function setGradient() { 5 | // set to the size of device 6 | let canvas = document.getElementById("gradient"); 7 | let ctx = canvas.getContext("2d"); 8 | 9 | canvas.width = window.innerWidth; 10 | canvas.height = window.innerHeight - 6; 11 | 12 | let gradient = ctx.createLinearGradient(0,0,0,canvas.height); 13 | gradient.addColorStop(0,"rgba(35, 7, 77, 1)"); 14 | gradient.addColorStop(1,"rgba(204, 83, 51, 1)"); 15 | ctx.fillStyle = gradient; 16 | ctx.fillRect(0,0,canvas.width,canvas.height); 17 | } 18 | 19 | 20 | // Set the background to a gradient when component mounts 21 | useEffect(() => { 22 | setGradient(); 23 | }, []); 24 | 25 | return ( 26 | 27 | ); 28 | } -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Background from './Background' 3 | import AlbumArt from './AlbumArt' 4 | import './style.css'; 5 | import albumCover from "./media/vultures.png"; 6 | import Vultures from './media/Vultures.mp3'; 7 | import AudioPlayer from './AudioPlayer' 8 | import { FaCode } from 'react-icons/fa' 9 | 10 | function App() { 11 | let media = { 12 | title: 'Vultures', 13 | artist: 'Pervsydell', 14 | sources: { 15 | m4a: Vultures, 16 | }, 17 | free: true, 18 | }; 19 | 20 | return ( 21 |
22 |
23 |

IPFS Music Player

24 | by Casey Key 25 |
26 | 27 | 28 | 29 |
30 | ); 31 | } 32 | 33 | export default App; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "etherradio", 3 | "homepage": "./", 4 | "version": "0.1.0", 5 | "private": true, 6 | "dependencies": { 7 | "bootstrap": "^4.4.1", 8 | "react": "^16.12.0", 9 | "react-dom": "^16.12.0", 10 | "react-icons": "^3.9.0", 11 | "react-jplayer": "^7.1.3", 12 | "react-less-watcher": "^1.1.4", 13 | "react-redux": "^5.0.7", 14 | "react-scripts": "3.4.0", 15 | "redux": "^4.0.5" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject" 22 | }, 23 | "eslintConfig": { 24 | "extends": "react-app" 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { createStore, combineReducers } from 'redux'; 5 | import { reducer as jPlayers } from 'react-jplayer'; 6 | import 'bootstrap/dist/css/bootstrap.css'; 7 | 8 | import App from './App'; 9 | 10 | // Styles the jPlayer to look nice 11 | import 'react-jplayer/dist/css/skins/sleek.min.css'; 12 | // Styles Play/Pause/Mute etc when icons () are used for them 13 | import 'react-jplayer/dist/css/controls/iconControls.min.css'; 14 | 15 | /* Pass the jPlayer reducer and it's initialStates to the store */ 16 | const store = createStore(combineReducers({ jPlayers })); 17 | 18 | ReactDOM.render(( 19 | 20 | 21 | 22 | ), document.getElementById('root')); 23 | 24 | // If you want your app to work offline and load faster, you can change 25 | // unregister() to register() below. Note this comes with some pitfalls. 26 | // Learn more about service workers: https://bit.ly/CRA-PWA 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## IPFS Music Player Template 2 | 3 | Join the decentralized web with this music player template! 4 | 5 | ## Making it your own 6 | ### Edit the source 7 | * `/src/App.jsx` 8 | * Contains the location to your song, album art, title, and artist. 9 | * `/public/index.html` 10 | * Contains the title, description, and favicon for your website. 11 | 12 | ### Test your website 13 | 14 | #### `npm run start` 15 | Runs the app in the development mode.
16 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 17 | 18 | The page will reload if you make edits.
19 | You will also see any lint errors in the console. 20 | 21 | ### Deploy your website 22 | 23 | #### 1. `npm run build` 24 | 25 | Builds the app for production to the `build` folder.
26 | It correctly bundles React in production mode and optimizes the build for the best performance. 27 | 28 | The build is minified and the filenames include the hashes.
29 | Your app is ready to be deployed! 30 | 31 | #### 2. `pinata.cloud` 32 | 33 | Deploy it at `pinata.cloud` using folder upload! More instructions are found [here](https://medium.com/pinata/how-to-easily-host-a-website-on-ipfs-9d842b5d6a01). 34 | 35 | 36 | ## Want more features? 37 | 38 | Connect with me and my team at [my website](https://caseyjkey.com/). 39 | 40 | ## Learn more 41 | 42 | This template is built with React and a handful of npm modules. To learn React, check out the [React documentation](https://reactjs.org/). 43 | 44 | -------------------------------------------------------------------------------- /src/AudioPlayer/style.css: -------------------------------------------------------------------------------- 1 | #player { 2 | position: absolute; 3 | bottom: 10px; 4 | display: block; 5 | margin: 0 auto; 6 | width: 50%; 7 | left: 0; 8 | right: 0; 9 | } 10 | 11 | .jp-title { 12 | font-size: 12px; 13 | text-align: center; 14 | color: #999; 15 | } 16 | 17 | .jp-title ul { 18 | padding: 0; 19 | margin: 0; 20 | list-style: none; 21 | } 22 | 23 | .jp-gui { 24 | position: relative; 25 | background: #f34927; 26 | background: -moz-linear-gradient(top, #f34927 0%, #dd3311 100%); 27 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f34927), color-stop(100%,#dd3311)); 28 | background: -webkit-linear-gradient(top, #f34927 0%,#dd3311 100%); 29 | background: -o-linear-gradient(top, #f34927 0%,#dd3311 100%); 30 | background: -ms-linear-gradient(top, #f34927 0%,#dd3311 100%); 31 | background: linear-gradient(to bottom, #f34927 0%,#dd3311 100%); 32 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f34927', endColorstr='#dd3311',GradientType=0 ); 33 | -webkit-box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, .1); 34 | box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, .1); 35 | border-radius: 3px; 36 | overflow: hidden; 37 | margin-top: 10px; 38 | } 39 | 40 | .jp-jplayer,.jp-audio { 41 | width: 420px; 42 | margin: 50px auto; 43 | } 44 | 45 | .jp-controls { 46 | padding: 0; 47 | margin: 0; 48 | list-style: none; 49 | font-family: "FontAwesome"; 50 | text-shadow: 1px 1px 0 rgba(0,0,0,0.3); 51 | } 52 | 53 | .jp-controls li { 54 | display: inline; 55 | } -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 16 | 17 | 21 | 30 | IPFS Music Player 31 | 32 | 33 | 34 |
35 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/AudioPlayer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import JPlayer, { 3 | initializeOptions, Gui, SeekBar, BufferBar, 4 | Poster, Audio, Title, Mute, Play, PlayBar, Repeat, 5 | VolumeBar, Duration, CurrentTime, Download, BrowserUnsupported, 6 | } from 'react-jplayer'; 7 | 8 | 9 | 10 | 11 | export default function AudioPlayer(props) { 12 | let defaultOptions = { 13 | id: 'AudioPlayer', 14 | keyEnabled: true, 15 | verticalVolume: true, 16 | media: { 17 | title: '', 18 | artist: '', 19 | sources: { 20 | }, 21 | free: true, 22 | }, 23 | }; 24 | 25 | if(props.media) { 26 | defaultOptions = { ...defaultOptions, ...props }; 27 | } 28 | 29 | 30 | initializeOptions(defaultOptions); 31 | 32 | return ( 33 | 34 |