1
0
Fork 0
forked from lesion/plaid
This commit is contained in:
lesion 2023-01-23 12:29:24 +01:00
commit 0ca9098e19
57 changed files with 1006 additions and 0 deletions

42
.gitignore vendored Normal file
View 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/

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
assets-src/web-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

19
framework7.json Normal file
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

BIN
public/icons/144x144.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
public/icons/152x152.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
public/icons/192x192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
public/icons/256x256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/icons/512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
public/icons/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

88
src/components/Button.vue Normal file
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,4 @@
/* Your app custom styles here */
@tailwind base;
@tailwind components;
@tailwind utilities;

56
src/css/icons.css Normal file
View 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;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

55
src/fonts/_mixins.scss Normal file
View 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');
}

View 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
View 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
View file

@ -0,0 +1,4 @@
@import 'variables';
@import 'mixins';
@include material-icons-font('Material Icons');

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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";
}

View file

@ -0,0 +1,5 @@
@import 'filled';
@import 'outlined';
@import 'round';
@import 'sharp';
@import 'two-tone';

Binary file not shown.

Binary file not shown.

24
src/fonts/outlined.css Normal file
View 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
View file

@ -0,0 +1,4 @@
@import 'variables';
@import 'mixins';
@include material-icons-font('Material Icons Outlined');

24
src/fonts/round.css Normal file
View 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
View file

@ -0,0 +1,4 @@
@import 'variables';
@import 'mixins';
@include material-icons-font('Material Icons Round');

24
src/fonts/sharp.css Normal file
View 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
View file

@ -0,0 +1,4 @@
@import 'variables';
@import 'mixins';
@include material-icons-font('Material Icons Sharp');

24
src/fonts/two-tone.css Normal file
View 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
View file

@ -0,0 +1,4 @@
@import 'variables';
@import 'mixins';
@include material-icons-font('Material Icons Two Tone');

34
src/index.html Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,6 @@
module.exports = {
purge: {
content: ['./src/index.html', './src/**/*.{vue,svelte,js,ts}'],
},
plugins: [],
}

34
vite.config.js Normal file
View 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,
},
};