From 90b99cbb51016bed5290837b85c372c376c9e105 Mon Sep 17 00:00:00 2001 From: shabinder Date: Sat, 13 Mar 2021 16:07:27 +0530 Subject: [PATCH] Style Fixes on Small Screens --- .../com/shabinder/common/di/WebActual.kt | 25 ++- .../kotlin/com/shabinder/common/di/WebDir.kt | 2 +- web-app/src/main/kotlin/App.kt | 6 +- web-app/src/main/kotlin/Styles.kt | 1 - web-app/src/main/kotlin/home/IconList.kt | 4 +- web-app/src/main/kotlin/home/Message.kt | 2 +- .../main/kotlin/list/CircularProgressBar.kt | 38 ++++ .../src/main/kotlin/list/DownloadButton.kt | 49 +++++ web-app/src/main/kotlin/list/ListScreen.kt | 24 ++- web-app/src/main/kotlin/list/LoadingAnim.kt | 36 ++-- .../src/main/kotlin/list/LoadingSpinner.kt | 29 +++ web-app/src/main/kotlin/list/TrackItem.kt | 97 ++++++---- web-app/src/main/resources/check.svg | 1 + .../main/resources/css-circular-prog-bar.css | 168 ++++++++++++++++++ .../src/main/resources/download-gradient.svg | 4 +- web-app/src/main/resources/error.svg | 1 + web-app/src/main/resources/index.html | 3 +- web-app/src/main/resources/styles.css | 54 +++++- 18 files changed, 462 insertions(+), 82 deletions(-) create mode 100644 web-app/src/main/kotlin/list/CircularProgressBar.kt create mode 100644 web-app/src/main/kotlin/list/DownloadButton.kt create mode 100644 web-app/src/main/kotlin/list/LoadingSpinner.kt create mode 100644 web-app/src/main/resources/check.svg create mode 100644 web-app/src/main/resources/css-circular-prog-bar.css create mode 100644 web-app/src/main/resources/error.svg diff --git a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebActual.kt b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebActual.kt index 520e106d..b3037611 100644 --- a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebActual.kt +++ b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebActual.kt @@ -7,7 +7,6 @@ import io.ktor.client.request.* import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.collect -import org.khronos.webgl.ArrayBuffer actual fun openPlatform(packageID:String, platformLink:String){ //TODO @@ -43,13 +42,14 @@ private suspend fun isInternetAvailable(): Boolean { actual val isInternetAvailable:Boolean get(){ return true - var result = false + /*var result = false val job = GlobalScope.launch { result = isInternetAvailable() } while(job.isActive){} - return result + return result*/ } val DownloadProgressFlow: MutableSharedFlow> = MutableSharedFlow(1) +val allTracksStatus: HashMap = hashMapOf() actual suspend fun downloadTracks( list: List, @@ -58,35 +58,48 @@ actual suspend fun downloadTracks( ){ withContext(Dispatchers.Default){ list.forEach { + allTracksStatus[it.title] = DownloadStatus.Queued if (!it.videoID.isNullOrBlank()) {//Video ID already known! downloadTrack(it.videoID!!, it, fetcher, dir) } else { val searchQuery = "${it.title} - ${it.artists.joinToString(",")}" val videoID = fetcher.youtubeMusic.getYTIDBestMatch(searchQuery,it) if (videoID.isNullOrBlank()) { + allTracksStatus[it.title] = DownloadStatus.Failed + DownloadProgressFlow.emit(allTracksStatus) } else {//Found Youtube Video ID downloadTrack(videoID, it, fetcher, dir) } } } + DownloadProgressFlow.emit(allTracksStatus) } } suspend fun downloadTrack(videoID: String, track: TrackDetails, fetcher:FetchPlatformQueryResult,dir:Dir) { val url = fetcher.youtubeMp3.getMp3DownloadLink(videoID) if(url == null){ - // TODO Handle + allTracksStatus[track.title] = DownloadStatus.Failed + DownloadProgressFlow.emit(allTracksStatus) println("No URL to Download") }else { downloadFile(url).collect { when(it){ is DownloadResult.Success -> { println("Download Completed") + allTracksStatus[track.title] = DownloadStatus.Downloaded dir.saveFileWithMetadata(it.byteArray, track) } - is DownloadResult.Error -> println("Download Error: ${track.title}") - is DownloadResult.Progress -> println("Download Progress: ${it.progress} : ${track.title}") + is DownloadResult.Error -> { + 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) } } } diff --git a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebDir.kt b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebDir.kt index e9d66437..b9db776b 100644 --- a/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebDir.kt +++ b/common/dependency-injection/src/jsMain/kotlin/com/shabinder/common/di/WebDir.kt @@ -74,7 +74,7 @@ actual class Dir actual constructor( private suspend fun writeTagsAndSave(writer:ID3Writer, albumArt:Object?, trackDetails: TrackDetails){ writer.apply { setFrame("TIT2", trackDetails.title) - setFrame("TPE1", trackDetails.artists) + setFrame("TPE1", trackDetails.artists.toTypedArray()) setFrame("TALB", trackDetails.albumName?:"") try{trackDetails.year?.substring(0,4)?.toInt()?.let { setFrame("TYER", it) }} catch(e:Exception){} setFrame("TPE2", trackDetails.artists.joinToString(",")) diff --git a/web-app/src/main/kotlin/App.kt b/web-app/src/main/kotlin/App.kt index 3b3ffaa6..e56fff15 100644 --- a/web-app/src/main/kotlin/App.kt +++ b/web-app/src/main/kotlin/App.kt @@ -6,11 +6,10 @@ import com.arkivanov.decompose.lifecycle.resume import com.arkivanov.mvikotlin.core.store.StoreFactory import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory 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.database.Database import extras.renderableChild -import kotlinx.coroutines.flow.MutableSharedFlow import react.* import root.RootR @@ -40,8 +39,7 @@ class App(props: AppProps): RComponent(props) { override val directories = dependencies.directories override val database: Database? = directories.db override val showPopUpMessage: (String) -> Unit = {}//TODO - override val downloadProgressReport: MutableSharedFlow> - = MutableSharedFlow(1) + override val downloadProgressReport = DownloadProgressFlow } ) diff --git a/web-app/src/main/kotlin/Styles.kt b/web-app/src/main/kotlin/Styles.kt index 8150645a..e4b6fd96 100644 --- a/web-app/src/main/kotlin/Styles.kt +++ b/web-app/src/main/kotlin/Styles.kt @@ -10,7 +10,6 @@ val colorOffWhite = Color("#E7E7E7") object Styles: StyleSheet("Searchbar", isStatic = true) { val makeRow by css { display = Display.flex - flexDirection = FlexDirection.row alignItems = Align.center alignContent = Align.center justifyContent = JustifyContent.center diff --git a/web-app/src/main/kotlin/home/IconList.kt b/web-app/src/main/kotlin/home/IconList.kt index e496fab2..cb21ad7b 100644 --- a/web-app/src/main/kotlin/home/IconList.kt +++ b/web-app/src/main/kotlin/home/IconList.kt @@ -24,11 +24,11 @@ fun RBuilder.IconList(handler:IconListProps.() -> Unit): ReactElement { private val iconList = functionalComponent("IconList") { props -> styledDiv { css { - +Styles.makeRow margin(18.px) if(props.isBadge) { - alignItems = Align.end + classes = mutableListOf("info-banners") } + + Styles.makeRow } for((icon,platformLink) in props.iconsAndPlatforms){ styledA(href = platformLink){ diff --git a/web-app/src/main/kotlin/home/Message.kt b/web-app/src/main/kotlin/home/Message.kt index df5bc852..1460ccf0 100644 --- a/web-app/src/main/kotlin/home/Message.kt +++ b/web-app/src/main/kotlin/home/Message.kt @@ -25,7 +25,7 @@ private val message = functionalComponent("Message") { props-> + props.text css { classes = mutableListOf("headingTitle") - fontSize = 3.2.rem + fontSize = 2.6.em } } } diff --git a/web-app/src/main/kotlin/list/CircularProgressBar.kt b/web-app/src/main/kotlin/list/CircularProgressBar.kt new file mode 100644 index 00000000..b36eacf2 --- /dev/null +++ b/web-app/src/main/kotlin/list/CircularProgressBar.kt @@ -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("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 + } + } +} \ No newline at end of file diff --git a/web-app/src/main/kotlin/list/DownloadButton.kt b/web-app/src/main/kotlin/list/DownloadButton.kt new file mode 100644 index 00000000..fbca8036 --- /dev/null +++ b/web-app/src/main/kotlin/list/DownloadButton.kt @@ -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("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 + } + } +} \ No newline at end of file diff --git a/web-app/src/main/kotlin/list/ListScreen.kt b/web-app/src/main/kotlin/list/ListScreen.kt index 8a5aa508..a45b0bd5 100644 --- a/web-app/src/main/kotlin/list/ListScreen.kt +++ b/web-app/src/main/kotlin/list/ListScreen.kt @@ -9,6 +9,7 @@ import kotlinx.html.id import react.RBuilder import styled.css import styled.styledDiv +import styled.styledSection class ListScreen( props: Props, @@ -20,9 +21,9 @@ class ListScreen( val result = state.data.queryResult - styledDiv { + styledSection { attrs { - id = "list-screen-div" + id = "list-screen" } if(result == null){ @@ -37,10 +38,18 @@ class ListScreen( isActive = state.data.trackList.isNotEmpty() } - state.data.trackList.forEachIndexed{ index, trackDetails -> - TrackItem { - details = trackDetails - downloadTrack = model::onDownloadClicked + styledDiv{ + css { + display =Display.flex + 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 { classes = mutableListOf("list-screen") display = Display.flex + padding(8.px) flexDirection = FlexDirection.column flexGrow = 1.0 - justifyContent = JustifyContent.center - alignItems = Align.stretch } } } diff --git a/web-app/src/main/kotlin/list/LoadingAnim.kt b/web-app/src/main/kotlin/list/LoadingAnim.kt index dedab437..e701adfc 100644 --- a/web-app/src/main/kotlin/list/LoadingAnim.kt +++ b/web-app/src/main/kotlin/list/LoadingAnim.kt @@ -16,22 +16,28 @@ fun RBuilder.LoadingAnim(handler: RProps.() -> Unit): ReactElement { } private val loadingAnim = functionalComponent("Loading Animation") { - 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") } } - + styledDiv{ css { - classes = mutableListOf("sk-cube-grid") - height = 60.px - width = 60.px + flexGrow = 1.0 + display = Display.flex + 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 + } } } } \ No newline at end of file diff --git a/web-app/src/main/kotlin/list/LoadingSpinner.kt b/web-app/src/main/kotlin/list/LoadingSpinner.kt new file mode 100644 index 00000000..98adb9ba --- /dev/null +++ b/web-app/src/main/kotlin/list/LoadingSpinner.kt @@ -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("Loading-Spinner") { + styledDiv { + styledDiv{} + styledDiv{} + styledDiv{} + styledDiv{} + css{ + classes = mutableListOf("lds-ring") + width = 50.px + } + } +} \ No newline at end of file diff --git a/web-app/src/main/kotlin/list/TrackItem.kt b/web-app/src/main/kotlin/list/TrackItem.kt index a0ec5739..b28feda0 100644 --- a/web-app/src/main/kotlin/list/TrackItem.kt +++ b/web-app/src/main/kotlin/list/TrackItem.kt @@ -1,9 +1,9 @@ package list +import com.shabinder.common.models.DownloadStatus import com.shabinder.common.models.TrackDetails import kotlinx.css.* import kotlinx.html.id -import kotlinx.html.js.onClickFunction import react.* import styled.* @@ -36,72 +36,99 @@ private val trackItem = functionalComponent("Track-Item"){ props attrs { 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 { + details.title css { 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 { + css { + height = 40.px + alignItems = Align.center + display = Display.flex + } styledH4 { + details.artists.joinToString(",") css { flexGrow = 1.0 padding(8.px) + minWidth = 4.em + fontSize = 1.1.em + textOverflow = TextOverflow.ellipsis + whiteSpace = WhiteSpace.nowrap + overflow = Overflow.hidden } } styledH4 { - + "${details.durationSec} sec" css { + textAlign = TextAlign.end flexGrow = 1.0 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 { - styledImg(src = "download-gradient.svg") { - attrs { - onClickFunction = { - props.downloadTrack(details) - } - } - css { - margin(8.px) + when(details.downloaded){ + is DownloadStatus.NotDownloaded ->{ + DownloadButton { + onClick = { props.downloadTrack(details) } + status = details.downloaded } } - css { - classes = mutableListOf("glow-button") - borderRadius = 100.px - width = 65.px + is DownloadStatus.Downloading -> { + CircularProgressBar { + progress = (details.downloaded as DownloadStatus.Downloading).progress + } + } + DownloadStatus.Queued -> { + LoadingSpinner {} + } + DownloadStatus.Downloaded -> { + DownloadButton { + onClick = {} + status = details.downloaded + } + } + DownloadStatus.Converting -> { + LoadingSpinner {} + } + DownloadStatus.Failed -> { + DownloadButton { + onClick = {} + status = details.downloaded + } } } css { alignItems = Align.center display =Display.flex - flexDirection = FlexDirection.row flexGrow = 1.0 - color = Color.white } } } diff --git a/web-app/src/main/resources/check.svg b/web-app/src/main/resources/check.svg new file mode 100644 index 00000000..65c47d51 --- /dev/null +++ b/web-app/src/main/resources/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web-app/src/main/resources/css-circular-prog-bar.css b/web-app/src/main/resources/css-circular-prog-bar.css new file mode 100644 index 00000000..f3a9bfa9 --- /dev/null +++ b/web-app/src/main/resources/css-circular-prog-bar.css @@ -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); } \ No newline at end of file diff --git a/web-app/src/main/resources/download-gradient.svg b/web-app/src/main/resources/download-gradient.svg index d74dc881..13c3ead2 100644 --- a/web-app/src/main/resources/download-gradient.svg +++ b/web-app/src/main/resources/download-gradient.svg @@ -6,8 +6,8 @@ - - + + diff --git a/web-app/src/main/resources/index.html b/web-app/src/main/resources/index.html index 56d661df..92db7273 100644 --- a/web-app/src/main/resources/index.html +++ b/web-app/src/main/resources/index.html @@ -7,10 +7,11 @@ + -
+
diff --git a/web-app/src/main/resources/styles.css b/web-app/src/main/resources/styles.css index 9ddd95ef..5f49257e 100644 --- a/web-app/src/main/resources/styles.css +++ b/web-app/src/main/resources/styles.css @@ -2,6 +2,16 @@ font-family: pristine; 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 { background-image: url("header-dark.jpg"); font-family: Lora,Helvetica Neue,Helvetica,Arial,sans-serif; @@ -20,6 +30,8 @@ body, html { } #appName{ font-family: pristine, cursive; + font-weight: 100; + text-shadow: 0.3px 0.5px #ffffff; } .headingTitle{ text-align: center; @@ -30,6 +42,42 @@ body, html { color: rgba(255, 255, 255, 1); 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 { text-decoration: none; color: rgba(255, 255, 255, 0.8); @@ -190,10 +238,4 @@ body, html { -webkit-transform: scale3D(0, 0, 1); transform: scale3D(0, 0, 1); } -} -@media screen and (max-width: 620px) { - .searchBox:hover > .searchInput { - width: 150px; - padding: 0 6px; - } } \ No newline at end of file