diff --git a/README.md b/README.md
index 65f5fc8..84edd62 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,40 @@
-# team-1
+# ChillBox
-Test
+> *A project by Pausetta.org, Simone Tesini, Francesco De Carlo, Leonardo Segala, Matteo Peretto*
+
+**ChillBox** is a web app that lets you create a shared radio station with a democratic voting system, so everyone gets to enjoy their favorite music together.
+Perfect for venues like swimming pools, cafΓ©s, or even lively parties.
+
+---
+
+## π΅ Voting System
+
+Joining a ChillBox room is easy: users can either scan the QR code displayed on the host screen or use GPS to find nearby rooms.
+Hosts can set a location range, ensuring only people physically present can add or vote for songs.
+
+---
+
+## π Ranking Algorithm
+
+ChillBox uses a smart ranking algorithm to decide what plays next. The score of each song is based on:
+
+* Votes from users
+* How recently similar songs (same genre or artist) have been played (less = better)
+* A bit of randomness to keep things interesting
+* A strong penalty for songs played too recently
+
+---
+
+## π Hands-Off Experience
+
+ChillBox is designed to be almost entirely hands-free.
+Once the host sets up a room and optionally connects a screen or projector
+(to show the current track, QR code, etc.), ChillBox takes care of the rest.
+
+ChillBox comes with built-in automatic moderation to keep the music fair and on-theme.
+
+* Users canβt vote for the same song multiple times.
+* A cooldown prevents users from spamming song requests.
+* Hosts can define preferred genres and overall mood, so no one can hijack your chill beach vibes with unexpected death metal.
+
+That said, hosts still have access to essential controls, like pause and skip, if needed.
diff --git a/SPEECH.md b/SPEECH.md
new file mode 100644
index 0000000..2ab507f
--- /dev/null
+++ b/SPEECH.md
@@ -0,0 +1,15 @@
+# speech
+
+## Home screen
+We start here in the home page.
+We can see this little radar animation, which means that the app is looking for nearby ChillBox rooms to join.
+It uses GPS for this feature.
+
+## Join room
+When we join a room, the server checks our location and checks if it's within a specified range.
+That way, you must physically be in the location to actually be able to add new songs
+
+## Talk about the host
+As you can see here (and hear) on the left, the host is already playing some music.
+Now i will add a song on the client side and it will pop up in the list.
+
diff --git a/backend/Dockerfile b/backend/Dockerfile
index c6a1412..3390030 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -12,5 +12,6 @@ RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
-CMD ["flask", "--app", "src.app", "run", "--debug", "--host=0.0.0.0"]
+# CMD ["flask", "--app", "src.app", "run", "--debug", "--host=0.0.0.0"]
+CMD ["python3", "src/app.py"]
# flask --app src.app run --host=0.0.0.0 --port=5001 --debug
diff --git a/backend/requirements.txt b/backend/requirements.txt
index 5eae02e..cb18a70 100644
--- a/backend/requirements.txt
+++ b/backend/requirements.txt
@@ -4,4 +4,5 @@ flask-socketio
dotenv
requests
qrcode
-Pillow
\ No newline at end of file
+Pillow
+eventlet>=0.33
diff --git a/backend/src/app.py b/backend/src/app.py
index c11cf37..28c66e9 100644
--- a/backend/src/app.py
+++ b/backend/src/app.py
@@ -1,17 +1,17 @@
import uuid
from dataclasses import asdict
+
import dotenv
+from connect import get_connection
from flask import Flask, Response, jsonify, request
from flask_cors import CORS
from flask_socketio import SocketIO, join_room, leave_room
-
-from .state import State
-from .connect import get_connection
-from .room import Room
-from .song import Song, init_db, get_song_by_title_artist, add_song_in_db, get_song_by_uuid
-from .song_fetch import query_search, yt_get_audio_url, yt_search_song
-from .qrcode_gen import generate_qr
-
+from gps import Coordinates, distance_between_coords
+from qrcode_gen import generate_qr
+from room import Room
+from song import Song, add_song_in_db, get_song_by_title_artist, get_song_by_uuid, init_db
+from song_fetch import query_search, yt_get_audio_url, yt_search_song
+from state import State
dotenv.load_dotenv()
@@ -28,11 +28,11 @@ init_db(state.db)
state.rooms[1000] = Room(
id=1000,
- coord=(1.0, 5.5),
- name="Test Room",
- pin=None,
- tags=set(),
- range_size=100,
+ coord=Coordinates(46.6769043, 11.1851585),
+ name="Lido Scena",
+ pin=1234,
+ tags=set(["chill", "raggaetton", "spanish", "latino", "mexican", "rock"]),
+ range_size=150,
songs={},
history=[],
playing=[],
@@ -73,7 +73,7 @@ def on_leave(data):
@app.get("/api/join")
def join():
room_id = request.args.get("room")
- code = request.args.get("code")
+ code = request.args.get("pin")
if room_id is None:
return error("Missing room id")
@@ -81,8 +81,22 @@ def join():
if (room := state.rooms.get(int(room_id))) is None:
return error("Invalid room")
- if room.pin is not None and room.pin != code:
- return error("Invalid code")
+ if room.pin is not None:
+ if code is None:
+ return error("Missing code")
+ if int(room.pin) != int(code):
+ return error("Invalid code")
+
+ distance = distance_between_coords(
+ lhs=room.coord,
+ rhs=Coordinates(
+ latitude=float(request.args["lat"]),
+ longitude=float(request.args["lon"]),
+ ),
+ )
+
+ if distance > room.range_size:
+ return error("You are not within the room range")
return {"success": True, "ws": f"/ws/{room_id}"}
@@ -140,8 +154,8 @@ def room_new():
lat, lon = room_cords.split(",")
room = Room(
- id=max(state.rooms or [0]) + 1, #
- coord=(float(lat), float(lon)),
+ id=max(state.rooms or [0]) + 1,
+ coord=Coordinates(float(lat), float(lon)),
range_size=int(room_range),
name=room_name,
pin=room_pin,
@@ -159,6 +173,14 @@ def room_new():
@app.get("/api/room")
def room():
+ lat = request.args.get("lat")
+ lon = request.args.get("lon")
+
+ if lat and lon:
+ user_coords = Coordinates(latitude=float(lat), longitude=float(lon))
+ else:
+ return error("Missing user coordinates")
+
return [
{
"id": room.id,
@@ -166,8 +188,10 @@ def room():
"private": room.pin is not None,
"coords": room.coord,
"range": room.range_size,
+ "distance": d,
}
for room in state.rooms.values()
+ if (d := distance_between_coords(user_coords, room.coord)) <= room.range_size
]
@@ -189,6 +213,9 @@ def add_song():
## song not found, downolad from YT
yt_video_id = yt_search_song(info.title, info.artist)
+ if yt_video_id is None:
+ return error("No video found on youtube")
+
## add in DB
song = Song(
uuid=str(uuid.uuid4()),
@@ -201,6 +228,15 @@ def add_song():
add_song_in_db(song)
+ if len(room.tags) > 0:
+ tag_ok = False
+ for tag in song.tags:
+ if tag in room.tags:
+ tag_ok = True
+
+ if not tag_ok:
+ return error("Song genre does not belong to this room")
+
## add the song in the room if does not exists
if song.uuid not in room.songs:
room.songs[song.uuid] = (song, 1) # start with one vote
@@ -273,4 +309,4 @@ def get_audio_url():
if __name__ == "__main__":
- socketio.run(app, debug=True)
+ socketio.run(app, host="0.0.0.0", port=5000, debug=True)
diff --git a/backend/src/gps.py b/backend/src/gps.py
index 546531b..98bda0c 100644
--- a/backend/src/gps.py
+++ b/backend/src/gps.py
@@ -1,9 +1,11 @@
import math
+from dataclasses import dataclass
+@dataclass
class Coordinates:
- latitude: int
- longitude: int
+ latitude: float
+ longitude: float
def distance_between_coords(lhs: Coordinates, rhs: Coordinates) -> float:
diff --git a/backend/src/room.py b/backend/src/room.py
index 5109884..cb775b6 100644
--- a/backend/src/room.py
+++ b/backend/src/room.py
@@ -1,7 +1,8 @@
import random
from dataclasses import dataclass
-from .song import Song
+from gps import Coordinates
+from song import Song
USER_SCORE_WEIGHT = 0.7
ARTIST_WEIGHT = 0.1
@@ -30,7 +31,7 @@ class Rank:
@dataclass
class Room:
id: int
- coord: tuple[float, float]
+ coord: Coordinates
name: str
pin: int | None
tags: set[str]
diff --git a/backend/src/song.py b/backend/src/song.py
index 7409d06..f95609b 100644
--- a/backend/src/song.py
+++ b/backend/src/song.py
@@ -1,7 +1,7 @@
from dataclasses import dataclass
from sqlite3 import Cursor
-from .connect import get_connection
+from connect import get_connection
def init_db(db: Cursor):
diff --git a/backend/src/song_fetch.py b/backend/src/song_fetch.py
index 665e2c9..905d126 100644
--- a/backend/src/song_fetch.py
+++ b/backend/src/song_fetch.py
@@ -1,10 +1,11 @@
-import requests
-import urllib.parse
-import os.path
import os
+import os.path
import sys
+import urllib.parse
from dataclasses import dataclass
+import requests
+
sys.path.append("/yt-dlp")
import yt_dlp
@@ -17,7 +18,7 @@ class SongInfo:
tags: list[str]
-def _lastfm_search(query: str) -> tuple[str, str]:
+def _lastfm_search(query: str) -> tuple[str, str] | None:
response = requests.get(
url="https://ws.audioscrobbler.com/2.0/?method=track.search&format=json",
params={"limit": 5, "track": query, "api_key": os.environ["LASTFM_API_KEY"]},
@@ -25,7 +26,10 @@ def _lastfm_search(query: str) -> tuple[str, str]:
assert response.status_code == 200
- track_info = response.json()["results"]["trackmatches"]["track"][0]
+ tracks = response.json()["results"]["trackmatches"]["track"]
+ if len(tracks) == 0:
+ return None
+ track_info = tracks[0]
return track_info["name"], track_info["artist"]
@@ -42,11 +46,16 @@ def _lastfm_getinfo(name: str, artist: str) -> tuple[str, list[str]]: # ( image
track_info = response.json()["track"]
- image_url = urllib.parse.urlparse(track_info["album"]["image"][0]["#text"])
+ image_id = ""
+ if "album" in track_info:
+ image_url = urllib.parse.urlparse(track_info["album"]["image"][0]["#text"])
+ image_id = os.path.splitext(os.path.basename(image_url.path))[0]
+ else:
+ print("this song haas no image", flush=True)
return (
# track_info["mbid"],
- os.path.splitext(os.path.basename(image_url.path))[0],
+ image_id,
[t["name"] for t in track_info["toptags"]["tag"]],
)
@@ -68,14 +77,17 @@ def _yt_search(query: str) -> tuple[str, str]:
def query_search(query: str) -> SongInfo | None:
- name, artist = _lastfm_search(query)
+ res = _lastfm_search(query)
+ if res is None:
+ return None
+ name, artist = res
img_id, tags = _lastfm_getinfo(name, artist)
return SongInfo(artist=artist, title=name, img_id=img_id, tags=tags)
-def yt_search_song(name: str, artist: str) -> str: # video id
+def yt_search_song(name: str, artist: str) -> str | None: # video id
ydl_opts = {
"format": "bestaudio",
"default_search": "ytsearch1",
@@ -86,6 +98,9 @@ def yt_search_song(name: str, artist: str) -> str: # video id
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(f"{name!r} - {artist!r}", download=False)
+ if len(info["entries"]) == 0:
+ return None
+
return info["entries"][0]["id"]
diff --git a/backend/src/state.py b/backend/src/state.py
index e1f3e7c..73d05d2 100644
--- a/backend/src/state.py
+++ b/backend/src/state.py
@@ -4,7 +4,7 @@ from sqlite3 import Cursor
from flask import Flask
from flask_socketio import SocketIO
-from .room import Room
+from room import Room
@dataclass
diff --git a/frontend/src/app.html b/frontend/src/app.html
index 7af2f6d..0e6ef01 100644
--- a/frontend/src/app.html
+++ b/frontend/src/app.html
@@ -1,15 +1,13 @@
-
-
-
-
-
- %sveltekit.head%
-
-
-
- %sveltekit.body%
-
-
+
+
+
+
+
+ %sveltekit.head%
+
+
+ %sveltekit.body%
+
diff --git a/frontend/src/lib/components/QueueSlider.svelte b/frontend/src/lib/components/QueueSlider.svelte
index ec5a647..5df1e8d 100644
--- a/frontend/src/lib/components/QueueSlider.svelte
+++ b/frontend/src/lib/components/QueueSlider.svelte
@@ -8,6 +8,10 @@
queueSongs[playingIndex],
playingIndex == queueSongs.length - 1 ? createEmptySong() : queueSongs[playingIndex + 1],
])
+
+ $effect(() => {
+ console.log(displaySongs)
+ })
@@ -19,20 +23,22 @@
class={`flex h-[60vw] max-h-[250px] w-[60vw] max-w-[250px] items-center justify-center ${i === 1 ? "spin-slower rounded-full border-2 border-black" : "rounded"} object-cover`}
>
{#if i === 1}
-
+
{/if}
-

+
{#if i === 1}
- {song.title} - {song.artist}
+ {song.title} - {song.artist}
{/if}
{:else}
-
- {#if i === 1}
-
No song in queue
- {/if}
-
+
{/if}
{/each}
diff --git a/frontend/src/lib/components/RoomComponent.svelte b/frontend/src/lib/components/RoomComponent.svelte
index e98e000..0192683 100644
--- a/frontend/src/lib/components/RoomComponent.svelte
+++ b/frontend/src/lib/components/RoomComponent.svelte
@@ -1,18 +1,45 @@
-
+
+ {#if showPinModal}
+
+
+ {/if}
+
diff --git a/frontend/src/lib/components/SuggestionInput.svelte b/frontend/src/lib/components/SuggestionInput.svelte
index 09982fd..d19dd17 100644
--- a/frontend/src/lib/components/SuggestionInput.svelte
+++ b/frontend/src/lib/components/SuggestionInput.svelte
@@ -1,19 +1,69 @@
-
-
+
+ {
+ errorMsg = null
+ if (e.key == "Enter") {
+ sendSong()
+ }
+ }}
+ disabled={loading}
+ />
+ {#if loading}
+
+
+
+ {/if}
+
+
+
+ {errorMsg}
+
diff --git a/frontend/src/lib/components/SuggestionList.svelte b/frontend/src/lib/components/SuggestionList.svelte
index 285d242..6c667a3 100644
--- a/frontend/src/lib/components/SuggestionList.svelte
+++ b/frontend/src/lib/components/SuggestionList.svelte
@@ -1,41 +1,62 @@
{#if suggestions.length == 0}
-
No suggestions yet! Try to add a new one using the Add button
+
No suggestions yet! Try to add a new one using the Add button
{/if}
- {#each suggestions as sug, idx}
-
-
-

-
-
{sug.title}
+ {#each suggestions as sug}
+
+
+

+
+
{sug.title}
{sug.artist}
{
+ await vote(1, sug.uuid)
+ }}>
-
{sug.upvote}
+
{sug.upvote}
{
+ await vote(-1, sug.uuid)
+ }}>
diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts
index 0c2e8f5..87182fc 100644
--- a/frontend/src/lib/types.ts
+++ b/frontend/src/lib/types.ts
@@ -10,19 +10,19 @@ const SongSchema = z.object({
})
export type Song = z.infer
-export const parseSong = async function(song: any): Promise {
+export const parseSong = async function (song: any): Promise {
let resp = await SongSchema.parseAsync(song)
return resp
}
-export const createEmptySong = function(): Song {
+export const createEmptySong = function (): Song {
return {
uuid: "-1",
title: "",
artist: "",
tags: [""],
image_id: "",
- youtube_id: 0,
+ youtube_id: "",
}
}
@@ -31,21 +31,22 @@ const SuggestionSchema = SongSchema.extend({
})
export type Suggestion = z.infer
-export const parseSuggestion = async function(sugg: any): Promise {
+export const parseSuggestion = async function (sugg: any): Promise {
let resp = await SuggestionSchema.parseAsync(sugg)
return resp
}
const RoomSchema = z.object({
- id: z.string(),
+ id: z.number(),
name: z.string(),
private: z.boolean(),
- coords: z.tuple([z.number(), z.number()]),
- range: z.number().int()
+ coords: z.object({ latitude: z.number(), longitude: z.number() }),
+ range: z.number().int(),
+ distance: z.number()
})
export type Room = z.infer
-export const parseRoom = async function(room: any): Promise {
+export const parseRoom = async function (room: any): Promise {
let resp = await RoomSchema.parseAsync(room)
return resp
}
diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts
index 1b806c5..470da85 100644
--- a/frontend/src/lib/utils.ts
+++ b/frontend/src/lib/utils.ts
@@ -1,9 +1,10 @@
+import { type Coordinates } from "./gps"
import { parseSong, parseSuggestion, type FetchError, type Song, type Suggestion } from "./types"
-export const joinRoom = async function (roomId: string): Promise<[FetchError | null, string]> {
- let resp = await fetch("/api/join?room=" + roomId)
+export const joinRoom = async function (roomId: string, coords: Coordinates, pin: string): Promise<[FetchError | null, string]> {
+ let res = await fetch(`/api/join?room=${roomId}&lat=${coords.latitude}&lon=${coords.longitude}&pin=${pin}`)
- if (resp.status != 200) {
+ if (res.status != 200) {
return [{ code: 400, message: "Cannot join the room" }, ""]
}
diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte
index e4c699e..0ab9b2b 100644
--- a/frontend/src/routes/+layout.svelte
+++ b/frontend/src/routes/+layout.svelte
@@ -4,6 +4,6 @@
let { children } = $props()
-
+
{@render children()}
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
index 319ce8d..b0b35bf 100644
--- a/frontend/src/routes/+page.svelte
+++ b/frontend/src/routes/+page.svelte
@@ -1,9 +1,20 @@
@@ -12,46 +23,22 @@
ChillBox
-

+
Scanning for rooms near you...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/frontend/src/routes/admin/[id]/+page.svelte b/frontend/src/routes/admin/[id]/+page.svelte
index e017cc5..02f5f08 100644
--- a/frontend/src/routes/admin/[id]/+page.svelte
+++ b/frontend/src/routes/admin/[id]/+page.svelte
@@ -15,14 +15,37 @@
let currentPlaying = $derived(queueSongs[playingIndex])
let audioController = $state()
+ let playerInfo = $state({
+ playing: false,
+ currentTime: 0,
+ duration: 0,
+ })
+
async function playOnEnd() {
let url = await getStreamingUrl(currentPlaying.uuid)
if (audioController) {
audioController.src = url
- audioController.play()
+ await audioController.play()
}
}
+ $effect(() => {
+ if (audioController) {
+ audioController.ontimeupdate = () => {
+ playerInfo.currentTime = audioController?.currentTime || 0
+ }
+ audioController.onloadedmetadata = () => {
+ playerInfo.duration = audioController?.duration || 0
+ }
+ audioController.onplay = () => {
+ playerInfo.playing = true
+ }
+ audioController.onpause = () => {
+ playerInfo.playing = false
+ }
+ }
+ })
+
onMount(async () => {
let songs, index
;[returnError, songs, index] = await getQueueSongs(data.roomId)
@@ -30,12 +53,21 @@
queueSongs = songs
playingIndex = index
- if (audioController) {
- audioController.src = await getStreamingUrl(currentPlaying.uuid)
- audioController.play()
+ if (queueSongs.length == 0) {
+ playNext()
}
})
+ $effect(() => {
+ playOnEnd()
+ })
+
+ const formatTime = (t: number) => {
+ const min = Math.floor(t / 60)
+ const sec = Math.floor(t % 60)
+ return `${min}:${sec.toString().padStart(2, "0")}`
+ }
+
async function playNext() {
let songs, index
;[returnError, songs, index] = await triggerPlayNext(data.roomId)
@@ -44,6 +76,20 @@
queueSongs = songs
playingIndex = index
+
+ if (audioController) {
+ audioController.pause()
+ audioController.currentTime = 0
+ }
+ }
+
+ function seek(e: Event) {
+ const target = e.target as HTMLInputElement
+ const seekTime = parseFloat(target.value)
+ playerInfo.currentTime = seekTime
+ if (audioController) {
+ audioController.currentTime = seekTime
+ }
}
@@ -52,7 +98,21 @@
{:else}
-
Next
-
+
+
+
+
+
{formatTime(playerInfo.currentTime)} - {formatTime(playerInfo.duration)}
+
+
+ (playerInfo.playing ? audioController?.pause() : audioController?.play())}>{playerInfo.playing ? "Pause" : "Unpause"}
+ Next
+
+
+

+
{/if}
diff --git a/frontend/src/routes/room/[id]/+page.svelte b/frontend/src/routes/room/[id]/+page.svelte
index e53cb58..84d8d67 100644
--- a/frontend/src/routes/room/[id]/+page.svelte
+++ b/frontend/src/routes/room/[id]/+page.svelte
@@ -8,6 +8,7 @@
import { getQueueSongs, getSuggestions, joinRoom } from "$lib/utils.js"
import type { FetchError } from "$lib/types.js"
import { io, Socket } from "socket.io-client"
+ import { get_coords } from "$lib/gps.js"
let { data } = $props()
@@ -23,8 +24,14 @@
onMount(async () => {
// Join the room
+ let { coords, error } = await get_coords()
+ if (error || coords == null) {
+ // Default to Lido
+ coords = { latitude: 46.6769043, longitude: 11.1851585 }
+ }
+
let sugg, queue, index
- ;[returnError] = await joinRoom(data.roomId)
+ ;[returnError] = await joinRoom(data.roomId, coords, data.pin)
if (returnError) {
return
}
@@ -69,7 +76,7 @@
{#if returnError}
{:else}
-
+
diff --git a/frontend/src/routes/room/[id]/+page.ts b/frontend/src/routes/room/[id]/+page.ts
index 969ffc5..f3bea98 100644
--- a/frontend/src/routes/room/[id]/+page.ts
+++ b/frontend/src/routes/room/[id]/+page.ts
@@ -1,13 +1,8 @@
-import { error, type Load, type ServerLoad } from "@sveltejs/kit"
import type { PageLoad } from "./$types"
-import type { FetchError } from "$lib/util"
-import { parseSuggestion, type Suggestion } from "$lib/types"
-export const load: PageLoad = async ({ params }) => {
- if (params.id) {
- return {
- roomId: params.id,
- }
+export const load: PageLoad = ({ params, url }) => {
+ return {
+ roomId: params.id || "",
+ pin: url.searchParams.get("pin") || "",
}
- error(400, "Please provide a room id")
}
diff --git a/frontend/src/routes/room/create/+page.svelte b/frontend/src/routes/room/create/+page.svelte
new file mode 100644
index 0000000..d0009f3
--- /dev/null
+++ b/frontend/src/routes/room/create/+page.svelte
@@ -0,0 +1,83 @@
+
+
+
diff --git a/frontend/static/android-chrome-192x192.png b/frontend/static/android-chrome-192x192.png
new file mode 100644
index 0000000..ddc7955
Binary files /dev/null and b/frontend/static/android-chrome-192x192.png differ
diff --git a/frontend/static/android-chrome-512x512.png b/frontend/static/android-chrome-512x512.png
new file mode 100644
index 0000000..71ec4aa
Binary files /dev/null and b/frontend/static/android-chrome-512x512.png differ
diff --git a/frontend/static/apple-touch-icon.png b/frontend/static/apple-touch-icon.png
new file mode 100644
index 0000000..a60445a
Binary files /dev/null and b/frontend/static/apple-touch-icon.png differ
diff --git a/frontend/static/favicon-16x16.png b/frontend/static/favicon-16x16.png
new file mode 100644
index 0000000..6bb39f3
Binary files /dev/null and b/frontend/static/favicon-16x16.png differ
diff --git a/frontend/static/favicon-32x32.png b/frontend/static/favicon-32x32.png
new file mode 100644
index 0000000..7d938c2
Binary files /dev/null and b/frontend/static/favicon-32x32.png differ
diff --git a/frontend/static/favicon.ico b/frontend/static/favicon.ico
new file mode 100644
index 0000000..f5208bb
Binary files /dev/null and b/frontend/static/favicon.ico differ
diff --git a/frontend/static/favicon.svg b/frontend/static/favicon.svg
deleted file mode 100644
index cc5dc66..0000000
--- a/frontend/static/favicon.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/frontend/static/manifest.json b/frontend/static/manifest.json
index f042a95..8a414d3 100644
--- a/frontend/static/manifest.json
+++ b/frontend/static/manifest.json
@@ -1,21 +1,21 @@
{
- "name": "Chillbox Music Player",
- "short_name": "Chillbox",
- "start_url": "/",
- "display": "standalone",
- "background_color": "#334155",
- "theme_color": "#334155",
- "orientation": "portrait-primary",
- "icons": [
- {
- "src": "/icon-512.png",
- "sizes": "512x512",
- "type": "image/png"
- },
- {
- "src": "/icon-192.png",
- "sizes": "192x192",
- "type": "image/png"
- }
- ]
+ "name": "Chillbox Music Player",
+ "short_name": "Chillbox",
+ "start_url": "/",
+ "display": "standalone",
+ "background_color": "#334155",
+ "theme_color": "#334155",
+ "orientation": "portrait-primary",
+ "icons": [
+ {
+ "src": "/android-chrome-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ },
+ {
+ "src": "/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ]
}
diff --git a/frontend/static/smerdoradar.gif b/frontend/static/radar.gif
similarity index 100%
rename from frontend/static/smerdoradar.gif
rename to frontend/static/radar.gif
diff --git a/frontend/static/smerdo_radar_bonus.gif b/frontend/static/radar_bonus.gif
similarity index 100%
rename from frontend/static/smerdo_radar_bonus.gif
rename to frontend/static/radar_bonus.gif