Style Fixes on Small Screens

This commit is contained in:
shabinder 2021-03-13 16:07:27 +05:30
parent a47d9f52a0
commit 90b99cbb51
18 changed files with 462 additions and 82 deletions

View File

@ -7,7 +7,6 @@ import io.ktor.client.request.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import org.khronos.webgl.ArrayBuffer
actual fun openPlatform(packageID:String, platformLink:String){ actual fun openPlatform(packageID:String, platformLink:String){
//TODO //TODO
@ -43,13 +42,14 @@ private suspend fun isInternetAvailable(): Boolean {
actual val isInternetAvailable:Boolean actual val isInternetAvailable:Boolean
get(){ get(){
return true return true
var result = false /*var result = false
val job = GlobalScope.launch { result = isInternetAvailable() } val job = GlobalScope.launch { result = isInternetAvailable() }
while(job.isActive){} while(job.isActive){}
return result return result*/
} }
val DownloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>> = MutableSharedFlow(1) val DownloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>> = MutableSharedFlow(1)
val allTracksStatus: HashMap<String, DownloadStatus> = hashMapOf()
actual suspend fun downloadTracks( actual suspend fun downloadTracks(
list: List<TrackDetails>, list: List<TrackDetails>,
@ -58,35 +58,48 @@ actual suspend fun downloadTracks(
){ ){
withContext(Dispatchers.Default){ withContext(Dispatchers.Default){
list.forEach { list.forEach {
allTracksStatus[it.title] = DownloadStatus.Queued
if (!it.videoID.isNullOrBlank()) {//Video ID already known! if (!it.videoID.isNullOrBlank()) {//Video ID already known!
downloadTrack(it.videoID!!, it, fetcher, dir) downloadTrack(it.videoID!!, it, fetcher, dir)
} else { } else {
val searchQuery = "${it.title} - ${it.artists.joinToString(",")}" val searchQuery = "${it.title} - ${it.artists.joinToString(",")}"
val videoID = fetcher.youtubeMusic.getYTIDBestMatch(searchQuery,it) val videoID = fetcher.youtubeMusic.getYTIDBestMatch(searchQuery,it)
if (videoID.isNullOrBlank()) { if (videoID.isNullOrBlank()) {
allTracksStatus[it.title] = DownloadStatus.Failed
DownloadProgressFlow.emit(allTracksStatus)
} else {//Found Youtube Video ID } else {//Found Youtube Video ID
downloadTrack(videoID, it, fetcher, dir) downloadTrack(videoID, it, fetcher, dir)
} }
} }
} }
DownloadProgressFlow.emit(allTracksStatus)
} }
} }
suspend fun downloadTrack(videoID: String, track: TrackDetails, fetcher:FetchPlatformQueryResult,dir:Dir) { suspend fun downloadTrack(videoID: String, track: TrackDetails, fetcher:FetchPlatformQueryResult,dir:Dir) {
val url = fetcher.youtubeMp3.getMp3DownloadLink(videoID) val url = fetcher.youtubeMp3.getMp3DownloadLink(videoID)
if(url == null){ if(url == null){
// TODO Handle allTracksStatus[track.title] = DownloadStatus.Failed
DownloadProgressFlow.emit(allTracksStatus)
println("No URL to Download") println("No URL to Download")
}else { }else {
downloadFile(url).collect { downloadFile(url).collect {
when(it){ when(it){
is DownloadResult.Success -> { is DownloadResult.Success -> {
println("Download Completed") println("Download Completed")
allTracksStatus[track.title] = DownloadStatus.Downloaded
dir.saveFileWithMetadata(it.byteArray, track) dir.saveFileWithMetadata(it.byteArray, track)
} }
is DownloadResult.Error -> println("Download Error: ${track.title}") is DownloadResult.Error -> {
is DownloadResult.Progress -> println("Download Progress: ${it.progress} : ${track.title}") allTracksStatus[track.title] = DownloadStatus.Failed
println("Download Error: ${track.title}")
}
is DownloadResult.Progress -> {
allTracksStatus[track.title] = DownloadStatus.Downloading(it.progress)
println("Download Progress: ${it.progress} : ${track.title}")
}
} }
DownloadProgressFlow.emit(allTracksStatus)
} }
} }
} }

View File

@ -74,7 +74,7 @@ actual class Dir actual constructor(
private suspend fun writeTagsAndSave(writer:ID3Writer, albumArt:Object?, trackDetails: TrackDetails){ private suspend fun writeTagsAndSave(writer:ID3Writer, albumArt:Object?, trackDetails: TrackDetails){
writer.apply { writer.apply {
setFrame("TIT2", trackDetails.title) setFrame("TIT2", trackDetails.title)
setFrame("TPE1", trackDetails.artists) setFrame("TPE1", trackDetails.artists.toTypedArray())
setFrame("TALB", trackDetails.albumName?:"") setFrame("TALB", trackDetails.albumName?:"")
try{trackDetails.year?.substring(0,4)?.toInt()?.let { setFrame("TYER", it) }} catch(e:Exception){} try{trackDetails.year?.substring(0,4)?.toInt()?.let { setFrame("TYER", it) }} catch(e:Exception){}
setFrame("TPE2", trackDetails.artists.joinToString(",")) setFrame("TPE2", trackDetails.artists.joinToString(","))

View File

@ -6,11 +6,10 @@ import com.arkivanov.decompose.lifecycle.resume
import com.arkivanov.mvikotlin.core.store.StoreFactory import com.arkivanov.mvikotlin.core.store.StoreFactory
import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
import com.shabinder.common.models.DownloadStatus import com.shabinder.common.di.DownloadProgressFlow
import com.shabinder.common.root.SpotiFlyerRoot import com.shabinder.common.root.SpotiFlyerRoot
import com.shabinder.database.Database import com.shabinder.database.Database
import extras.renderableChild import extras.renderableChild
import kotlinx.coroutines.flow.MutableSharedFlow
import react.* import react.*
import root.RootR import root.RootR
@ -40,8 +39,7 @@ class App(props: AppProps): RComponent<AppProps, RState>(props) {
override val directories = dependencies.directories override val directories = dependencies.directories
override val database: Database? = directories.db override val database: Database? = directories.db
override val showPopUpMessage: (String) -> Unit = {}//TODO override val showPopUpMessage: (String) -> Unit = {}//TODO
override val downloadProgressReport: MutableSharedFlow<HashMap<String, DownloadStatus>> override val downloadProgressReport = DownloadProgressFlow
= MutableSharedFlow(1)
} }
) )

View File

@ -10,7 +10,6 @@ val colorOffWhite = Color("#E7E7E7")
object Styles: StyleSheet("Searchbar", isStatic = true) { object Styles: StyleSheet("Searchbar", isStatic = true) {
val makeRow by css { val makeRow by css {
display = Display.flex display = Display.flex
flexDirection = FlexDirection.row
alignItems = Align.center alignItems = Align.center
alignContent = Align.center alignContent = Align.center
justifyContent = JustifyContent.center justifyContent = JustifyContent.center

View File

@ -24,11 +24,11 @@ fun RBuilder.IconList(handler:IconListProps.() -> Unit): ReactElement {
private val iconList = functionalComponent<IconListProps>("IconList") { props -> private val iconList = functionalComponent<IconListProps>("IconList") { props ->
styledDiv { styledDiv {
css { css {
+Styles.makeRow
margin(18.px) margin(18.px)
if(props.isBadge) { if(props.isBadge) {
alignItems = Align.end classes = mutableListOf("info-banners")
} }
+ Styles.makeRow
} }
for((icon,platformLink) in props.iconsAndPlatforms){ for((icon,platformLink) in props.iconsAndPlatforms){
styledA(href = platformLink){ styledA(href = platformLink){

View File

@ -25,7 +25,7 @@ private val message = functionalComponent<MessageProps>("Message") { props->
+ props.text + props.text
css { css {
classes = mutableListOf("headingTitle") classes = mutableListOf("headingTitle")
fontSize = 3.2.rem fontSize = 2.6.em
} }
} }
} }

View File

@ -0,0 +1,38 @@
package list
import kotlinx.css.px
import kotlinx.css.width
import react.*
import styled.css
import styled.styledDiv
import styled.styledSpan
@Suppress("FunctionName")
fun RBuilder.CircularProgressBar(handler: CircularProgressBarProps.() -> Unit): ReactElement {
return child(circularProgressBar){
attrs {
handler()
}
}
}
external interface CircularProgressBarProps : RProps {
var progress:Int
}
private val circularProgressBar = functionalComponent<CircularProgressBarProps>("Circular-Progress-Bar") { props->
styledDiv {
styledSpan { +"${props.progress}%" }
styledDiv{
css {
classes = mutableListOf("left-half-clipper")
}
styledDiv{ css { classes = mutableListOf("first50-bar") } }
styledDiv{ css { classes = mutableListOf("value-bar") } }
}
css{
classes = mutableListOf("progress-circle","p${props.progress}").apply { if(props.progress>50) add("over50") }
width = 50.px
}
}
}

View File

@ -0,0 +1,49 @@
package list
import com.shabinder.common.models.DownloadStatus
import kotlinx.css.*
import kotlinx.html.js.onClickFunction
import react.*
import styled.css
import styled.styledDiv
import styled.styledImg
@Suppress("FunctionName")
fun RBuilder.DownloadButton(handler: DownloadButtonProps.() -> Unit): ReactElement {
return child(downloadButton){
attrs {
handler()
}
}
}
external interface DownloadButtonProps : RProps {
var onClick:()->Unit
var status :DownloadStatus
}
private val downloadButton = functionalComponent<DownloadButtonProps>("Circular-Progress-Bar") { props->
styledDiv {
val src = when(props.status){
is DownloadStatus.NotDownloaded -> "download-gradient.svg"
is DownloadStatus.Downloaded -> "check.svg"
is DownloadStatus.Failed -> "error.svg"
else -> ""
}
styledImg(src = src) {
attrs {
onClickFunction = {
props.onClick()
}
}
css {
width = (2.5).em
margin(8.px)
}
}
css {
classes = mutableListOf("glow-button")
borderRadius = 100.px
}
}
}

View File

@ -9,6 +9,7 @@ import kotlinx.html.id
import react.RBuilder import react.RBuilder
import styled.css import styled.css
import styled.styledDiv import styled.styledDiv
import styled.styledSection
class ListScreen( class ListScreen(
props: Props<SpotiFlyerList>, props: Props<SpotiFlyerList>,
@ -20,9 +21,9 @@ class ListScreen(
val result = state.data.queryResult val result = state.data.queryResult
styledDiv { styledSection {
attrs { attrs {
id = "list-screen-div" id = "list-screen"
} }
if(result == null){ if(result == null){
@ -37,10 +38,18 @@ class ListScreen(
isActive = state.data.trackList.isNotEmpty() isActive = state.data.trackList.isNotEmpty()
} }
state.data.trackList.forEachIndexed{ index, trackDetails -> styledDiv{
TrackItem { css {
details = trackDetails display =Display.flex
downloadTrack = model::onDownloadClicked flexGrow = 1.0
flexDirection = FlexDirection.column
color = Color.white
}
state.data.trackList.forEachIndexed{ index, trackDetails ->
TrackItem {
details = trackDetails
downloadTrack = model::onDownloadClicked
}
} }
} }
} }
@ -48,10 +57,9 @@ class ListScreen(
css { css {
classes = mutableListOf("list-screen") classes = mutableListOf("list-screen")
display = Display.flex display = Display.flex
padding(8.px)
flexDirection = FlexDirection.column flexDirection = FlexDirection.column
flexGrow = 1.0 flexGrow = 1.0
justifyContent = JustifyContent.center
alignItems = Align.stretch
} }
} }
} }

View File

@ -16,22 +16,28 @@ fun RBuilder.LoadingAnim(handler: RProps.() -> Unit): ReactElement {
} }
private val loadingAnim = functionalComponent<RProps>("Loading Animation") { private val loadingAnim = functionalComponent<RProps>("Loading Animation") {
styledDiv { styledDiv{
styledDiv { css { classes = mutableListOf("sk-cube sk-cube1") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube2") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube3") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube4") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube5") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube6") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube7") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube8") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube9") } }
css { css {
classes = mutableListOf("sk-cube-grid") flexGrow = 1.0
height = 60.px display = Display.flex
width = 60.px alignItems = Align.center
}
styledDiv {
styledDiv { css { classes = mutableListOf("sk-cube sk-cube1") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube2") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube3") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube4") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube5") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube6") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube7") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube8") } }
styledDiv { css { classes = mutableListOf("sk-cube sk-cube9") } }
css {
classes = mutableListOf("sk-cube-grid")
height = 60.px
width = 60.px
}
} }
} }
} }

View File

@ -0,0 +1,29 @@
package list
import kotlinx.css.px
import kotlinx.css.width
import react.*
import styled.css
import styled.styledDiv
@Suppress("FunctionName")
fun RBuilder.LoadingSpinner(handler: RProps.() -> Unit): ReactElement {
return child(loadingSpinner){
attrs {
handler()
}
}
}
private val loadingSpinner = functionalComponent<RProps>("Loading-Spinner") {
styledDiv {
styledDiv{}
styledDiv{}
styledDiv{}
styledDiv{}
css{
classes = mutableListOf("lds-ring")
width = 50.px
}
}
}

View File

@ -1,9 +1,9 @@
package list package list
import com.shabinder.common.models.DownloadStatus
import com.shabinder.common.models.TrackDetails import com.shabinder.common.models.TrackDetails
import kotlinx.css.* import kotlinx.css.*
import kotlinx.html.id import kotlinx.html.id
import kotlinx.html.js.onClickFunction
import react.* import react.*
import styled.* import styled.*
@ -36,72 +36,99 @@ private val trackItem = functionalComponent<TrackItemProps>("Track-Item"){ props
attrs { attrs {
id = "text-details" id = "text-details"
} }
styledDiv { css {
flexGrow = 1.0
minWidth = 0.px
display = Display.flex
flexDirection = FlexDirection.column
margin(8.px)
}
styledDiv{
css {
height = 40.px
alignItems = Align.center
display = Display.flex
}
styledH3 { styledH3 {
+ details.title + details.title
css { css {
padding(8.px) padding(8.px)
fontSize = 1.3.em
textOverflow = TextOverflow.ellipsis
whiteSpace = WhiteSpace.nowrap
overflow = Overflow.hidden
} }
} }
css {
height = 40.px
display =Display.flex
alignItems = Align.center
}
} }
styledDiv { styledDiv {
css {
height = 40.px
alignItems = Align.center
display = Display.flex
}
styledH4 { styledH4 {
+ details.artists.joinToString(",") + details.artists.joinToString(",")
css { css {
flexGrow = 1.0 flexGrow = 1.0
padding(8.px) padding(8.px)
minWidth = 4.em
fontSize = 1.1.em
textOverflow = TextOverflow.ellipsis
whiteSpace = WhiteSpace.nowrap
overflow = Overflow.hidden
} }
} }
styledH4 { styledH4 {
+ "${details.durationSec} sec"
css { css {
textAlign = TextAlign.end
flexGrow = 1.0 flexGrow = 1.0
padding(8.px) padding(8.px)
textAlign = TextAlign.right minWidth = 4.em
fontSize = 1.1.em
textOverflow = TextOverflow.ellipsis
whiteSpace = WhiteSpace.nowrap
overflow = Overflow.hidden
} }
+ details.durationSec.toString()
} }
css {
height = 40.px
display =Display.flex
alignItems = Align.center
}
}
css {
display = Display.flex
flexGrow = 1.0
flexDirection = FlexDirection.column
margin(8.px)
} }
} }
styledDiv { when(details.downloaded){
styledImg(src = "download-gradient.svg") { is DownloadStatus.NotDownloaded ->{
attrs { DownloadButton {
onClickFunction = { onClick = { props.downloadTrack(details) }
props.downloadTrack(details) status = details.downloaded
}
}
css {
margin(8.px)
} }
} }
css { is DownloadStatus.Downloading -> {
classes = mutableListOf("glow-button") CircularProgressBar {
borderRadius = 100.px progress = (details.downloaded as DownloadStatus.Downloading).progress
width = 65.px }
}
DownloadStatus.Queued -> {
LoadingSpinner {}
}
DownloadStatus.Downloaded -> {
DownloadButton {
onClick = {}
status = details.downloaded
}
}
DownloadStatus.Converting -> {
LoadingSpinner {}
}
DownloadStatus.Failed -> {
DownloadButton {
onClick = {}
status = details.downloaded
}
} }
} }
css { css {
alignItems = Align.center alignItems = Align.center
display =Display.flex display =Display.flex
flexDirection = FlexDirection.row
flexGrow = 1.0 flexGrow = 1.0
color = Color.white
} }
} }
} }

View File

@ -0,0 +1 @@
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(1 0 0 -1 0 -6826)" gradientUnits="userSpaceOnUse" x1="0" x2="512" y1="-7082" y2="-7082"><stop offset="0" stop-color="#31d8ff"/><stop offset="1" stop-color="#FC5C7D"/></linearGradient><path d="m512 256c0 141.386719-114.613281 256-256 256s-256-114.613281-256-256 114.613281-256 256-256 256 114.613281 256 256zm0 0" fill="url(#a)"/><path d="m175 395.246094c-4.035156 0-7.902344-1.628906-10.726562-4.511719l-81-82.832031c-5.789063-5.921875-5.683594-15.417969.238281-21.210938 5.921875-5.792968 15.417969-5.6875 21.210937.238282l70.273438 71.859374 232.277344-237.523437c5.792968-5.921875 15.289062-6.027344 21.210937-.234375 5.925781 5.789062 6.03125 15.289062.238281 21.210938l-243 248.492187c-2.820312 2.882813-6.6875 4.511719-10.722656 4.511719zm0 0" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 923 B

View File

@ -0,0 +1,168 @@
.progress-circle {
margin: 20px;
position: relative; /* so that children can be absolutely positioned */
line-height: 5em;
}
.progress-circle:after{
border: none;
position: absolute;
text-align: center;
display: block;
border-radius: 50%;
width: 4.3em;
height: 4.3em;
background-color: white;
content: " ";
}
/* Text inside the control */
.progress-circle span {
position: absolute;
line-height: 5em;
width: 5em;
text-align: center;
display: block;
color: #53777A;
z-index: 2;
}
.left-half-clipper {
/* a round circle */
border-radius: 50%;
width: 5em;
height: 5em;
position: absolute; /* needed for clipping */
clip: rect(0, 5em, 5em, 2.5em); /* clips the whole left half*/
}
/* when p>50, don't clip left half*/
.progress-circle.over50 .left-half-clipper {
clip: rect(auto,auto,auto,auto);
}
.value-bar {
/*This is an overlayed square, that is made round with the border radius,
then it is cut to display only the left half, then rotated clockwise
to escape the outer clipping path.*/
position: absolute; /*needed for clipping*/
clip: rect(0, 2.5em, 5em, 0);
width: 5em;
height: 5em;
border-radius: 50%;
border: 0.45em solid #53777A; /*The border is 0.35 but making it larger removes visual artifacts */
/*background-color: #4D642D;*/ /* for debug */
box-sizing: border-box;
}
/* Progress bar filling the whole right half for values above 50% */
.progress-circle.over50 .first50-bar {
/*Progress bar for the first 50%, filling the whole right half*/
position: absolute; /*needed for clipping*/
clip: rect(0, 5em, 5em, 2.5em);
background-color: #53777A;
border-radius: 50%;
width: 5em;
height: 5em;
}
.progress-circle:not(.over50) .first50-bar{ display: none; }
/* Progress bar rotation position */
.progress-circle.p0 .value-bar { display: none; }
.progress-circle.p1 .value-bar { transform: rotate(4deg); }
.progress-circle.p2 .value-bar { transform: rotate(7deg); }
.progress-circle.p3 .value-bar { transform: rotate(11deg); }
.progress-circle.p4 .value-bar { transform: rotate(14deg); }
.progress-circle.p5 .value-bar { transform: rotate(18deg); }
.progress-circle.p6 .value-bar { transform: rotate(22deg); }
.progress-circle.p7 .value-bar { transform: rotate(25deg); }
.progress-circle.p8 .value-bar { transform: rotate(29deg); }
.progress-circle.p9 .value-bar { transform: rotate(32deg); }
.progress-circle.p10 .value-bar { transform: rotate(36deg); }
.progress-circle.p11 .value-bar { transform: rotate(40deg); }
.progress-circle.p12 .value-bar { transform: rotate(43deg); }
.progress-circle.p13 .value-bar { transform: rotate(47deg); }
.progress-circle.p14 .value-bar { transform: rotate(50deg); }
.progress-circle.p15 .value-bar { transform: rotate(54deg); }
.progress-circle.p16 .value-bar { transform: rotate(58deg); }
.progress-circle.p17 .value-bar { transform: rotate(61deg); }
.progress-circle.p18 .value-bar { transform: rotate(65deg); }
.progress-circle.p19 .value-bar { transform: rotate(68deg); }
.progress-circle.p20 .value-bar { transform: rotate(72deg); }
.progress-circle.p21 .value-bar { transform: rotate(76deg); }
.progress-circle.p22 .value-bar { transform: rotate(79deg); }
.progress-circle.p23 .value-bar { transform: rotate(83deg); }
.progress-circle.p24 .value-bar { transform: rotate(86deg); }
.progress-circle.p25 .value-bar { transform: rotate(90deg); }
.progress-circle.p26 .value-bar { transform: rotate(94deg); }
.progress-circle.p27 .value-bar { transform: rotate(97deg); }
.progress-circle.p28 .value-bar { transform: rotate(101deg); }
.progress-circle.p29 .value-bar { transform: rotate(104deg); }
.progress-circle.p30 .value-bar { transform: rotate(108deg); }
.progress-circle.p31 .value-bar { transform: rotate(112deg); }
.progress-circle.p32 .value-bar { transform: rotate(115deg); }
.progress-circle.p33 .value-bar { transform: rotate(119deg); }
.progress-circle.p34 .value-bar { transform: rotate(122deg); }
.progress-circle.p35 .value-bar { transform: rotate(126deg); }
.progress-circle.p36 .value-bar { transform: rotate(130deg); }
.progress-circle.p37 .value-bar { transform: rotate(133deg); }
.progress-circle.p38 .value-bar { transform: rotate(137deg); }
.progress-circle.p39 .value-bar { transform: rotate(140deg); }
.progress-circle.p40 .value-bar { transform: rotate(144deg); }
.progress-circle.p41 .value-bar { transform: rotate(148deg); }
.progress-circle.p42 .value-bar { transform: rotate(151deg); }
.progress-circle.p43 .value-bar { transform: rotate(155deg); }
.progress-circle.p44 .value-bar { transform: rotate(158deg); }
.progress-circle.p45 .value-bar { transform: rotate(162deg); }
.progress-circle.p46 .value-bar { transform: rotate(166deg); }
.progress-circle.p47 .value-bar { transform: rotate(169deg); }
.progress-circle.p48 .value-bar { transform: rotate(173deg); }
.progress-circle.p49 .value-bar { transform: rotate(176deg); }
.progress-circle.p50 .value-bar { transform: rotate(180deg); }
.progress-circle.p51 .value-bar { transform: rotate(184deg); }
.progress-circle.p52 .value-bar { transform: rotate(187deg); }
.progress-circle.p53 .value-bar { transform: rotate(191deg); }
.progress-circle.p54 .value-bar { transform: rotate(194deg); }
.progress-circle.p55 .value-bar { transform: rotate(198deg); }
.progress-circle.p56 .value-bar { transform: rotate(202deg); }
.progress-circle.p57 .value-bar { transform: rotate(205deg); }
.progress-circle.p58 .value-bar { transform: rotate(209deg); }
.progress-circle.p59 .value-bar { transform: rotate(212deg); }
.progress-circle.p60 .value-bar { transform: rotate(216deg); }
.progress-circle.p61 .value-bar { transform: rotate(220deg); }
.progress-circle.p62 .value-bar { transform: rotate(223deg); }
.progress-circle.p63 .value-bar { transform: rotate(227deg); }
.progress-circle.p64 .value-bar { transform: rotate(230deg); }
.progress-circle.p65 .value-bar { transform: rotate(234deg); }
.progress-circle.p66 .value-bar { transform: rotate(238deg); }
.progress-circle.p67 .value-bar { transform: rotate(241deg); }
.progress-circle.p68 .value-bar { transform: rotate(245deg); }
.progress-circle.p69 .value-bar { transform: rotate(248deg); }
.progress-circle.p70 .value-bar { transform: rotate(252deg); }
.progress-circle.p71 .value-bar { transform: rotate(256deg); }
.progress-circle.p72 .value-bar { transform: rotate(259deg); }
.progress-circle.p73 .value-bar { transform: rotate(263deg); }
.progress-circle.p74 .value-bar { transform: rotate(266deg); }
.progress-circle.p75 .value-bar { transform: rotate(270deg); }
.progress-circle.p76 .value-bar { transform: rotate(274deg); }
.progress-circle.p77 .value-bar { transform: rotate(277deg); }
.progress-circle.p78 .value-bar { transform: rotate(281deg); }
.progress-circle.p79 .value-bar { transform: rotate(284deg); }
.progress-circle.p80 .value-bar { transform: rotate(288deg); }
.progress-circle.p81 .value-bar { transform: rotate(292deg); }
.progress-circle.p82 .value-bar { transform: rotate(295deg); }
.progress-circle.p83 .value-bar { transform: rotate(299deg); }
.progress-circle.p84 .value-bar { transform: rotate(302deg); }
.progress-circle.p85 .value-bar { transform: rotate(306deg); }
.progress-circle.p86 .value-bar { transform: rotate(310deg); }
.progress-circle.p87 .value-bar { transform: rotate(313deg); }
.progress-circle.p88 .value-bar { transform: rotate(317deg); }
.progress-circle.p89 .value-bar { transform: rotate(320deg); }
.progress-circle.p90 .value-bar { transform: rotate(324deg); }
.progress-circle.p91 .value-bar { transform: rotate(328deg); }
.progress-circle.p92 .value-bar { transform: rotate(331deg); }
.progress-circle.p93 .value-bar { transform: rotate(335deg); }
.progress-circle.p94 .value-bar { transform: rotate(338deg); }
.progress-circle.p95 .value-bar { transform: rotate(342deg); }
.progress-circle.p96 .value-bar { transform: rotate(346deg); }
.progress-circle.p97 .value-bar { transform: rotate(349deg); }
.progress-circle.p98 .value-bar { transform: rotate(353deg); }
.progress-circle.p99 .value-bar { transform: rotate(356deg); }
.progress-circle.p100 .value-bar { transform: rotate(360deg); }

View File

@ -6,8 +6,8 @@
<stop offset="0" style="stop-color:#80D8FF"/> <stop offset="0" style="stop-color:#80D8FF"/>
<stop offset="0.16" style="stop-color:#88D1FF"/> <stop offset="0.16" style="stop-color:#88D1FF"/>
<stop offset="0.413" style="stop-color:#9FBEFE"/> <stop offset="0.413" style="stop-color:#9FBEFE"/>
<stop offset="0.725" style="stop-color:#C4A0FD"/> <stop offset="0.725" style="stop-color:#FC5C7D"/>
<stop offset="1" style="stop-color:#EA80FC"/> <stop offset="1" style="stop-color:#FC5C7D"/>
</linearGradient> </linearGradient>
<path style="fill:url(#SVGID_1_);" d="M462.622,512H49.378C22.151,512,0,489.85,0,462.623v-118.49c0-11.046,8.954-20,20-20 <path style="fill:url(#SVGID_1_);" d="M462.622,512H49.378C22.151,512,0,489.85,0,462.623v-118.49c0-11.046,8.954-20,20-20
s20,8.954,20,20v118.49c0,5.171,4.207,9.377,9.378,9.377h413.244c5.171,0,9.378-4.207,9.378-9.377v-118.49c0-11.046,8.954-20,20-20 s20,8.954,20,20v118.49c0,5.171,4.207,9.377,9.378,9.377h413.244c5.171,0,9.378-4.207,9.378-9.377v-118.49c0-11.046,8.954-20,20-20

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(1 0 0 -1 0 -12146)" gradientUnits="userSpaceOnUse" x1="0" x2="512" y1="-12402" y2="-12402"><stop offset="0" stop-color="#9AB3FF"/><stop offset="1" stop-color="#FC5C7D"/></linearGradient><path d="m512 256c0 141.386719-114.613281 256-256 256s-256-114.613281-256-256 114.613281-256 256-256 256 114.613281 256 256zm0 0" fill="url(#a)"/><g fill="#fff"><path d="m256 56c-110.28125 0-200 89.71875-200 200s89.71875 200 200 200 200-89.71875 200-200-89.71875-200-200-200zm0 370c-93.738281 0-170-76.261719-170-170s76.261719-170 170-170 170 76.261719 170 170-76.261719 170-170 170zm0 0"/><path d="m324.179688 187.820312c-5.859376-5.855468-15.355469-5.855468-21.214844 0l-46.964844 46.964844-46.964844-46.964844c-5.859375-5.855468-15.355468-5.855468-21.214844 0-5.855468 5.859376-5.855468 15.355469 0 21.214844l46.964844 46.964844-46.964844 46.964844c-5.855468 5.859375-5.855468 15.355468 0 21.214844 2.929688 2.929687 6.769532 4.394531 10.605469 4.394531 3.839844 0 7.679688-1.464844 10.605469-4.394531l46.96875-46.964844 46.964844 46.964844c2.929687 2.929687 6.769531 4.394531 10.605468 4.394531 3.839844 0 7.679688-1.464844 10.609376-4.394531 5.855468-5.859376 5.855468-15.355469 0-21.214844l-46.964844-46.964844 46.964844-46.964844c5.855468-5.859375 5.855468-15.355468 0-21.214844zm0 0"/></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -7,10 +7,11 @@
<script src="web-app.js"></script> <script src="web-app.js"></script>
<link rel="icon" href="spotiflyer.svg" type="image/icon type"> <link rel="icon" href="spotiflyer.svg" type="image/icon type">
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<link href="css-circular-prog-bar.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.gstatic.com"> <link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=RocknRoll+One&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=RocknRoll+One&display=swap" rel="stylesheet">
</head> </head>
<body> <body>
<div style="height: 100%;display: flex; align-items: center;flex-direction: column" id="root"></div> <div style="display: flex;flex-direction: column; height: inherit; color: white;" id="root"></div>
</body> </body>
</html> </html>

View File

@ -2,6 +2,16 @@
font-family: pristine; font-family: pristine;
src: url("pristine_script.ttf"); src: url("pristine_script.ttf");
} }
@media (max-width: 600px) {
/* CSS HERE ONLY ON PHONE */
.searchBox:hover > .searchInput {
width: 150px;
padding: 0 6px;
}
.info-banners {
flex-direction: column;
}
}
html { html {
background-image: url("header-dark.jpg"); background-image: url("header-dark.jpg");
font-family: Lora,Helvetica Neue,Helvetica,Arial,sans-serif; font-family: Lora,Helvetica Neue,Helvetica,Arial,sans-serif;
@ -20,6 +30,8 @@ body, html {
} }
#appName{ #appName{
font-family: pristine, cursive; font-family: pristine, cursive;
font-weight: 100;
text-shadow: 0.3px 0.5px #ffffff;
} }
.headingTitle{ .headingTitle{
text-align: center; text-align: center;
@ -30,6 +42,42 @@ body, html {
color: rgba(255, 255, 255, 1); color: rgba(255, 255, 255, 1);
box-shadow: 0 5px 15px rgb(105, 44, 143); box-shadow: 0 5px 15px rgb(105, 44, 143);
} }
/*Loading Spinner*/
.lds-ring {
align-items: center;
justify-content: center;
display: flex;
}
.lds-ring div {
box-sizing: border-box;
display: block;
position: absolute;
width: 3.5em;
height: 3.5em;
border: 8px solid #fff;
border-radius: 50%;
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
border-color: #fff transparent transparent transparent;
}
.lds-ring div:nth-child(1) {
animation-delay: -0.45s;
}
.lds-ring div:nth-child(2) {
animation-delay: -0.3s;
}
.lds-ring div:nth-child(3) {
animation-delay: -0.15s;
}
@keyframes lds-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.button { .button {
text-decoration: none; text-decoration: none;
color: rgba(255, 255, 255, 0.8); color: rgba(255, 255, 255, 0.8);
@ -190,10 +238,4 @@ body, html {
-webkit-transform: scale3D(0, 0, 1); -webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1); transform: scale3D(0, 0, 1);
} }
}
@media screen and (max-width: 620px) {
.searchBox:hover > .searchInput {
width: 150px;
padding: 0 6px;
}
} }