mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-22 09:04:32 +01:00
Style Fixes on Small Screens
This commit is contained in:
parent
a47d9f52a0
commit
90b99cbb51
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(","))
|
||||||
|
@ -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)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
|
@ -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){
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
web-app/src/main/kotlin/list/CircularProgressBar.kt
Normal file
38
web-app/src/main/kotlin/list/CircularProgressBar.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
web-app/src/main/kotlin/list/DownloadButton.kt
Normal file
49
web-app/src/main/kotlin/list/DownloadButton.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
29
web-app/src/main/kotlin/list/LoadingSpinner.kt
Normal file
29
web-app/src/main/kotlin/list/LoadingSpinner.kt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
web-app/src/main/resources/check.svg
Normal file
1
web-app/src/main/resources/check.svg
Normal 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 |
168
web-app/src/main/resources/css-circular-prog-bar.css
Normal file
168
web-app/src/main/resources/css-circular-prog-bar.css
Normal 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); }
|
@ -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 |
1
web-app/src/main/resources/error.svg
Normal file
1
web-app/src/main/resources/error.svg
Normal 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 |
@ -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>
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user