basic ui mock-up
This commit is contained in:
		@ -53,6 +53,7 @@ dependencies {
 | 
			
		||||
    implementation 'com.google.android.material:material:1.4.0'
 | 
			
		||||
    implementation "androidx.compose.ui:ui:$compose_version"
 | 
			
		||||
    implementation "androidx.compose.material:material:$compose_version"
 | 
			
		||||
    implementation "androidx.compose.material:material-icons-extended:$compose_version"
 | 
			
		||||
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
 | 
			
		||||
    implementation "androidx.navigation:navigation-compose:$nav_compose_version"
 | 
			
		||||
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,8 @@
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    package="net.blumia.pcmdroid">
 | 
			
		||||
 | 
			
		||||
    <uses-permission android:name="android.permission.INTERNET"/>
 | 
			
		||||
 | 
			
		||||
    <application
 | 
			
		||||
        android:allowBackup="true"
 | 
			
		||||
        android:icon="@mipmap/ic_launcher"
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@ package net.blumia.pcmdroid
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import androidx.activity.ComponentActivity
 | 
			
		||||
import androidx.activity.compose.setContent
 | 
			
		||||
import androidx.activity.viewModels
 | 
			
		||||
import androidx.compose.material.MaterialTheme
 | 
			
		||||
import androidx.compose.material.Surface
 | 
			
		||||
import androidx.compose.material.Text
 | 
			
		||||
@ -13,28 +14,18 @@ import net.blumia.pcmdroid.ui.screen.main.MainPlayer
 | 
			
		||||
import net.blumia.pcmdroid.ui.theme.PrivateCloudMusicTheme
 | 
			
		||||
 | 
			
		||||
class MainActivity : ComponentActivity() {
 | 
			
		||||
 | 
			
		||||
    private val model: MainViewModel by viewModels()
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
        setContent {
 | 
			
		||||
            PrivateCloudMusicTheme {
 | 
			
		||||
                // A surface container using the 'background' color from the theme
 | 
			
		||||
                Surface(color = MaterialTheme.colors.background) {
 | 
			
		||||
                    NavGraph()
 | 
			
		||||
                    NavGraph(model)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun Greeting(name: String) {
 | 
			
		||||
    Text(text = "Hello $name!")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview(showBackground = true)
 | 
			
		||||
@Composable
 | 
			
		||||
fun DefaultPreview() {
 | 
			
		||||
    PrivateCloudMusicTheme {
 | 
			
		||||
        Greeting("Android")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										63
									
								
								app/src/main/java/net/blumia/pcmdroid/MainViewModel.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								app/src/main/java/net/blumia/pcmdroid/MainViewModel.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
package net.blumia.pcmdroid
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import androidx.lifecycle.LiveData
 | 
			
		||||
import androidx.lifecycle.MutableLiveData
 | 
			
		||||
import androidx.lifecycle.ViewModel
 | 
			
		||||
import net.blumia.pcmdroid.model.Folder
 | 
			
		||||
import net.blumia.pcmdroid.model.Server
 | 
			
		||||
import net.blumia.pcmdroid.model.Song
 | 
			
		||||
 | 
			
		||||
class MainViewModel : ViewModel() {
 | 
			
		||||
 | 
			
		||||
    val servers: LiveData<List<Server>> = MutableLiveData<List<Server>>(
 | 
			
		||||
        listOf(
 | 
			
		||||
            Server(
 | 
			
		||||
                url = Uri.parse("https://localhost/api.php"),
 | 
			
		||||
                name = "PCM",
 | 
			
		||||
                baseFolderName = "pcm",
 | 
			
		||||
            ),
 | 
			
		||||
            Server(
 | 
			
		||||
                url = Uri.parse("https://localhost/api.php"),
 | 
			
		||||
                name = "PCM2",
 | 
			
		||||
                baseFolderName = "pcm2",
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    val currentPath: LiveData<String> = MutableLiveData("")
 | 
			
		||||
 | 
			
		||||
    val drawerFolders: LiveData<List<Folder>> = MutableLiveData(
 | 
			
		||||
        listOf(
 | 
			
		||||
            Folder("Test/"),
 | 
			
		||||
            Folder("Folder/")
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    val folders: LiveData<List<Folder>> = MutableLiveData(
 | 
			
		||||
        listOf(
 | 
			
		||||
            Folder("Test/Converted-Modules/")
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    val songs: LiveData<List<Song>> = MutableLiveData(
 | 
			
		||||
        listOf(
 | 
			
		||||
            Song(
 | 
			
		||||
                filePath = "Test/Rick Astley - Never Gonna Give You Up.mp3",
 | 
			
		||||
                url = Uri.parse("http://localhost/rickroll.mp3")
 | 
			
		||||
            ),
 | 
			
		||||
            Song(
 | 
			
		||||
                filePath = "Test/哇 好东西一堆.xm",
 | 
			
		||||
                url = Uri.parse("http://localhost/rickroll.mp3")
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    fun fetchServer(srv: Server) {
 | 
			
		||||
        //
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun fetchFolder(folder: Folder) {
 | 
			
		||||
        //
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -6,4 +6,4 @@ data class Server (
 | 
			
		||||
    val url: Uri,
 | 
			
		||||
    val name: String,
 | 
			
		||||
    val baseFolderName: String,
 | 
			
		||||
)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								app/src/main/java/net/blumia/pcmdroid/model/Song.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/src/main/java/net/blumia/pcmdroid/model/Song.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
package net.blumia.pcmdroid.model
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
 | 
			
		||||
data class Song (
 | 
			
		||||
    val filePath: String, // with file name
 | 
			
		||||
    val modifiedTime: Int = 0,
 | 
			
		||||
    val fileSize: Int = 0,
 | 
			
		||||
    val additionalInfo: Boolean = false, // if sidecar meta-info json file exist.
 | 
			
		||||
    val url: Uri,
 | 
			
		||||
) {
 | 
			
		||||
    fun displayName(): String {
 | 
			
		||||
        return Uri.parse(filePath).lastPathSegment ?: "???"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
data class Folder (
 | 
			
		||||
    val folderPath: String,
 | 
			
		||||
) {
 | 
			
		||||
    fun displayName(): String {
 | 
			
		||||
        return Uri.parse(folderPath).lastPathSegment ?: "???"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,4 @@
 | 
			
		||||
package net.blumia.pcmdroid.repository
 | 
			
		||||
 | 
			
		||||
class ServerRepository {
 | 
			
		||||
}
 | 
			
		||||
@ -1,11 +1,11 @@
 | 
			
		||||
package net.blumia.pcmdroid.ui
 | 
			
		||||
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.navigation.NavHostController
 | 
			
		||||
import androidx.navigation.compose.NavHost
 | 
			
		||||
import androidx.navigation.compose.composable
 | 
			
		||||
import androidx.navigation.compose.rememberNavController
 | 
			
		||||
import net.blumia.pcmdroid.MainViewModel
 | 
			
		||||
import net.blumia.pcmdroid.ui.screen.addserver.AddServerScreen
 | 
			
		||||
import net.blumia.pcmdroid.ui.screen.main.MainPlayer
 | 
			
		||||
import net.blumia.pcmdroid.ui.screen.settings.SettingsScreen
 | 
			
		||||
@ -18,6 +18,7 @@ object MainDestinations {
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun NavGraph(
 | 
			
		||||
    viewModel: MainViewModel,
 | 
			
		||||
    navController: NavHostController = rememberNavController(),
 | 
			
		||||
    startDestination: String = MainDestinations.MAIN_ROUTE,
 | 
			
		||||
) {
 | 
			
		||||
@ -27,6 +28,7 @@ fun NavGraph(
 | 
			
		||||
    ) {
 | 
			
		||||
        composable(MainDestinations.MAIN_ROUTE) {
 | 
			
		||||
            MainPlayer(
 | 
			
		||||
                viewModel = viewModel,
 | 
			
		||||
                addServerActionTriggered = {
 | 
			
		||||
                    navController.navigate(MainDestinations.ADD_SERVER_ROUTE)
 | 
			
		||||
                },
 | 
			
		||||
 | 
			
		||||
@ -1,50 +1,72 @@
 | 
			
		||||
package net.blumia.pcmdroid.ui.screen.main
 | 
			
		||||
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import androidx.compose.foundation.Image
 | 
			
		||||
import androidx.compose.foundation.clickable
 | 
			
		||||
import androidx.compose.foundation.gestures.scrollable
 | 
			
		||||
import androidx.compose.foundation.horizontalScroll
 | 
			
		||||
import androidx.compose.foundation.layout.*
 | 
			
		||||
import androidx.compose.foundation.rememberScrollState
 | 
			
		||||
import androidx.compose.material.*
 | 
			
		||||
import androidx.compose.material.icons.Icons
 | 
			
		||||
import androidx.compose.material.icons.filled.*
 | 
			
		||||
import androidx.compose.material.icons.rounded.FeaturedPlayList
 | 
			
		||||
import androidx.compose.material.icons.rounded.PlayArrow
 | 
			
		||||
import androidx.compose.material.icons.rounded.PlayCircle
 | 
			
		||||
import androidx.compose.material.icons.rounded.PlayCircleOutline
 | 
			
		||||
import androidx.compose.runtime.*
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.graphics.vector.ImageVector
 | 
			
		||||
import androidx.compose.ui.layout.VerticalAlignmentLine
 | 
			
		||||
import androidx.compose.ui.res.painterResource
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
import net.blumia.pcmdroid.MainViewModel
 | 
			
		||||
import net.blumia.pcmdroid.R
 | 
			
		||||
import net.blumia.pcmdroid.model.Folder
 | 
			
		||||
import net.blumia.pcmdroid.model.Server
 | 
			
		||||
import net.blumia.pcmdroid.model.Song
 | 
			
		||||
 | 
			
		||||
@Preview(showBackground = true)
 | 
			
		||||
@OptIn(ExperimentalMaterialApi::class)
 | 
			
		||||
@Composable
 | 
			
		||||
fun NowPlaying() {
 | 
			
		||||
    Row(
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = Modifier
 | 
			
		||||
            .fillMaxWidth()
 | 
			
		||||
            .height(56.dp),
 | 
			
		||||
        verticalAlignment = Alignment.CenterVertically,
 | 
			
		||||
            .fillMaxWidth(),
 | 
			
		||||
    ) {
 | 
			
		||||
        Image(
 | 
			
		||||
            painter = painterResource(id = R.drawable.ic_launcher_background),
 | 
			
		||||
            contentDescription = "Album cover",
 | 
			
		||||
        LinearProgressIndicator(
 | 
			
		||||
            modifier = Modifier.fillMaxWidth(),
 | 
			
		||||
            progress = 0f,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        ListItem(
 | 
			
		||||
            text = {
 | 
			
		||||
                Text(
 | 
			
		||||
                    text = "Not playing at all.",
 | 
			
		||||
                )
 | 
			
		||||
            },
 | 
			
		||||
            trailing = {
 | 
			
		||||
                IconButton(onClick = { /*TODO*/ }) {
 | 
			
		||||
                    Icon(imageVector = Icons.Rounded.PlayArrow, contentDescription = "Menu")
 | 
			
		||||
        Row(
 | 
			
		||||
            modifier = Modifier
 | 
			
		||||
                .fillMaxWidth()
 | 
			
		||||
                .height(56.dp),
 | 
			
		||||
            verticalAlignment = Alignment.CenterVertically,
 | 
			
		||||
        ) {
 | 
			
		||||
            Image(
 | 
			
		||||
                painter = painterResource(id = R.drawable.ic_launcher_background),
 | 
			
		||||
                contentDescription = "Album cover",
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            ListItem(
 | 
			
		||||
                text = {
 | 
			
		||||
                    Text(
 | 
			
		||||
                        text = "Not playing at all.",
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
                trailing = {
 | 
			
		||||
                    IconButton(onClick = { /*TODO*/ }) {
 | 
			
		||||
                        Icon(imageVector = Icons.Rounded.PlayCircleOutline, contentDescription = "Menu")
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -52,32 +74,34 @@ fun NowPlaying() {
 | 
			
		||||
@OptIn(ExperimentalMaterialApi::class)
 | 
			
		||||
@Composable
 | 
			
		||||
fun DrawerContent(
 | 
			
		||||
    viewModel: MainViewModel = MainViewModel(),
 | 
			
		||||
    addServerActionTriggered: () -> Unit = {},
 | 
			
		||||
    settingsActionTriggered: () -> Unit = {},
 | 
			
		||||
) {
 | 
			
		||||
    Row(modifier = Modifier.fillMaxSize()) {
 | 
			
		||||
        var selectedItem by remember { mutableStateOf<Int?>(null) }
 | 
			
		||||
        val items = listOf<String>()
 | 
			
		||||
        val icons = listOf<ImageVector>()
 | 
			
		||||
        var selectedItem by remember { mutableStateOf<Int?>(0) }
 | 
			
		||||
        val servers = viewModel.servers.value
 | 
			
		||||
        NavigationRail {
 | 
			
		||||
            items.forEachIndexed { index, item ->
 | 
			
		||||
            servers?.forEachIndexed { index, server ->
 | 
			
		||||
                NavigationRailItem(
 | 
			
		||||
                    icon = {
 | 
			
		||||
                        Icon(
 | 
			
		||||
                            icons[index], item
 | 
			
		||||
                            Icons.Filled.LibraryMusic, server.name
 | 
			
		||||
                        )
 | 
			
		||||
                    },
 | 
			
		||||
                    label = {
 | 
			
		||||
                        Text(item)
 | 
			
		||||
                        Text(server.name)
 | 
			
		||||
                    },
 | 
			
		||||
                    selected = selectedItem == index,
 | 
			
		||||
                    onClick = { /*TODO*/ }
 | 
			
		||||
                    onClick = {
 | 
			
		||||
                        viewModel.fetchServer(server)
 | 
			
		||||
                    }
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            NavigationRailItem(
 | 
			
		||||
                icon = { Icon(Icons.Filled.AddCircle, null) },
 | 
			
		||||
                label = { Text("Add") },
 | 
			
		||||
                label = { Text(stringResource(id = R.string.add)) },
 | 
			
		||||
                selected = false,
 | 
			
		||||
                onClick = addServerActionTriggered,
 | 
			
		||||
            )
 | 
			
		||||
@ -86,7 +110,7 @@ fun DrawerContent(
 | 
			
		||||
 | 
			
		||||
            NavigationRailItem(
 | 
			
		||||
                icon = { Icon(Icons.Filled.Settings, null) },
 | 
			
		||||
                label = { Text("Settings") },
 | 
			
		||||
                label = { Text(stringResource(id = R.string.settings)) },
 | 
			
		||||
                selected = false,
 | 
			
		||||
                onClick = settingsActionTriggered,
 | 
			
		||||
            )
 | 
			
		||||
@ -108,13 +132,30 @@ fun DrawerContent(
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            Divider()
 | 
			
		||||
 | 
			
		||||
            val drawerFolders = viewModel.drawerFolders.value
 | 
			
		||||
            drawerFolders?.forEach { folder ->
 | 
			
		||||
                ListItem(
 | 
			
		||||
                    modifier = Modifier.clickable{
 | 
			
		||||
                        viewModel.fetchFolder(folder)
 | 
			
		||||
                    },
 | 
			
		||||
                    text = {
 | 
			
		||||
                        Text(
 | 
			
		||||
                            text = folder.displayName(),
 | 
			
		||||
                            style = MaterialTheme.typography.subtitle1
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview(showBackground = true)
 | 
			
		||||
@OptIn(ExperimentalMaterialApi::class)
 | 
			
		||||
@Composable
 | 
			
		||||
fun MainPlayer(
 | 
			
		||||
    viewModel: MainViewModel = MainViewModel(),
 | 
			
		||||
    addServerActionTriggered: () -> Unit = {},
 | 
			
		||||
    settingsActionTriggered: () -> Unit = {},
 | 
			
		||||
) {
 | 
			
		||||
@ -124,6 +165,7 @@ fun MainPlayer(
 | 
			
		||||
        drawerState = drawerState,
 | 
			
		||||
        drawerContent = {
 | 
			
		||||
            DrawerContent(
 | 
			
		||||
                viewModel = viewModel,
 | 
			
		||||
                addServerActionTriggered = addServerActionTriggered,
 | 
			
		||||
                settingsActionTriggered = settingsActionTriggered,
 | 
			
		||||
            )
 | 
			
		||||
@ -132,7 +174,7 @@ fun MainPlayer(
 | 
			
		||||
        Scaffold(
 | 
			
		||||
            topBar = {
 | 
			
		||||
                TopAppBar(
 | 
			
		||||
                    title = { Text("Private Cloud Music") },
 | 
			
		||||
                    title = { Text(stringResource(id = R.string.app_name)) },
 | 
			
		||||
                    navigationIcon = {
 | 
			
		||||
                        IconButton(onClick = {
 | 
			
		||||
                            drawerScope.launch {
 | 
			
		||||
@ -154,7 +196,68 @@ fun MainPlayer(
 | 
			
		||||
                modifier = Modifier.fillMaxSize()
 | 
			
		||||
            ) {
 | 
			
		||||
                Column(modifier = Modifier.weight(1f, fill = true)) {
 | 
			
		||||
                    //
 | 
			
		||||
 | 
			
		||||
                    val iconLeftPadding = 16.dp
 | 
			
		||||
                    val iconVerticalPadding = 12.dp
 | 
			
		||||
                    Row(
 | 
			
		||||
                        modifier = Modifier
 | 
			
		||||
                            .fillMaxWidth()
 | 
			
		||||
                            .horizontalScroll(rememberScrollState())
 | 
			
		||||
                            .padding(
 | 
			
		||||
                                horizontal = iconLeftPadding,
 | 
			
		||||
                                vertical = iconVerticalPadding,
 | 
			
		||||
                            ),
 | 
			
		||||
                        verticalAlignment = Alignment.CenterVertically,
 | 
			
		||||
                    ) {
 | 
			
		||||
                        val pathSeg = listOf("Deep", "Dark", "Folder")
 | 
			
		||||
                        pathSeg.forEach { seg ->
 | 
			
		||||
                            val isLastSeg = seg == pathSeg.last()
 | 
			
		||||
 | 
			
		||||
                            Text(
 | 
			
		||||
                                text = seg,
 | 
			
		||||
                                style = MaterialTheme.typography.body1,
 | 
			
		||||
                                color = if (isLastSeg) MaterialTheme.colors.primary else MaterialTheme.colors.onSurface
 | 
			
		||||
                            )
 | 
			
		||||
 | 
			
		||||
                            if (!isLastSeg) {
 | 
			
		||||
                                Icon(
 | 
			
		||||
                                    modifier = Modifier.padding(horizontal = 5.dp),
 | 
			
		||||
                                    imageVector = Icons.Filled.NavigateNext,
 | 
			
		||||
                                    contentDescription = null,
 | 
			
		||||
                                )
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    viewModel.folders.value?.forEach { folder ->
 | 
			
		||||
                        ListItem(
 | 
			
		||||
                            modifier = Modifier.clickable {  },
 | 
			
		||||
                            icon = {
 | 
			
		||||
                                Icon(
 | 
			
		||||
                                    imageVector = Icons.Filled.FolderOpen,
 | 
			
		||||
                                    contentDescription = null,
 | 
			
		||||
                                )
 | 
			
		||||
                            },
 | 
			
		||||
                            text = {
 | 
			
		||||
                                Text(folder.displayName())
 | 
			
		||||
                            }
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    viewModel.songs.value?.forEach { song ->
 | 
			
		||||
                        ListItem(
 | 
			
		||||
                            modifier = Modifier.clickable {  },
 | 
			
		||||
                            icon = {
 | 
			
		||||
                                Icon(
 | 
			
		||||
                                    imageVector = Icons.Filled.MusicNote,
 | 
			
		||||
                                    contentDescription = null
 | 
			
		||||
                                )
 | 
			
		||||
                            },
 | 
			
		||||
                            text = {
 | 
			
		||||
                                Text(song.displayName())
 | 
			
		||||
                            }
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                NowPlaying()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								app/src/main/res/values-zh/strings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/src/main/res/values-zh/strings.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
<resources>
 | 
			
		||||
    <string name="app_name">私有云音乐</string>
 | 
			
		||||
    <string name="settings">设置</string>
 | 
			
		||||
    <string name="add">添加</string>
 | 
			
		||||
</resources>
 | 
			
		||||
@ -1,3 +1,5 @@
 | 
			
		||||
<resources>
 | 
			
		||||
    <string name="app_name">Private Cloud Music</string>
 | 
			
		||||
    <string name="settings">Settings</string>
 | 
			
		||||
    <string name="add">Add</string>
 | 
			
		||||
</resources>
 | 
			
		||||
		Reference in New Issue
	
	Block a user