├── 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 |
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 |
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 |
35 |
36 |
37 |
{/* Icon set in css */}
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | {/* Icon set in css */}
50 |
51 |
56 |
57 |
58 |
62 |
63 |
64 |
65 |
66 | );
67 | }
68 |
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 |
2 | a {
3 | text-decoration: none;
4 | }
5 |
6 | #renderer {
7 | height: 100%;
8 | }
9 |
10 | .jp-title li{
11 | font-size: 32px;
12 | color: white;
13 | }
14 |
15 | /* Header styling */
16 | header {
17 | height: 3em;
18 | width: 100%;
19 | top: 0px;
20 | position: absolute;
21 | display: flex;
22 | background: #f34927;
23 | background: -moz-linear-gradient(bottom, #f34927 0%, #dd3311 100%);
24 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f34927), color-stop(100%,#dd3311));
25 | background: -webkit-linear-gradient(bottom, #f34927 0%,#dd3311 100%);
26 | background: -o-linear-gradient(bottom, #f34927 0%,#dd3311 100%);
27 | background: -ms-linear-gradient(bottom, #f34927 0%,#dd3311 100%);
28 | background: linear-gradient(to bottom, #f34927 0%,#dd3311 100%);
29 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f34927', endColorstr='#dd3311',GradientType=0 );
30 | -webkit-box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, .1);
31 | box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, .1);
32 | border-radius: 3px;
33 | }
34 | header>h1 {
35 | font-family: diskopia;
36 | font-size: 2.5em;
37 | text-shadow: 2px 2px purple;
38 | float: left;
39 | }
40 |
41 | header a {
42 | position: absolute;
43 | right: 1em;
44 | top: 10%;
45 | color: black;
46 | font-size: 1.5em;
47 | float: right;
48 | }
49 |
50 | @media only screen and (max-width: 768px) {
51 | header>h1 {
52 | font-size: 1.2em;
53 | }
54 | header a {
55 | font-size: 1.3em;
56 | }
57 | header span {
58 | display: none;
59 | }
60 | }
61 |
62 |
63 |
64 | @font-face {
65 | font-family: diskopia;
66 | src: url("./fonts/diskopia.ttf");
67 |
68 | }
69 |
70 | /* End of Header Styling */
71 |
72 |
73 |
74 | .por_portis-container>.por_portis-widget-frame {
75 | top: 3.5em;
76 | right: 10px;
77 | }
78 |
79 |
80 | header {
81 | padding-left: 5px;
82 | clear: left;
83 | text-align: left;
84 | }
85 |
86 | header ul {
87 | padding-left: 50px;
88 | list-style-type: none;
89 | margin: 0;
90 | overflow: hidden;
91 | }
92 |
93 |
94 | header li {
95 | display: block;
96 | color: white;
97 | text-align: center;
98 | padding: 14px 16px;
99 | text-decoration: none;
100 | float: left;
101 | }
102 |
103 | .wallet {
104 | display: block;
105 | position: absolute;
106 | top: 3.5em;
107 | right: 10px;
108 | width: 353px;
109 | float: right;
110 | }
111 |
112 | #player {
113 | position: absolute;
114 | bottom: 10px;
115 | display: block;
116 | margin: 0 auto;
117 | width: 50%;
118 | left: 0;
119 | right: 0;
120 | }
121 |
122 |
123 | img {
124 | position: fixed;
125 | width: 300px;
126 | height: 300px;
127 | border-radius: 50%;
128 | right: 0;
129 | }
130 |
131 | body {
132 | height: 100%;
133 | }
134 |
--------------------------------------------------------------------------------
/src/fonts/DISKOPIA2.0.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
580 |
--------------------------------------------------------------------------------