init
42
.gitignore
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Production build
|
||||
www/
|
BIN
assets-src/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets-src/web-icon.png
Normal file
After Width: | Height: | Size: 15 KiB |
19
framework7.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"cwd": "/home/les/dev/plaid2",
|
||||
"type": [
|
||||
"web"
|
||||
],
|
||||
"name": "plaid",
|
||||
"framework": "vue",
|
||||
"template": "single-view",
|
||||
"bundler": "vite",
|
||||
"cssPreProcessor": false,
|
||||
"theming": {
|
||||
"customColor": false,
|
||||
"color": "#007aff",
|
||||
"darkTheme": false,
|
||||
"iconFonts": true,
|
||||
"fillBars": true
|
||||
},
|
||||
"customBuild": false
|
||||
}
|
41
package.json
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"name": "plaid",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "plaid",
|
||||
"repository": "",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"start": "npm run dev",
|
||||
"dev": "cross-env NODE_ENV=development vite",
|
||||
"build": "cross-env NODE_ENV=production vite build",
|
||||
"postinstall": "cpy --flat ./node_modules/framework7-icons/fonts/*.* ./src/fonts/ && cpy --flat ./node_modules/material-icons/iconfont/*.* ./src/fonts/"
|
||||
},
|
||||
"browserslist": [
|
||||
"IOS >= 13",
|
||||
"Safari >= 13",
|
||||
"last 5 Chrome versions",
|
||||
"last 5 Firefox versions",
|
||||
"Samsung >= 12"
|
||||
],
|
||||
"dependencies": {
|
||||
"dom7": "^4.0.4",
|
||||
"framework7": "^7.1.2",
|
||||
"framework7-icons": "^5.0.5",
|
||||
"framework7-vue": "^7.1.2",
|
||||
"howler": "^2.2.3",
|
||||
"material-icons": "^1.13.1",
|
||||
"skeleton-elements": "^4.0.1",
|
||||
"swiper": "^8.4.6",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"vue": "^3.2.45"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vue/compiler-sfc": "^3.2.45",
|
||||
"cpy-cli": "^4.2.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"postcss-preset-env": "^7.8.3",
|
||||
"vite": "^4.0.4"
|
||||
}
|
||||
}
|
BIN
public/icons/128x128.png
Normal file
After Width: | Height: | Size: 7 KiB |
BIN
public/icons/144x144.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
public/icons/152x152.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
public/icons/192x192.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
public/icons/256x256.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
public/icons/512x512.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/icons/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
public/icons/favicon.png
Normal file
After Width: | Height: | Size: 7 KiB |
88
src/components/Button.vue
Normal file
|
@ -0,0 +1,88 @@
|
|||
<template >
|
||||
<div class='playStopButton' @click='togglePlay' :class='{ active: status === "play", loading }'>
|
||||
<!-- //- <svg version="1.1" xmlns="http://www.w3.org/2000/svg" fill='white' xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" xml:space="preserve">
|
||||
//- <circle id='circle' cx="50%" cy="50%" r="5%" fill/>
|
||||
//- </svg> -->
|
||||
<div id='stop'>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<g><g transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"><path d="M3598.3,1507.4l-46.2-48.3v-1354v-1356.1l48.3-44.1l48.3-46.2h1354h1356.1l44.1,48.3l46.2,48.3v1354v1356l-48.3,44.1l-48.3,46.2h-1354h-1356L3598.3,1507.4z"/></g></g>
|
||||
</svg>
|
||||
</div>
|
||||
<div id='play'>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<g><g transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"><path d="M3885.7,2036.4c-29.2-29.2-33.4-229.6-33.4-1888.8c0-1241.8,6.3-1872.1,20.9-1899.2c27.1-48,104.4-52.2,194.1-6.3C4286.4-1645.2,7143.6,14,7166.6,41.2c33.4,41.7,33.4,154.4-2.1,196.2c-20.9,27.1-2876,1686.3-3097.2,1799C3983.8,2078.1,3927.5,2078.1,3885.7,2036.4z"/></g></g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
status: 'stop'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
play () {
|
||||
this.status = 'play'
|
||||
},
|
||||
stop () {
|
||||
this.status = 'stop'
|
||||
},
|
||||
togglePlay () {
|
||||
this.status = this.status === 'play' ? 'stop' : 'play'
|
||||
this.$emit(this.status)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.playStopButton {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin: 5px 0px 5px 5px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.playStopButton:focus {
|
||||
outline:0;
|
||||
}
|
||||
|
||||
.playStopButton.active #play {
|
||||
transform: rotate( 90deg ) scale( 0 );
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.playStopButton:not( .active ) #stop {
|
||||
transform: rotate( -90deg ) scale( 0 );
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.playStopButton svg {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
#play, #stop {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: all .35s ease-in-out;
|
||||
position: absolute;
|
||||
stroke: rgba(248, 113, 113, var(--tw-text-opacity));
|
||||
fill:rgba(248, 113, 113, var(--tw-text-opacity));
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
#circle {
|
||||
fill: none;
|
||||
stroke: red;
|
||||
stroke-width: 3px;
|
||||
}
|
||||
</style>
|
66
src/components/Player.vue
Normal file
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<div class="bg-gray-800 rounded-sm">
|
||||
<div class="flex items-center space-x-3.5 sm:space-x-5 lg:space-x-3.5 xl:space-x-5">
|
||||
<Button class='text-red-400' ref='button' @play='play' @stop='stop' />
|
||||
<div class="min-w-0 flex-auto space-y-0.5">
|
||||
<!-- //- <p class="text-white text-sm sm:text-base lg:text-sm xl:text-base font-semibold uppercase">
|
||||
//- <abbr title="Episode">Ep.</abbr> 128
|
||||
//- </p> -->
|
||||
<h2 class="text-white text-base sm:text-xl lg:text-base xl:text-xl font-semibold truncate" v-text='title'>
|
||||
</h2>
|
||||
<!-- //- <p class="text-gray-400 text-base sm:text-lg lg:text-base xl:text-lg font-medium">
|
||||
//- Full Stack Radio
|
||||
//- </p> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Howl } from 'howler'
|
||||
import Button from './Button.vue'
|
||||
|
||||
export default {
|
||||
components: { Button },
|
||||
data () {
|
||||
return {
|
||||
loading: true,
|
||||
status: 'pause',
|
||||
volume: 100,
|
||||
title: 'RadioBlackout > DIRETTA',
|
||||
subtitle: '',
|
||||
live: true,
|
||||
player: null
|
||||
}
|
||||
},
|
||||
// destroyed () {
|
||||
// this.$nuxt.$off('play:podcast', this.stop)
|
||||
// },
|
||||
// mounted () {
|
||||
// this.$nuxt.$on('play:podcast', this.stop)
|
||||
// },
|
||||
methods: {
|
||||
play () {
|
||||
const rnd = Math.random()
|
||||
this.player = new Howl({
|
||||
autoSuspend: false,
|
||||
html5: true,
|
||||
preload: true,
|
||||
src: ['https://stream.radioblackout.org/blackout.ogg?rnd=' + rnd,
|
||||
'https://stream.radioblackout.org/blackout.mp3'],
|
||||
})
|
||||
this.player.play()
|
||||
this.$nuxt.$emit('play:player')
|
||||
},
|
||||
stop () {
|
||||
if (this.player) {
|
||||
this.player.stop()
|
||||
}
|
||||
this.$refs.button.stop()
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
40
src/components/app.vue
Normal file
|
@ -0,0 +1,40 @@
|
|||
<script setup>
|
||||
import Player from '../components/Player.vue'
|
||||
import routes from '../js/routes.js';
|
||||
import store from '../js/store';
|
||||
|
||||
// Framework7 Parameters
|
||||
const f7params = {
|
||||
name: 'plaid', // App name
|
||||
theme: 'ios', // Automatic theme detection
|
||||
view: {
|
||||
browserHistory: true,
|
||||
iosDynamicNavbar: true,
|
||||
xhrCache: false,
|
||||
masterDetailBreakpoint: 800,
|
||||
main: true,
|
||||
},
|
||||
|
||||
// passRouteParamsToRequest: true,
|
||||
// App store
|
||||
store,
|
||||
|
||||
// App routes
|
||||
routes,
|
||||
};
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<f7-app v-bind="f7params" >
|
||||
<!-- Top Navbar -->
|
||||
<f7-toolbar>
|
||||
<Player />
|
||||
</f7-toolbar>
|
||||
<f7-navbar back-link="Back" title='plaid' />
|
||||
|
||||
<!-- Your main view, should have "view-main" class -->
|
||||
<f7-view main url="/"></f7-view>
|
||||
|
||||
|
||||
</f7-app>
|
||||
</template>
|
53
src/css/app.css
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* Your app custom styles here */
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* Invert navigation bars to fill style */
|
||||
:root,
|
||||
:root.dark,
|
||||
:root .dark {
|
||||
--f7-bars-bg-color: var(--f7-theme-color);
|
||||
--f7-bars-bg-color-rgb: var(--f7-theme-color-rgb);
|
||||
--f7-bars-translucent-opacity: 0.9;
|
||||
--f7-bars-text-color: #fff;
|
||||
--f7-bars-link-color: #fff;
|
||||
--f7-navbar-subtitle-text-color: rgba(255,255,255,0.85);
|
||||
--f7-bars-border-color: transparent;
|
||||
--f7-tabbar-link-active-color: #fff;
|
||||
--f7-tabbar-link-inactive-color: rgba(255,255,255,0.54);
|
||||
--f7-sheet-border-color: transparent;
|
||||
--f7-tabbar-link-active-border-color: #fff;
|
||||
}
|
||||
.appbar,
|
||||
.navbar,
|
||||
.toolbar,
|
||||
.subnavbar,
|
||||
.calendar-header,
|
||||
.calendar-footer {
|
||||
--f7-touch-ripple-color: var(--f7-touch-ripple-white);
|
||||
--f7-link-highlight-color: var(--f7-link-highlight-white);
|
||||
--f7-link-touch-ripple-color: var(--f7-touch-ripple-white);
|
||||
--f7-button-text-color: #fff;
|
||||
--f7-button-pressed-bg-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
.navbar-large-transparent,
|
||||
.navbar-large.navbar-transparent {
|
||||
--f7-navbar-large-title-text-color: #000;
|
||||
|
||||
--r: 0;
|
||||
--g: 122;
|
||||
--b: 255;
|
||||
--progress: var(--f7-navbar-large-collapse-progress);
|
||||
--f7-bars-link-color: rgb(
|
||||
calc(var(--r) + (255 - var(--r)) * var(--progress)),
|
||||
calc(var(--g) + (255 - var(--g)) * var(--progress)),
|
||||
calc(var(--b) + (255 - var(--b)) * var(--progress))
|
||||
);
|
||||
}
|
||||
.dark .navbar-large-transparent,
|
||||
.dark .navbar-large.navbar-transparent {
|
||||
--f7-navbar-large-title-text-color: #fff;
|
||||
}
|
||||
|
||||
/* Your app custom styles here */
|
4
src/css/app.less
Normal file
|
@ -0,0 +1,4 @@
|
|||
/* Your app custom styles here */
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
56
src/css/icons.css
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* Material Icons Font (for MD theme) */
|
||||
@font-face {
|
||||
font-family: 'Material Icons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Material Icons'), local('MaterialIcons-Regular'),
|
||||
url(../fonts/material-icons.woff2) format('woff2'),
|
||||
url(../fonts/material-icons.woff) format('woff');
|
||||
}
|
||||
.material-icons {
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
word-wrap: normal;
|
||||
white-space: nowrap;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-feature-settings: 'liga';
|
||||
}
|
||||
|
||||
/* Framework7 Icons Font (for iOS theme) */
|
||||
@font-face {
|
||||
font-family: 'Framework7 Icons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('../fonts/Framework7Icons-Regular.woff2') format('woff2'),
|
||||
url('../fonts/Framework7Icons-Regular.woff') format('woff');
|
||||
}
|
||||
.f7-icons {
|
||||
font-family: 'Framework7 Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 28px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-feature-settings: 'liga';
|
||||
-moz-font-feature-settings: 'liga=1';
|
||||
-moz-font-feature-settings: 'liga';
|
||||
font-feature-settings: 'liga';
|
||||
text-align: center;
|
||||
}
|
BIN
src/fonts/Framework7Icons-Regular.ttf
Normal file
BIN
src/fonts/Framework7Icons-Regular.woff
Normal file
BIN
src/fonts/Framework7Icons-Regular.woff2
Normal file
55
src/fonts/_mixins.scss
Normal file
|
@ -0,0 +1,55 @@
|
|||
// @see https://github.com/twbs/bootstrap/blob/main/scss/_functions.scss
|
||||
@function material-icons-str-replace($string, $search, $replace: '') {
|
||||
$index: str-index($string, $search);
|
||||
@if $index {
|
||||
@return str-slice($string, 1, $index - 1) + $replace +
|
||||
material-icons-str-replace(
|
||||
str-slice($string, $index + str-length($search)),
|
||||
$search,
|
||||
$replace
|
||||
);
|
||||
}
|
||||
@return $string;
|
||||
}
|
||||
|
||||
@mixin material-icons-font-class($font-family) {
|
||||
font-family: $font-family;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: $material-icons-font-size;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased; // Support for all WebKit browsers
|
||||
-moz-osx-font-smoothing: grayscale; // Support for Firefox
|
||||
text-rendering: optimizeLegibility; // Support for Safari and Chrome
|
||||
font-feature-settings: 'liga'; // Support for IE
|
||||
}
|
||||
|
||||
@mixin material-icons-font($font-family) {
|
||||
$class-name: to-lower-case($font-family);
|
||||
$class-name: material-icons-str-replace($class-name, ' ', '-');
|
||||
$font-file: $material-icons-font-path + $class-name;
|
||||
|
||||
@font-face {
|
||||
font-family: $font-family;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: $material-icons-font-display;
|
||||
src: url('#{$font-file}.woff2') format('woff2'),
|
||||
url('#{$font-file}.woff') format('woff');
|
||||
}
|
||||
|
||||
.#{$class-name} {
|
||||
@include material-icons-font-class($font-family);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin material-icons() {
|
||||
@warn "material-icons() Sass mixin has been deprecated as of 1.0. Use '@extend .material-icons;' instead of '@include material-icons();'.";
|
||||
@include material-icons-font-class('Material Icons');
|
||||
}
|
3
src/fonts/_variables.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
$material-icons-font-path: './' !default;
|
||||
$material-icons-font-size: 24px !default;
|
||||
$material-icons-font-display: block !default;
|
24
src/fonts/filled.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
@font-face {
|
||||
font-family: "Material Icons";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons.woff2") format("woff2"), url("./material-icons.woff") format("woff");
|
||||
}
|
||||
.material-icons {
|
||||
font-family: "Material Icons";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
4
src/fonts/filled.scss
Normal file
|
@ -0,0 +1,4 @@
|
|||
@import 'variables';
|
||||
@import 'mixins';
|
||||
|
||||
@include material-icons-font('Material Icons');
|
BIN
src/fonts/material-icons-outlined.woff
Normal file
BIN
src/fonts/material-icons-outlined.woff2
Normal file
BIN
src/fonts/material-icons-round.woff
Normal file
BIN
src/fonts/material-icons-round.woff2
Normal file
BIN
src/fonts/material-icons-sharp.woff
Normal file
BIN
src/fonts/material-icons-sharp.woff2
Normal file
BIN
src/fonts/material-icons-two-tone.woff
Normal file
BIN
src/fonts/material-icons-two-tone.woff2
Normal file
124
src/fonts/material-icons.css
Normal file
|
@ -0,0 +1,124 @@
|
|||
@font-face {
|
||||
font-family: "Material Icons";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons.woff2") format("woff2"), url("./material-icons.woff") format("woff");
|
||||
}
|
||||
.material-icons {
|
||||
font-family: "Material Icons";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Material Icons Outlined";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons-outlined.woff2") format("woff2"), url("./material-icons-outlined.woff") format("woff");
|
||||
}
|
||||
.material-icons-outlined {
|
||||
font-family: "Material Icons Outlined";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Material Icons Round";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons-round.woff2") format("woff2"), url("./material-icons-round.woff") format("woff");
|
||||
}
|
||||
.material-icons-round {
|
||||
font-family: "Material Icons Round";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Material Icons Sharp";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons-sharp.woff2") format("woff2"), url("./material-icons-sharp.woff") format("woff");
|
||||
}
|
||||
.material-icons-sharp {
|
||||
font-family: "Material Icons Sharp";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Material Icons Two Tone";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons-two-tone.woff2") format("woff2"), url("./material-icons-two-tone.woff") format("woff");
|
||||
}
|
||||
.material-icons-two-tone {
|
||||
font-family: "Material Icons Two Tone";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
5
src/fonts/material-icons.scss
Normal file
|
@ -0,0 +1,5 @@
|
|||
@import 'filled';
|
||||
@import 'outlined';
|
||||
@import 'round';
|
||||
@import 'sharp';
|
||||
@import 'two-tone';
|
BIN
src/fonts/material-icons.woff
Normal file
BIN
src/fonts/material-icons.woff2
Normal file
24
src/fonts/outlined.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
@font-face {
|
||||
font-family: "Material Icons Outlined";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons-outlined.woff2") format("woff2"), url("./material-icons-outlined.woff") format("woff");
|
||||
}
|
||||
.material-icons-outlined {
|
||||
font-family: "Material Icons Outlined";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
4
src/fonts/outlined.scss
Normal file
|
@ -0,0 +1,4 @@
|
|||
@import 'variables';
|
||||
@import 'mixins';
|
||||
|
||||
@include material-icons-font('Material Icons Outlined');
|
24
src/fonts/round.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
@font-face {
|
||||
font-family: "Material Icons Round";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons-round.woff2") format("woff2"), url("./material-icons-round.woff") format("woff");
|
||||
}
|
||||
.material-icons-round {
|
||||
font-family: "Material Icons Round";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
4
src/fonts/round.scss
Normal file
|
@ -0,0 +1,4 @@
|
|||
@import 'variables';
|
||||
@import 'mixins';
|
||||
|
||||
@include material-icons-font('Material Icons Round');
|
24
src/fonts/sharp.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
@font-face {
|
||||
font-family: "Material Icons Sharp";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons-sharp.woff2") format("woff2"), url("./material-icons-sharp.woff") format("woff");
|
||||
}
|
||||
.material-icons-sharp {
|
||||
font-family: "Material Icons Sharp";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
4
src/fonts/sharp.scss
Normal file
|
@ -0,0 +1,4 @@
|
|||
@import 'variables';
|
||||
@import 'mixins';
|
||||
|
||||
@include material-icons-font('Material Icons Sharp');
|
24
src/fonts/two-tone.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
@font-face {
|
||||
font-family: "Material Icons Two Tone";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("./material-icons-two-tone.woff2") format("woff2"), url("./material-icons-two-tone.woff") format("woff");
|
||||
}
|
||||
.material-icons-two-tone {
|
||||
font-family: "Material Icons Two Tone";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: "liga";
|
||||
}
|
4
src/fonts/two-tone.scss
Normal file
|
@ -0,0 +1,4 @@
|
|||
@import 'variables';
|
||||
@import 'mixins';
|
||||
|
||||
@include material-icons-font('Material Icons Two Tone');
|
34
src/index.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
Customize this policy to fit your own app's needs. For more guidance, please refer to the docs:
|
||||
https://cordova.apache.org/docs/en/latest/
|
||||
Some notes:
|
||||
* https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
|
||||
* Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
|
||||
* Enable inline JS: add 'unsafe-inline' to default-src
|
||||
-->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src * 'self' 'unsafe-inline' 'unsafe-eval' data: content:">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover">
|
||||
|
||||
<meta name="theme-color" content="#007aff">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<title>plaid</title>
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<link rel="apple-touch-icon" href="icons/apple-touch-icon.png">
|
||||
<link rel="icon" href="icons/favicon.png">
|
||||
|
||||
|
||||
<!-- built styles file will be auto injected -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
<script type="module" src="./js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
30
src/js/app.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Import Vue
|
||||
import { createApp } from 'vue';
|
||||
|
||||
// Import Framework7
|
||||
import Framework7 from 'framework7/lite-bundle';
|
||||
|
||||
// Import Framework7-Vue Plugin
|
||||
import Framework7Vue, { registerComponents } from 'framework7-vue/bundle';
|
||||
|
||||
// Import Framework7 Styles
|
||||
import 'framework7/css/bundle';
|
||||
|
||||
// Import Icons and App Custom Styles
|
||||
import '../css/icons.css';
|
||||
import '../css/app.css';
|
||||
|
||||
// Import App Component
|
||||
import App from '../components/app.vue';
|
||||
|
||||
// Init Framework7-Vue Plugin
|
||||
Framework7.use(Framework7Vue);
|
||||
|
||||
// Init App
|
||||
const app = createApp(App);
|
||||
|
||||
// Register Framework7 Vue components
|
||||
registerComponents(app);
|
||||
|
||||
// Mount the app
|
||||
app.mount('#app');
|
32
src/js/radiomanifest.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
import radiomanifest from 'radiomanifest'
|
||||
|
||||
const cachedRadiomanifest = {}
|
||||
|
||||
|
||||
const RM = {
|
||||
|
||||
radio: {
|
||||
'ROR': { name: 'Radio Onda Rossa', description: 'un segnale che disturba', url: 'https://www.ondarossa.info' },
|
||||
'Spore': { name: 'Radio Spore', description: 'una voce senza padrone', url: 'https://radiospore.oziosi.org' },
|
||||
// 'RBO': { }
|
||||
},
|
||||
|
||||
currentRadio : null,
|
||||
|
||||
async get (id) {
|
||||
// check if this radio id exists
|
||||
if (!RM.radio[id]) {
|
||||
throw new Error('This radio id does not exists!')
|
||||
}
|
||||
|
||||
// check if is cached, load it otherwise
|
||||
if (!cachedRadiomanifest[id]) {
|
||||
const radio = RM.radio[id]
|
||||
cachedRadiomanifest[id] = await radiomanifest.get(radio.url)
|
||||
}
|
||||
this.currentRadio = cachedRadiomanifest[id]
|
||||
return cachedRadiomanifest[id]
|
||||
}
|
||||
}
|
||||
|
||||
export default RM
|
27
src/js/routes.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
import HomePage from '../pages/home.vue'
|
||||
import RadioPage from '../pages/Radio.vue'
|
||||
import ShowPage from '../pages/Show.vue'
|
||||
import NotFoundPage from '../pages/404.vue'
|
||||
|
||||
var routes = [
|
||||
{
|
||||
path: '/',
|
||||
master: true,
|
||||
component: HomePage,
|
||||
detailRoutes: [{
|
||||
path: '/radio/:radioName',
|
||||
component: RadioPage,
|
||||
},
|
||||
{
|
||||
path: '/radio/:radioName/:showName',
|
||||
component: ShowPage
|
||||
}],
|
||||
},
|
||||
{
|
||||
path: '(.*)',
|
||||
component: NotFoundPage,
|
||||
},
|
||||
]
|
||||
|
||||
export default routes
|
14
src/js/store.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
import { createStore } from 'framework7/lite'
|
||||
|
||||
const store = createStore({
|
||||
state: {
|
||||
radios: [
|
||||
{ id: 1, name: 'Radio Onda Rossa', description: 'un segnale che disturba', url: 'https://www.ondarossa.info' },
|
||||
{ id: 2, name: 'Radio Spore', description: 'una voce senza padrone', url: 'https://radiospore.oziosi.org' },
|
||||
],
|
||||
},
|
||||
actions: {
|
||||
},
|
||||
})
|
||||
export default store;
|
12
src/pages/404.vue
Normal file
|
@ -0,0 +1,12 @@
|
|||
<template>
|
||||
<f7-page>
|
||||
<f7-navbar title="Not found" back-link="Back"></f7-navbar>
|
||||
<f7-block strong>
|
||||
<p>Sorry</p>
|
||||
<p>Requested content not found.</p>
|
||||
</f7-block>
|
||||
</f7-page>
|
||||
</template>
|
||||
<script>
|
||||
export default {};
|
||||
</script>
|
46
src/pages/Radio.vue
Normal file
|
@ -0,0 +1,46 @@
|
|||
<template>
|
||||
<f7-page name="radio">
|
||||
<img :src='Radio.logo' id='logo'/>
|
||||
<f7-block-title>{{Radio.name}}</f7-block-title>
|
||||
<f7-block-header>{{Radio.description}}</f7-block-header>
|
||||
|
||||
<f7-preloader v-if='loading' />
|
||||
<f7-list v-else>
|
||||
<f7-list-item v-for='show in Radio.shows' :key='show.name' :title='show.name' :link='`/radio/show/${show.name}`' :footer='show.description'/>
|
||||
</f7-list>
|
||||
</f7-page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import radiomanifest from '../js/radiomanifest'
|
||||
|
||||
export default {
|
||||
name: 'radio',
|
||||
data () {
|
||||
return {
|
||||
loading: true,
|
||||
radioId: null,
|
||||
radio: { name: '' },
|
||||
Radio: { }
|
||||
}
|
||||
},
|
||||
props: { f7route: Object, f7router: Object },
|
||||
async mounted () {
|
||||
try {
|
||||
this.Radio = await radiomanifest.get(this.f7route.params.radioName)
|
||||
// this.Radio.schedule.getNowShow(new Date())
|
||||
console.error(this.Radio)
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
console.error('le cose non vanno mai sempre bene!', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
#logo {
|
||||
margin-left: 10px;
|
||||
max-width: 40px;
|
||||
}
|
||||
</style>
|
19
src/pages/Show.vue
Normal file
|
@ -0,0 +1,19 @@
|
|||
<script setup>
|
||||
import radiomanifest from '../js/radiomanifest'
|
||||
const { f7Route } = defineProps({ f7Route: Object })
|
||||
|
||||
const Radio = radiomanifest.currentRadio
|
||||
|
||||
// ma non c'e' Radio.schedule.getShowPodcast ?
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<f7-page name="show">
|
||||
|
||||
<f7-block-title>{{Radio.name}}</f7-block-title>
|
||||
<f7-block-header>{{Radio.description}}</f7-block-header>
|
||||
|
||||
|
||||
</f7-page>
|
||||
</template>
|
16
src/pages/home.vue
Normal file
|
@ -0,0 +1,16 @@
|
|||
<script setup>
|
||||
import radiomanifest from '../js/radiomanifest'
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<f7-page name="home">
|
||||
|
||||
<!-- Page content-->
|
||||
<f7-block-title>Radio</f7-block-title>
|
||||
<f7-list>
|
||||
<f7-list-item v-for='(radio, id) in radiomanifest.radio' :key='id' :link="`/radio/${id}`" :title="radio.name" />
|
||||
</f7-list>
|
||||
|
||||
|
||||
</f7-page>
|
||||
</template>
|
6
tailwind.config.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
purge: {
|
||||
content: ['./src/index.html', './src/**/*.{vue,svelte,js,ts}'],
|
||||
},
|
||||
plugins: [],
|
||||
}
|
34
vite.config.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
import path from 'path';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
|
||||
const SRC_DIR = path.resolve(__dirname, './src');
|
||||
const PUBLIC_DIR = path.resolve(__dirname, './public');
|
||||
const BUILD_DIR = path.resolve(__dirname, './www',);
|
||||
|
||||
export default {
|
||||
plugins: [
|
||||
vue(),
|
||||
|
||||
],
|
||||
root: SRC_DIR,
|
||||
base: '',
|
||||
publicDir: PUBLIC_DIR,
|
||||
build: {
|
||||
outDir: BUILD_DIR,
|
||||
assetsInlineLimit: 0,
|
||||
emptyOutDir: true,
|
||||
rollupOptions: {
|
||||
treeshake: false,
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': SRC_DIR,
|
||||
},
|
||||
},
|
||||
server: {
|
||||
host: true,
|
||||
},
|
||||
|
||||
};
|