mirror of
				https://github.com/emptyynes/EmptyPlayer.git
				synced 2025-10-30 22:28:56 +03:00 
			
		
		
		
	iu improvements
This commit is contained in:
		
							parent
							
								
									4057af1c55
								
							
						
					
					
						commit
						fdfb0aa679
					
				
					 13 changed files with 298 additions and 64 deletions
				
			
		
							
								
								
									
										117
									
								
								.idea/codeStyles/Project.xml
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								.idea/codeStyles/Project.xml
									
										
									
										generated
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | ||||||
|  | <component name="ProjectCodeStyleConfiguration"> | ||||||
|  |   <code_scheme name="Project" version="173"> | ||||||
|  |     <codeStyleSettings language="XML"> | ||||||
|  |       <option name="FORCE_REARRANGE_MODE" value="1" /> | ||||||
|  |       <indentOptions> | ||||||
|  |         <option name="CONTINUATION_INDENT_SIZE" value="4" /> | ||||||
|  |       </indentOptions> | ||||||
|  |       <arrangement> | ||||||
|  |         <rules> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>xmlns:android</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>xmlns:.*</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |               <order>BY_NAME</order> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*:id</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*:name</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>name</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>style</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>^$</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |               <order>BY_NAME</order> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |               <order>ANDROID_ATTRIBUTE_ORDER</order> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |           <section> | ||||||
|  |             <rule> | ||||||
|  |               <match> | ||||||
|  |                 <AND> | ||||||
|  |                   <NAME>.*</NAME> | ||||||
|  |                   <XML_ATTRIBUTE /> | ||||||
|  |                   <XML_NAMESPACE>.*</XML_NAMESPACE> | ||||||
|  |                 </AND> | ||||||
|  |               </match> | ||||||
|  |               <order>BY_NAME</order> | ||||||
|  |             </rule> | ||||||
|  |           </section> | ||||||
|  |         </rules> | ||||||
|  |       </arrangement> | ||||||
|  |     </codeStyleSettings> | ||||||
|  |   </code_scheme> | ||||||
|  | </component> | ||||||
							
								
								
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
										
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
										
									
										generated
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | <component name="ProjectCodeStyleConfiguration"> | ||||||
|  |   <state> | ||||||
|  |     <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" /> | ||||||
|  |   </state> | ||||||
|  | </component> | ||||||
							
								
								
									
										8
									
								
								.idea/deploymentTargetSelector.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								.idea/deploymentTargetSelector.xml
									
										
									
										generated
									
									
									
								
							|  | @ -4,6 +4,14 @@ | ||||||
|     <selectionStates> |     <selectionStates> | ||||||
|       <SelectionState runConfigName="app"> |       <SelectionState runConfigName="app"> | ||||||
|         <option name="selectionMode" value="DROPDOWN" /> |         <option name="selectionMode" value="DROPDOWN" /> | ||||||
|  |         <DropdownSelection timestamp="2024-09-25T08:00:24.944510800Z"> | ||||||
|  |           <Target type="DEFAULT_BOOT"> | ||||||
|  |             <handle> | ||||||
|  |               <DeviceId pluginId="PhysicalDevice" identifier="serial=3128450" /> | ||||||
|  |             </handle> | ||||||
|  |           </Target> | ||||||
|  |         </DropdownSelection> | ||||||
|  |         <DialogSelection /> | ||||||
|       </SelectionState> |       </SelectionState> | ||||||
|     </selectionStates> |     </selectionStates> | ||||||
|   </component> |   </component> | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
										
									
										generated
									
									
									
								
							|  | @ -3,15 +3,19 @@ | ||||||
|     <option name="myName" value="Project Default" /> |     <option name="myName" value="Project Default" /> | ||||||
|     <inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true"> |     <inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|     <inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true"> |     <inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|     <inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true"> |     <inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|     <inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true"> |     <inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|     <inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true"> |     <inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  | @ -27,18 +31,23 @@ | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|     <inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true"> |     <inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|     <inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true"> |     <inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|     <inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true"> |     <inspection_tool class="PreviewFontScaleMustBeGreaterThanZero" enabled="true" level="ERROR" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|     <inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true"> |     <inspection_tool class="PreviewMultipleParameterProviders" enabled="true" level="ERROR" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|     <inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true"> |     <inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true"> | ||||||
|       <option name="composableFile" value="true" /> |       <option name="composableFile" value="true" /> | ||||||
|  |       <option name="previewFile" value="true" /> | ||||||
|     </inspection_tool> |     </inspection_tool> | ||||||
|   </profile> |   </profile> | ||||||
| </component> | </component> | ||||||
|  | @ -12,7 +12,7 @@ android { | ||||||
|         minSdk = 34 |         minSdk = 34 | ||||||
|         targetSdk = 34 |         targetSdk = 34 | ||||||
|         versionCode = 1 |         versionCode = 1 | ||||||
|         versionName = "1.0" |         versionName = "0.0.1α" | ||||||
| 
 | 
 | ||||||
|         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" |         testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" | ||||||
|         vectorDrawables { |         vectorDrawables { | ||||||
|  | @ -24,8 +24,7 @@ android { | ||||||
|         release { |         release { | ||||||
|             isMinifyEnabled = false |             isMinifyEnabled = false | ||||||
|             proguardFiles( |             proguardFiles( | ||||||
|                 getDefaultProguardFile("proguard-android-optimize.txt"), |                 getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" | ||||||
|                 "proguard-rules.pro" |  | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -50,6 +49,7 @@ android { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| dependencies { | dependencies { | ||||||
|  |     implementation(libs.kotlinx.serialization.json) | ||||||
|     implementation(libs.androidx.core.ktx) |     implementation(libs.androidx.core.ktx) | ||||||
|     implementation(libs.androidx.lifecycle.runtime.ktx) |     implementation(libs.androidx.lifecycle.runtime.ktx) | ||||||
|     implementation(libs.androidx.activity.compose) |     implementation(libs.androidx.activity.compose) | ||||||
|  | @ -62,11 +62,12 @@ dependencies { | ||||||
|     implementation(libs.androidx.media3.ui) |     implementation(libs.androidx.media3.ui) | ||||||
|     implementation(libs.androidx.media3.common) |     implementation(libs.androidx.media3.common) | ||||||
|     implementation(libs.androidx.media3.session) |     implementation(libs.androidx.media3.session) | ||||||
|     testImplementation(libs.junit) | 
 | ||||||
|     androidTestImplementation(libs.androidx.junit) |     androidTestImplementation(libs.androidx.junit) | ||||||
|     androidTestImplementation(libs.androidx.espresso.core) |     androidTestImplementation(libs.androidx.espresso.core) | ||||||
|     androidTestImplementation(platform(libs.androidx.compose.bom)) |     androidTestImplementation(platform(libs.androidx.compose.bom)) | ||||||
|     androidTestImplementation(libs.androidx.ui.test.junit4) |     androidTestImplementation(libs.androidx.ui.test.junit4) | ||||||
|  | 
 | ||||||
|     debugImplementation(libs.androidx.ui.tooling) |     debugImplementation(libs.androidx.ui.tooling) | ||||||
|     debugImplementation(libs.androidx.ui.test.manifest) |     debugImplementation(libs.androidx.ui.test.manifest) | ||||||
| } | } | ||||||
|  | @ -1,6 +1,8 @@ | ||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | <manifest xmlns:tools="http://schemas.android.com/tools" | ||||||
| 
 |     xmlns:android="http://schemas.android.com/apk/res/android"> | ||||||
|  |     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" | ||||||
|  |         tools:ignore="ScopedStorage" /> | ||||||
|     <application |     <application | ||||||
|         android:allowBackup="true" |         android:allowBackup="true" | ||||||
|         android:dataExtractionRules="@xml/data_extraction_rules" |         android:dataExtractionRules="@xml/data_extraction_rules" | ||||||
|  | @ -9,8 +11,7 @@ | ||||||
|         android:label="@string/app_name" |         android:label="@string/app_name" | ||||||
|         android:roundIcon="@mipmap/ic_launcher_round" |         android:roundIcon="@mipmap/ic_launcher_round" | ||||||
|         android:supportsRtl="true" |         android:supportsRtl="true" | ||||||
|         android:theme="@style/Theme.Player" |         android:theme="@style/Theme.Player"> | ||||||
|         > |  | ||||||
|         <activity |         <activity | ||||||
|             android:name=".MainActivity" |             android:name=".MainActivity" | ||||||
|             android:exported="true" |             android:exported="true" | ||||||
|  |  | ||||||
|  | @ -1,29 +1,59 @@ | ||||||
| package usr.empty.player | package usr.empty.player | ||||||
| 
 | 
 | ||||||
| import android.content.Intent | import android.content.Intent | ||||||
|  | import android.media.MediaMetadataRetriever | ||||||
|  | import android.net.Uri | ||||||
| import android.os.Bundle | import android.os.Bundle | ||||||
|  | import android.os.Environment | ||||||
|  | import android.provider.Settings | ||||||
| import android.util.Log | import android.util.Log | ||||||
| import androidx.activity.ComponentActivity | import androidx.activity.ComponentActivity | ||||||
| import androidx.activity.compose.rememberLauncherForActivityResult | import androidx.activity.compose.rememberLauncherForActivityResult | ||||||
| import androidx.activity.compose.setContent | import androidx.activity.compose.setContent | ||||||
| import androidx.activity.enableEdgeToEdge | import androidx.activity.enableEdgeToEdge | ||||||
| import androidx.activity.result.contract.ActivityResultContracts | import androidx.activity.result.contract.ActivityResultContracts | ||||||
|  | import androidx.compose.foundation.clickable | ||||||
| import androidx.compose.foundation.layout.Column | import androidx.compose.foundation.layout.Column | ||||||
| import androidx.compose.foundation.layout.fillMaxSize | import androidx.compose.foundation.layout.fillMaxSize | ||||||
| import androidx.compose.foundation.layout.padding | import androidx.compose.foundation.layout.padding | ||||||
|  | import androidx.compose.foundation.lazy.LazyColumn | ||||||
|  | import androidx.compose.foundation.lazy.items | ||||||
| import androidx.compose.material3.Button | import androidx.compose.material3.Button | ||||||
|  | import androidx.compose.material3.ButtonDefaults | ||||||
|  | import androidx.compose.material3.MaterialTheme | ||||||
| import androidx.compose.material3.Scaffold | import androidx.compose.material3.Scaffold | ||||||
| import androidx.compose.material3.Text | import androidx.compose.material3.Text | ||||||
| import androidx.compose.runtime.Composable | import androidx.compose.runtime.Composable | ||||||
|  | import androidx.compose.runtime.mutableStateListOf | ||||||
|  | import androidx.compose.runtime.remember | ||||||
| import androidx.compose.ui.Alignment | import androidx.compose.ui.Alignment | ||||||
| import androidx.compose.ui.Modifier | import androidx.compose.ui.Modifier | ||||||
|  | import androidx.compose.ui.graphics.RectangleShape | ||||||
|  | import androidx.compose.ui.tooling.preview.Preview | ||||||
|  | import androidx.compose.ui.unit.dp | ||||||
|  | import androidx.compose.ui.unit.sp | ||||||
| import usr.empty.player.ui.theme.PlayerTheme | import usr.empty.player.ui.theme.PlayerTheme | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | inline fun <T> nullifyException(block: () -> T) = try { | ||||||
|  |     block() | ||||||
|  | } catch (_: Exception) { | ||||||
|  |     null | ||||||
|  | } | ||||||
|  | 
 | ||||||
| class MainActivity : ComponentActivity() { | class MainActivity : ComponentActivity() { | ||||||
|     override fun onCreate(savedInstanceState: Bundle?) { |     override fun onCreate(savedInstanceState: Bundle?) { | ||||||
|         super.onCreate(savedInstanceState) |         super.onCreate(savedInstanceState) | ||||||
|  | 
 | ||||||
|  |         if (!Environment.isExternalStorageManager()) { | ||||||
|  |             val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) | ||||||
|  |             val uri = Uri.fromParts("package", packageName, null) | ||||||
|  |             intent.setData(uri) | ||||||
|  |             startActivity(intent) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         startService(Intent(this, PlayerService::class.java)) |         startService(Intent(this, PlayerService::class.java)) | ||||||
|  | 
 | ||||||
|         enableEdgeToEdge() |         enableEdgeToEdge() | ||||||
|         setContent { |         setContent { | ||||||
|             PlayerTheme { |             PlayerTheme { | ||||||
|  | @ -35,22 +65,74 @@ class MainActivity : ComponentActivity() { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fun uriToPath(uri: Uri): String { | ||||||
|  |     val result = uri.pathSegments!![1].replace(Regex("^primary"), "emulated/0").replace(":", "/") | ||||||
|  |     return "/storage/" + result.replace("primary:", "/storage/emulated/0/") | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @Composable | @Composable | ||||||
| fun MainLayout(modifier: Modifier = Modifier) { | fun MainLayout(modifier: Modifier = Modifier) { | ||||||
|  |     val notas = remember { mutableStateListOf<NotaDescriptor>() } | ||||||
|  | 
 | ||||||
|     val pickAudioLauncher = rememberLauncherForActivityResult( |     val pickAudioLauncher = rememberLauncherForActivityResult( | ||||||
|         ActivityResultContracts.GetContent() |         ActivityResultContracts.GetContent() | ||||||
|     ) { audioUri -> |     ) { audioUri -> | ||||||
|         audioUri?.run { |         audioUri?.run { | ||||||
|             path?.let { |             uriToPath(this).let { | ||||||
|                 Log.d("meow", it) |                 MediaMetadataRetriever().apply { | ||||||
|  |                     setDataSource(it) | ||||||
|  |                     notas.add(NotaDescriptor(name = nullifyException { | ||||||
|  |                         extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) | ||||||
|  |                     } ?: it.split('/').last().split('.').first(), artist = nullifyException { | ||||||
|  |                         extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST) | ||||||
|  |                     } ?: "Unknown Artist", sourceType = NotaDescriptor.Source.LOCAL, source = it)) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     Column(modifier.fillMaxSize()) { |     Column(modifier.fillMaxSize()) { | ||||||
|         Button(modifier = Modifier.align(Alignment.CenterHorizontally), onClick = { |         Button(shape = RectangleShape, colors = ButtonDefaults.buttonColors( | ||||||
|  |             containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.secondary | ||||||
|  |         ), modifier = Modifier.align(Alignment.CenterHorizontally), onClick = { | ||||||
|             pickAudioLauncher.launch("audio/*") |             pickAudioLauncher.launch("audio/*") | ||||||
|         }) { |         }) { | ||||||
|             Text("add track") |             Text("add track") | ||||||
|         } |         } | ||||||
|  |         NotaList(notas) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | @Composable | ||||||
|  | fun NotaList(notas: List<NotaDescriptor>, modifier: Modifier = Modifier) { | ||||||
|  |     LazyColumn( | ||||||
|  |         modifier = modifier, | ||||||
|  |     ) { | ||||||
|  |         items(notas) { nota -> | ||||||
|  |             Column(modifier = Modifier | ||||||
|  |                 .fillParentMaxWidth() | ||||||
|  |                 .clickable { } | ||||||
|  |                 .padding(4.dp) | ||||||
|  |                 .padding(start = 16.dp)) { | ||||||
|  |                 Text( | ||||||
|  |                     nota.name, fontSize = 16.sp | ||||||
|  |                 ) | ||||||
|  |                 Text( | ||||||
|  |                     nota.artist, fontSize = 12.sp | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |             Log.d("nya", nota.toString()) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @Preview | ||||||
|  | @Composable | ||||||
|  | fun Preview() { | ||||||
|  |     NotaList( | ||||||
|  |         listOf( | ||||||
|  |             NotaDescriptor(name = "hello", artist = "there", sourceType = NotaDescriptor.Source.LOCAL, source = ""), | ||||||
|  |             NotaDescriptor(name = "preview", artist = "me", sourceType = NotaDescriptor.Source.LOCAL, source = ""), | ||||||
|  |         ) | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| package usr.empty.player |  | ||||||
| 
 |  | ||||||
| interface Nota { |  | ||||||
|     fun play() |  | ||||||
|     fun pause() |  | ||||||
|     fun stop() |  | ||||||
|     fun seek() |  | ||||||
| } |  | ||||||
							
								
								
									
										16
									
								
								app/src/main/java/usr/empty/player/NotaDescriptor.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/src/main/java/usr/empty/player/NotaDescriptor.kt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | package usr.empty.player | ||||||
|  | 
 | ||||||
|  | import kotlinx.serialization.Serializable | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @Serializable | ||||||
|  | data class NotaDescriptor( | ||||||
|  |     val name: String, | ||||||
|  |     val artist: String, | ||||||
|  |     val sourceType: Source, | ||||||
|  |     val source: String, | ||||||
|  | ) { | ||||||
|  |     enum class Source { | ||||||
|  |         LOCAL | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| package usr.empty.player | package usr.empty.player | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class NotaPlayer { | class NotaPlayer { | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| package usr.empty.player | package usr.empty.player | ||||||
| 
 | 
 | ||||||
|  | import android.content.Intent | ||||||
| import android.util.Log | import android.util.Log | ||||||
| import androidx.media3.common.MediaItem | import androidx.media3.common.MediaItem | ||||||
| import androidx.media3.exoplayer.ExoPlayer | import androidx.media3.exoplayer.ExoPlayer | ||||||
|  | @ -8,19 +9,31 @@ import androidx.media3.session.MediaSessionService | ||||||
| import com.google.common.util.concurrent.Futures | import com.google.common.util.concurrent.Futures | ||||||
| import com.google.common.util.concurrent.ListenableFuture | import com.google.common.util.concurrent.ListenableFuture | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| class PlayerService : MediaSessionService() { | class PlayerService : MediaSessionService() { | ||||||
|     private var mediaSession: MediaSession? = null |     private var mediaSession: MediaSession? = null | ||||||
|     var player: ExoPlayer? = null |     var player: ExoPlayer? = null | ||||||
| 
 | 
 | ||||||
|     override fun onCreate() { |     override fun onCreate() { | ||||||
|         super.onCreate() |         super.onCreate() | ||||||
|         player = ExoPlayer.Builder(this).build() |         with(ExoPlayer.Builder(this).build()) { | ||||||
|         mediaSession = MediaSession.Builder(this, player!!) |             player = this | ||||||
|             .setCallback(MediaSessionCallback()) |             mediaSession = MediaSession.Builder(this@PlayerService, this).setCallback(MediaSessionCallback()).build() | ||||||
|             .build() |         } | ||||||
|         Log.d("meow", "memememe") |         Log.d("meow", "memememe") | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { | ||||||
|  |         intent?.run { | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |         return super.onStartCommand(intent, flags, startId) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private fun start() { | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     override fun onDestroy() { |     override fun onDestroy() { | ||||||
|         player?.release() |         player?.release() | ||||||
|         mediaSession?.release() |         mediaSession?.release() | ||||||
|  | @ -32,9 +45,7 @@ class PlayerService : MediaSessionService() { | ||||||
| 
 | 
 | ||||||
|     private inner class MediaSessionCallback : MediaSession.Callback { |     private inner class MediaSessionCallback : MediaSession.Callback { | ||||||
|         override fun onAddMediaItems( |         override fun onAddMediaItems( | ||||||
|             mediaSession: MediaSession, |             mediaSession: MediaSession, controller: MediaSession.ControllerInfo, mediaItems: MutableList<MediaItem> | ||||||
|             controller: MediaSession.ControllerInfo, |  | ||||||
|             mediaItems: MutableList<MediaItem> |  | ||||||
|         ): ListenableFuture<MutableList<MediaItem>> { |         ): ListenableFuture<MutableList<MediaItem>> { | ||||||
|             val updatedMediaItems = mediaItems.map { |             val updatedMediaItems = mediaItems.map { | ||||||
|                 it.buildUpon().setUri(it.mediaId).build() |                 it.buildUpon().setUri(it.mediaId).build() | ||||||
|  |  | ||||||
|  | @ -7,49 +7,31 @@ import androidx.compose.material3.lightColorScheme | ||||||
| import androidx.compose.runtime.Composable | import androidx.compose.runtime.Composable | ||||||
| import androidx.compose.ui.graphics.Color | import androidx.compose.ui.graphics.Color | ||||||
| 
 | 
 | ||||||
| private val DarkColorScheme = darkColorScheme( |  | ||||||
|     background = Color.Black, |  | ||||||
|     primary = Purple80, |  | ||||||
|     secondary = PurpleGrey80, |  | ||||||
|     tertiary = Pink80 |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| private val LightColorScheme = lightColorScheme( |  | ||||||
|     background = Color.White, |  | ||||||
|     primary = Purple40, |  | ||||||
|     secondary = PurpleGrey40, |  | ||||||
|     tertiary = Pink40 |  | ||||||
| 
 |  | ||||||
|     /* Other default colors to override |  | ||||||
|     background = Color(0xFFFFFBFE), |  | ||||||
|     surface = Color(0xFFFFFBFE), |  | ||||||
|     onPrimary = Color.White, |  | ||||||
|     onSecondary = Color.White, |  | ||||||
|     onTertiary = Color.White, |  | ||||||
|     onBackground = Color(0xFF1C1B1F), |  | ||||||
|     onSurface = Color(0xFF1C1B1F), |  | ||||||
|     */ |  | ||||||
| ) |  | ||||||
| 
 | 
 | ||||||
| @Composable | @Composable | ||||||
| fun PlayerTheme( | fun PlayerTheme( | ||||||
|     darkTheme: Boolean = isSystemInDarkTheme(), |     darkTheme: Boolean = isSystemInDarkTheme(), //     Dynamic color is available on Android 12+ | ||||||
|     // Dynamic color is available on Android 12+ |     dynamicColor: Boolean = true, content: @Composable () -> Unit | ||||||
| //    dynamicColor: Boolean = true, |  | ||||||
|     content: @Composable () -> Unit |  | ||||||
| ) { | ) { | ||||||
|     val colorScheme = when { |     val colorScheme = when { | ||||||
| //        dynamicColor -> { |         dynamicColor -> { | ||||||
| //            val context = LocalContext.current |             if (darkTheme) darkColorScheme( | ||||||
| //            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) |                 background = Color.Black | ||||||
| //        } |             ) else lightColorScheme( | ||||||
|         darkTheme -> DarkColorScheme |                 background = Color.White | ||||||
|         else -> LightColorScheme |             ) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         darkTheme -> darkColorScheme( | ||||||
|  |             background = Color.Black | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         else -> lightColorScheme( | ||||||
|  |             background = Color.White | ||||||
|  |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     MaterialTheme( |     MaterialTheme( | ||||||
|         colorScheme = colorScheme, |         colorScheme = colorScheme, typography = Typography, content = content | ||||||
|         typography = Typography, |  | ||||||
|         content = content |  | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
|  | @ -1,16 +1,20 @@ | ||||||
| [versions] | [versions] | ||||||
| agp = "8.6.0" | agp = "8.6.0" | ||||||
|  | core = "1.6.1" | ||||||
| kotlin = "1.9.0" | kotlin = "1.9.0" | ||||||
| coreKtx = "1.13.1" | coreKtx = "1.13.1" | ||||||
| junit = "4.13.2" | junit = "4.13.2" | ||||||
| junitVersion = "1.2.1" | junitVersion = "1.2.1" | ||||||
| espressoCore = "3.6.1" | espressoCore = "3.6.1" | ||||||
|  | kotlinxSerializationJson = "1.7.1" | ||||||
| lifecycleRuntimeKtx = "2.6.1" | lifecycleRuntimeKtx = "2.6.1" | ||||||
| activityCompose = "1.9.2" | activityCompose = "1.9.2" | ||||||
| composeBom = "2024.04.01" | composeBom = "2024.04.01" | ||||||
| media3Exoplayer = "1.4.1" | media3Exoplayer = "1.4.1" | ||||||
|  | junitJupiter = "5.8.1" | ||||||
| 
 | 
 | ||||||
| [libraries] | [libraries] | ||||||
|  | androidx-core = { module = "androidx.test:core", version.ref = "core" } | ||||||
| androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } | androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } | ||||||
| androidx-media3-common = { module = "androidx.media3:media3-common", version.ref = "media3Exoplayer" } | androidx-media3-common = { module = "androidx.media3:media3-common", version.ref = "media3Exoplayer" } | ||||||
| androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3Exoplayer" } | androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3Exoplayer" } | ||||||
|  | @ -29,6 +33,11 @@ androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-toolin | ||||||
| androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } | androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } | ||||||
| androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } | androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } | ||||||
| androidx-material3 = { group = "androidx.compose.material3", name = "material3" } | androidx-material3 = { group = "androidx.compose.material3", name = "material3" } | ||||||
|  | kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } | ||||||
|  | junit-jupiter = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junitJupiter" } | ||||||
|  | mockito-core = { module = "org.mockito:mockito-core", version = "5.10.0" } | ||||||
|  | mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version = "5.4.0" } | ||||||
|  | mockk = { module = "io.mockk:mockk", version = "1.13.10" } | ||||||
| 
 | 
 | ||||||
| [plugins] | [plugins] | ||||||
| android-application = { id = "com.android.application", version.ref = "agp" } | android-application = { id = "com.android.application", version.ref = "agp" } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue