├── .editorconfig ├── .gitignore ├── .vscode └── extensions.json ├── App_Resources ├── Android │ ├── app.gradle │ ├── before-plugins.gradle │ ├── gradle.properties │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── sinasamaki │ │ │ └── dynamicisland │ │ │ ├── App.kt │ │ │ ├── IslandView.kt │ │ │ ├── RadioButtonRow.kt │ │ │ ├── island │ │ │ ├── CallWaveform.kt │ │ │ ├── DynamicIsland.kt │ │ │ ├── FaceUnlock.kt │ │ │ ├── IslandBubbleContent.kt │ │ │ ├── IslandContent.kt │ │ │ ├── IslandState.kt │ │ │ ├── LeadingContent.kt │ │ │ └── TrailingContent.kt │ │ │ ├── metaball │ │ │ ├── MetaContainter.kt │ │ │ ├── MetaEntity.kt │ │ │ └── Modifiers.kt │ │ │ └── ui │ │ │ └── theme │ │ │ ├── Color.kt │ │ │ ├── Shape.kt │ │ │ ├── Theme.kt │ │ │ └── Type.kt │ │ └── res │ │ ├── drawable-hdpi │ │ ├── background.png │ │ └── logo.png │ │ ├── drawable-ldpi │ │ ├── background.png │ │ └── logo.png │ │ ├── drawable-mdpi │ │ ├── background.png │ │ └── logo.png │ │ ├── drawable-nodpi │ │ └── splash_screen.xml │ │ ├── drawable-xhdpi │ │ ├── background.png │ │ └── logo.png │ │ ├── drawable-xxhdpi │ │ ├── background.png │ │ └── logo.png │ │ ├── drawable-xxxhdpi │ │ ├── background.png │ │ └── logo.png │ │ ├── drawable │ │ ├── ic_launcher_foreground.xml │ │ └── timer.xml │ │ ├── mipmap-anydpi-v26 │ │ └── ic_launcher.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ ├── colors.xml │ │ └── styles.xml │ │ ├── values-v29 │ │ └── styles.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml └── iOS │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icon-1024.png │ │ ├── icon-20.png │ │ ├── icon-20@2x.png │ │ ├── icon-20@3x.png │ │ ├── icon-29.png │ │ ├── icon-29@2x.png │ │ ├── icon-29@3x.png │ │ ├── icon-40.png │ │ ├── icon-40@2x.png │ │ ├── icon-40@3x.png │ │ ├── icon-60@2x.png │ │ ├── icon-60@3x.png │ │ ├── icon-76.png │ │ ├── icon-76@2x.png │ │ └── icon-83.5@2x.png │ ├── Contents.json │ ├── LaunchScreen.AspectFill.imageset │ │ ├── Contents.json │ │ ├── LaunchScreen-AspectFill.png │ │ ├── LaunchScreen-AspectFill@2x.png │ │ └── LaunchScreen-AspectFill@3x.png │ └── LaunchScreen.Center.imageset │ │ ├── Contents.json │ │ ├── LaunchScreen-Center.png │ │ ├── LaunchScreen-Center@2x.png │ │ └── LaunchScreen-Center@3x.png │ ├── Info.plist │ ├── LaunchScreen.storyboard │ └── build.xcconfig ├── README.md ├── nativescript.config.ts ├── package-lock.json ├── package.json ├── references.d.ts ├── src ├── app.css ├── app │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ts │ ├── home.component.html │ └── home.component.ts ├── main.ts └── polyfills.ts ├── tailwind.config.js ├── tsconfig.json └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | 9 | [*.json] 10 | indent_style = space 11 | indent_size = 2 12 | 13 | [*.js] 14 | indent_style = space 15 | indent_size = 2 16 | 17 | [*.ts] 18 | indent_style = space 19 | indent_size = 2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # NativeScript 2 | hooks/ 3 | node_modules/ 4 | platforms/ 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | 13 | # General 14 | .DS_Store 15 | .AppleDouble 16 | .LSOverride 17 | .idea 18 | .cloud 19 | .project 20 | tmp/ 21 | typings/ 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["nativescript.nativescript"] 3 | } 4 | -------------------------------------------------------------------------------- /App_Resources/Android/app.gradle: -------------------------------------------------------------------------------- 1 | repositories { 2 | mavenCentral() 3 | } 4 | 5 | dependencies { 6 | implementation 'androidx.core:core-ktx:1.8.0' 7 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' 8 | implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1' 9 | implementation 'androidx.activity:activity-compose:1.5.1' 10 | implementation 'androidx.compose.ui:ui:$compose_ui_version' 11 | implementation 'androidx.compose.material:material:1.2.1' 12 | } 13 | 14 | android { 15 | compileSdkVersion 33 16 | buildToolsVersion '33.0.0' 17 | // ndkVersion '' 18 | 19 | defaultConfig { 20 | minSdkVersion 33 21 | targetSdkVersion 33 22 | 23 | // Version Information 24 | versionCode 1 25 | versionName '1.0.0' 26 | 27 | generatedDensities = [] 28 | 29 | // vectorDrawables { 30 | // useSupportLibrary true 31 | // } 32 | } 33 | 34 | aaptOptions { 35 | additionalParameters '--no-version-vectors' 36 | } 37 | 38 | compileOptions { 39 | sourceCompatibility JavaVersion.VERSION_1_8 40 | targetCompatibility JavaVersion.VERSION_1_8 41 | } 42 | kotlinOptions { 43 | jvmTarget = '1.8' 44 | } 45 | buildFeatures { 46 | compose true 47 | } 48 | composeOptions { 49 | kotlinCompilerExtensionVersion '1.3.2' 50 | } 51 | packagingOptions { 52 | resources { 53 | excludes += '/META-INF/{AL2.0,LGPL2.1}' 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /App_Resources/Android/before-plugins.gradle: -------------------------------------------------------------------------------- 1 | // this configurations is loaded before building plugins, as well as before building 2 | // the app - this is where you can apply global settings and overrides 3 | 4 | project.ext { 5 | // androidXAppCompat = "1.4.1" 6 | // androidXExifInterface = "1.3.3" 7 | // androidXFragment = "1.4.1" 8 | // androidXMaterial = "1.5.0" 9 | // androidXMultidex = "2.0.1" 10 | // androidXTransition = "1.4.1" 11 | // androidXViewPager = "1.0.0" 12 | 13 | // useKotlin = true 14 | // kotlinVersion = "1.6.0" 15 | 16 | compose_ui_version = '1.2.1' 17 | } 18 | -------------------------------------------------------------------------------- /App_Resources/Android/gradle.properties: -------------------------------------------------------------------------------- 1 | useKotlin=true 2 | kotlinVersion=1.7.20 -------------------------------------------------------------------------------- /App_Resources/Android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/App.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland 2 | 3 | import androidx.compose.foundation.layout.Column 4 | import androidx.compose.foundation.layout.padding 5 | import androidx.compose.foundation.layout.size 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.runtime.getValue 8 | import androidx.compose.runtime.mutableStateOf 9 | import androidx.compose.runtime.remember 10 | import androidx.compose.runtime.setValue 11 | import androidx.compose.ui.Modifier 12 | import androidx.compose.ui.graphics.Canvas 13 | import androidx.compose.ui.graphics.Color 14 | import androidx.compose.ui.unit.dp 15 | import com.sinasamaki.dynamicisland.island.DynamicIsland 16 | import com.sinasamaki.dynamicisland.island.IslandState 17 | 18 | @Composable 19 | fun App() { 20 | Column { 21 | var islandState: IslandState by remember { mutableStateOf(IslandState.DefaultState()) } 22 | 23 | DynamicIsland(islandState = islandState) 24 | 25 | RadioButtonRow( 26 | text = "Default", 27 | selected = islandState is IslandState.DefaultState 28 | ) { 29 | islandState = IslandState.DefaultState() 30 | } 31 | 32 | RadioButtonRow( 33 | text = "Call state", 34 | selected = islandState is IslandState.CallState 35 | ) { 36 | islandState = IslandState.CallState() 37 | } 38 | 39 | RadioButtonRow( 40 | text = "Call Timer state", 41 | selected = islandState is IslandState.CallTimerState 42 | ) { 43 | islandState = IslandState.CallTimerState() 44 | } 45 | 46 | RadioButtonRow( 47 | text = "Face unlock state", 48 | selected = islandState is IslandState.FaceUnlockState 49 | ) { 50 | islandState = IslandState.FaceUnlockState() 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/IslandView.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland 2 | 3 | import android.os.Bundle 4 | import android.content.Context 5 | import androidx.compose.material.MaterialTheme 6 | import androidx.compose.material.Text 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.runtime.getValue 9 | import androidx.compose.runtime.mutableStateOf 10 | import androidx.compose.runtime.setValue 11 | import androidx.compose.ui.platform.ComposeView 12 | import androidx.lifecycle.ViewModel 13 | import androidx.lifecycle.viewmodel.compose.viewModel 14 | import androidx.activity.ComponentActivity 15 | import androidx.activity.compose.setContent 16 | import androidx.compose.foundation.layout.fillMaxSize 17 | import androidx.compose.material.Surface 18 | import androidx.compose.ui.Modifier 19 | import com.sinasamaki.dynamicisland.ui.theme.DynamicIslandTheme 20 | 21 | class IslandView { 22 | fun generateComposeView(view: ComposeView): ComposeView { 23 | return view.apply { 24 | setContent { 25 | DynamicIslandTheme { 26 | Surface( 27 | modifier = Modifier.fillMaxSize(), 28 | color = MaterialTheme.colors.background 29 | ) { 30 | App() 31 | } 32 | } 33 | } 34 | } 35 | } 36 | 37 | fun updateData(value: Map) { 38 | } 39 | var onEvent: ((String) -> Unit)? = null 40 | 41 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/RadioButtonRow.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland 2 | 3 | import androidx.compose.foundation.clickable 4 | import androidx.compose.foundation.layout.Row 5 | import androidx.compose.foundation.layout.fillMaxWidth 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.material.MaterialTheme 9 | import androidx.compose.material.RadioButton 10 | import androidx.compose.material.RadioButtonDefaults 11 | import androidx.compose.material.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Alignment 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.unit.dp 16 | 17 | @Composable 18 | fun RadioButtonRow( 19 | modifier: Modifier = Modifier, 20 | text: String, 21 | selected: Boolean, 22 | onSelected: () -> Unit 23 | ) { 24 | 25 | Row( 26 | modifier = modifier 27 | .height(48.dp) 28 | .fillMaxWidth() 29 | .clickable { 30 | onSelected() 31 | } 32 | .padding(horizontal = 16.dp), 33 | verticalAlignment = Alignment.CenterVertically 34 | ) { 35 | 36 | RadioButton( 37 | selected = selected, 38 | onClick = null, 39 | colors = RadioButtonDefaults.colors( 40 | selectedColor = MaterialTheme.colors.onSurface 41 | ) 42 | ) 43 | 44 | Text(text) 45 | 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/island/CallWaveform.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.island 2 | 3 | import androidx.compose.animation.core.Animatable 4 | import androidx.compose.animation.core.Spring 5 | import androidx.compose.animation.core.spring 6 | import androidx.compose.foundation.background 7 | import androidx.compose.foundation.layout.Box 8 | import androidx.compose.foundation.layout.Row 9 | import androidx.compose.foundation.layout.fillMaxHeight 10 | import androidx.compose.foundation.layout.fillMaxSize 11 | import androidx.compose.foundation.layout.padding 12 | import androidx.compose.foundation.layout.width 13 | import androidx.compose.foundation.shape.RoundedCornerShape 14 | import androidx.compose.runtime.Composable 15 | import androidx.compose.runtime.LaunchedEffect 16 | import androidx.compose.runtime.remember 17 | import androidx.compose.ui.Alignment 18 | import androidx.compose.ui.Modifier 19 | import androidx.compose.ui.graphics.Color 20 | import androidx.compose.ui.unit.dp 21 | import com.sinasamaki.dynamicisland.ui.theme.Green 22 | import com.sinasamaki.dynamicisland.ui.theme.Orange 23 | import com.sinasamaki.dynamicisland.ui.theme.White 24 | import kotlin.random.Random 25 | 26 | @Composable 27 | fun CallWaveform() { 28 | Box( 29 | modifier = Modifier 30 | .padding(12.dp) 31 | .fillMaxSize() 32 | ) { 33 | Waveform(color = Green) 34 | Waveform(color = Orange) 35 | Waveform(color = White, limit = .7f) 36 | } 37 | } 38 | 39 | @Composable 40 | fun Waveform( 41 | color: Color, 42 | limit: Float = 1f, 43 | ) { 44 | Row( 45 | modifier = Modifier.fillMaxSize(), 46 | verticalAlignment = Alignment.CenterVertically, 47 | ) { 48 | for (i in 0..4) { 49 | val height = remember { Animatable(0f) } 50 | 51 | LaunchedEffect(Unit) { 52 | while (true) { 53 | height.animateTo( 54 | Random.nextFloat() * limit, 55 | animationSpec = spring(stiffness = Spring.StiffnessMediumLow) 56 | ) 57 | } 58 | } 59 | Box( 60 | modifier = Modifier 61 | .background( 62 | color = color, 63 | shape = RoundedCornerShape(20.dp) 64 | ) 65 | .fillMaxHeight(height.value) 66 | .weight(1f) 67 | ) 68 | Box(modifier = Modifier.width(2.dp)) 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/island/DynamicIsland.kt: -------------------------------------------------------------------------------- 1 | @file:OptIn(ExperimentalAnimationApi::class) 2 | 3 | package com.sinasamaki.dynamicisland.island 4 | 5 | import androidx.compose.animation.AnimatedVisibility 6 | import androidx.compose.animation.ExperimentalAnimationApi 7 | import androidx.compose.animation.animateContentSize 8 | import androidx.compose.animation.core.Animatable 9 | import androidx.compose.animation.core.Spring 10 | import androidx.compose.animation.core.animateDpAsState 11 | import androidx.compose.animation.core.spring 12 | import androidx.compose.animation.scaleIn 13 | import androidx.compose.animation.scaleOut 14 | import androidx.compose.animation.slideInHorizontally 15 | import androidx.compose.animation.slideOutHorizontally 16 | import androidx.compose.foundation.background 17 | import androidx.compose.foundation.layout.Box 18 | import androidx.compose.foundation.layout.Row 19 | import androidx.compose.foundation.layout.fillMaxSize 20 | import androidx.compose.foundation.layout.fillMaxWidth 21 | import androidx.compose.foundation.layout.height 22 | import androidx.compose.foundation.layout.offset 23 | import androidx.compose.foundation.layout.padding 24 | import androidx.compose.foundation.shape.RoundedCornerShape 25 | import androidx.compose.runtime.Composable 26 | import androidx.compose.runtime.LaunchedEffect 27 | import androidx.compose.runtime.getValue 28 | import androidx.compose.runtime.remember 29 | import androidx.compose.runtime.rememberCoroutineScope 30 | import androidx.compose.ui.Alignment 31 | import androidx.compose.ui.Modifier 32 | import androidx.compose.ui.graphics.Color 33 | import androidx.compose.ui.platform.LocalConfiguration 34 | import androidx.compose.ui.unit.IntOffset 35 | import androidx.compose.ui.unit.dp 36 | import androidx.compose.ui.zIndex 37 | import com.sinasamaki.dynamicisland.metaball.MetaContainer 38 | import com.sinasamaki.dynamicisland.metaball.MetaEntity 39 | import kotlinx.coroutines.launch 40 | import kotlin.math.roundToInt 41 | 42 | @Composable 43 | fun DynamicIsland(islandState: IslandState) { 44 | val config = LocalConfiguration.current 45 | 46 | val startPadding by animateDpAsState( 47 | targetValue = (config.screenWidthDp.dp / 2) - islandState.fullWidth / 2, 48 | animationSpec = spring( 49 | stiffness = Spring.StiffnessLow, 50 | dampingRatio = Spring.DampingRatioLowBouncy, 51 | ) 52 | ) 53 | 54 | val scope = rememberCoroutineScope() 55 | 56 | val shake = remember { Animatable(0f) } 57 | LaunchedEffect(islandState.hasBubbleContent) { 58 | scope.launch { 59 | shake.animateTo(15f) 60 | shake.animateTo( 61 | targetValue = 0f, 62 | animationSpec = spring( 63 | dampingRatio = Spring.DampingRatioMediumBouncy, 64 | stiffness = Spring.StiffnessLow, 65 | ) 66 | ) 67 | } 68 | } 69 | 70 | MetaContainer( 71 | modifier = Modifier.height(200.dp) 72 | ) { 73 | Row( 74 | modifier = Modifier 75 | .padding(top = 20.dp) 76 | .padding(start = startPadding) 77 | .fillMaxWidth(), 78 | verticalAlignment = Alignment.Top, 79 | ) { 80 | 81 | 82 | MetaEntity( 83 | modifier = Modifier 84 | .offset { IntOffset(shake.value.roundToInt(), 0) } 85 | .zIndex(10f), 86 | metaContent = { 87 | Box( 88 | modifier = Modifier 89 | .fillMaxSize() 90 | .background( 91 | color = Color.Black, 92 | shape = RoundedCornerShape(35.dp) 93 | ) 94 | ) 95 | } 96 | ) { 97 | IslandContent(state = islandState) 98 | } 99 | 100 | AnimatedVisibility( 101 | visible = islandState.hasBubbleContent, 102 | modifier = Modifier.padding(start = 8.dp), 103 | enter = bubbleEnterTransition, 104 | exit = bubbleExitTransition, 105 | ) { 106 | MetaEntity( 107 | metaContent = { 108 | Box( 109 | modifier = Modifier 110 | .fillMaxSize() 111 | .background( 112 | Color.Black, 113 | shape = RoundedCornerShape(50.dp) 114 | ) 115 | ) 116 | } 117 | ) { 118 | IslandBubbleContent(state = islandState) 119 | } 120 | } 121 | } 122 | } 123 | } 124 | 125 | private val bubbleEnterTransition = scaleIn(initialScale = .7f) + slideInHorizontally( 126 | animationSpec = spring( 127 | stiffness = Spring.StiffnessLow, 128 | dampingRatio = Spring.DampingRatioLowBouncy, 129 | ) 130 | ) { -it } 131 | 132 | private val bubbleExitTransition = scaleOut(targetScale = .7f) + slideOutHorizontally( 133 | animationSpec = spring( 134 | stiffness = Spring.StiffnessLow 135 | ) 136 | ) { (-it * 1.2f).roundToInt() } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/island/FaceUnlock.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.island 2 | 3 | import androidx.compose.foundation.layout.fillMaxSize 4 | import androidx.compose.foundation.layout.padding 5 | import androidx.compose.material.Icon 6 | import androidx.compose.material.icons.Icons 7 | import androidx.compose.material.icons.twotone.Face 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.unit.dp 11 | import com.sinasamaki.dynamicisland.ui.theme.Blue 12 | 13 | @Composable 14 | fun FaceUnlock() { 15 | Icon( 16 | imageVector = Icons.TwoTone.Face, 17 | contentDescription = null, 18 | modifier = Modifier 19 | .padding(16.dp) 20 | .fillMaxSize(), 21 | tint = Blue 22 | ) 23 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/island/IslandBubbleContent.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.island 2 | 3 | import androidx.compose.animation.core.Animatable 4 | import androidx.compose.animation.core.Spring 5 | import androidx.compose.animation.core.spring 6 | import androidx.compose.foundation.layout.Box 7 | import androidx.compose.foundation.layout.height 8 | import androidx.compose.foundation.layout.width 9 | import androidx.compose.material.Icon 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.runtime.LaunchedEffect 12 | import androidx.compose.runtime.getValue 13 | import androidx.compose.runtime.mutableStateOf 14 | import androidx.compose.runtime.remember 15 | import androidx.compose.runtime.setValue 16 | import androidx.compose.ui.Alignment 17 | import androidx.compose.ui.Modifier 18 | import androidx.compose.ui.res.painterResource 19 | import org.nativescript.nativescriptandroidcompose.R 20 | import com.sinasamaki.dynamicisland.ui.theme.Orange 21 | 22 | @Composable 23 | fun IslandBubbleContent(state: IslandState) { 24 | val width = state.bubbleContentSize.width 25 | val height = state.bubbleContentSize.height 26 | 27 | val scale = remember { Animatable(1.5f) } 28 | LaunchedEffect(Unit) { 29 | scale.animateTo( 30 | targetValue = 1f, 31 | animationSpec = spring( 32 | stiffness = Spring.StiffnessLow, 33 | dampingRatio = 0.35f, 34 | ) 35 | ) 36 | } 37 | 38 | Box( 39 | modifier = Modifier 40 | .width(width * scale.value) 41 | .height(height), 42 | contentAlignment = Alignment.Center, 43 | ) { 44 | 45 | var bubbleContent: @Composable () -> Unit by remember { 46 | mutableStateOf({}) 47 | } 48 | LaunchedEffect(state, block = { 49 | when (state) { 50 | is IslandState.CallTimerState -> { 51 | bubbleContent = { 52 | Icon( 53 | painter = painterResource(id = R.drawable.timer), 54 | contentDescription = null, 55 | tint = Orange 56 | ) 57 | } 58 | } 59 | 60 | else -> {} 61 | } 62 | }) 63 | bubbleContent() 64 | } 65 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/island/IslandContent.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.island 2 | 3 | import androidx.compose.animation.AnimatedVisibility 4 | import androidx.compose.animation.core.Spring 5 | import androidx.compose.animation.core.animateDpAsState 6 | import androidx.compose.animation.core.spring 7 | import androidx.compose.animation.core.tween 8 | import androidx.compose.animation.fadeIn 9 | import androidx.compose.foundation.layout.Box 10 | import androidx.compose.foundation.layout.Row 11 | import androidx.compose.foundation.layout.fillMaxHeight 12 | import androidx.compose.foundation.layout.fillMaxSize 13 | import androidx.compose.foundation.layout.height 14 | import androidx.compose.foundation.layout.size 15 | import androidx.compose.foundation.layout.width 16 | import androidx.compose.material.Icon 17 | import androidx.compose.material.Text 18 | import androidx.compose.material.icons.Icons 19 | import androidx.compose.material.icons.rounded.Call 20 | import androidx.compose.runtime.Composable 21 | import androidx.compose.runtime.getValue 22 | import androidx.compose.ui.Alignment 23 | import androidx.compose.ui.Modifier 24 | import androidx.compose.ui.draw.clipToBounds 25 | import com.sinasamaki.dynamicisland.ui.theme.Green 26 | 27 | @Composable 28 | fun IslandContent(state: IslandState) { 29 | val width by animateDpAsState( 30 | targetValue = state.fullWidth, 31 | animationSpec = spring( 32 | stiffness = Spring.StiffnessLow, 33 | dampingRatio = .6f, 34 | ) 35 | ) 36 | val height by animateDpAsState( 37 | targetValue = state.contentSize.height, 38 | animationSpec = spring( 39 | stiffness = Spring.StiffnessLow, 40 | dampingRatio = .6f, 41 | ) 42 | ) 43 | 44 | Box( 45 | modifier = Modifier 46 | .width(width) 47 | .height(height) 48 | ) { 49 | 50 | AnimatedVisibility( 51 | visible = state.hasMainContent, 52 | enter = fadeIn( 53 | animationSpec = tween(300, 300) 54 | ) 55 | ) { 56 | Box( 57 | modifier = Modifier.size(state.contentSize) 58 | ) { 59 | when (state) { 60 | is IslandState.FaceUnlockState -> { 61 | FaceUnlock() 62 | } 63 | 64 | else -> {} 65 | } 66 | } 67 | } 68 | 69 | Row( 70 | modifier = Modifier 71 | .fillMaxSize(), 72 | verticalAlignment = Alignment.CenterVertically, 73 | ) { 74 | LeadingContent(state) 75 | Box(Modifier.weight(1f)) 76 | TrailingContent(state) 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/island/IslandState.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.island 2 | 3 | import androidx.compose.ui.unit.Dp 4 | import androidx.compose.ui.unit.DpSize 5 | import androidx.compose.ui.unit.dp 6 | 7 | sealed class IslandState( 8 | val contentSize: DpSize = DpSize(150.dp, 50.dp), 9 | val hasMainContent: Boolean = false, 10 | 11 | val leadingContentSize: Dp = Dp.Hairline, 12 | val hasLeadingContent: Boolean = false, 13 | 14 | val trailingContentSize: Dp = Dp.Hairline, 15 | val hasTrailingContent: Boolean = false, 16 | 17 | val bubbleContentSize: DpSize = DpSize(50.dp, 50.dp), 18 | val hasBubbleContent: Boolean = false 19 | ) { 20 | 21 | val fullWidth = contentSize.width + leadingContentSize + trailingContentSize 22 | 23 | class DefaultState : IslandState() 24 | 25 | class CallTimerState : IslandState( 26 | leadingContentSize = 50.dp, 27 | hasLeadingContent = true, 28 | hasBubbleContent = true 29 | ) 30 | 31 | class CallState : IslandState( 32 | leadingContentSize = 65.dp, 33 | trailingContentSize = 55.dp, 34 | hasLeadingContent = true, 35 | hasTrailingContent = true, 36 | ) 37 | 38 | class FaceUnlockState : IslandState( 39 | contentSize = DpSize( 40 | 150.dp, 150.dp 41 | ), 42 | hasMainContent = true, 43 | ) 44 | 45 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/island/LeadingContent.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.island 2 | 3 | import androidx.compose.animation.AnimatedVisibility 4 | import androidx.compose.animation.core.tween 5 | import androidx.compose.animation.fadeIn 6 | import androidx.compose.foundation.layout.Box 7 | import androidx.compose.foundation.layout.fillMaxHeight 8 | import androidx.compose.foundation.layout.width 9 | import androidx.compose.material.Icon 10 | import androidx.compose.material.Text 11 | import androidx.compose.material.icons.Icons 12 | import androidx.compose.material.icons.rounded.Call 13 | import androidx.compose.runtime.Composable 14 | import androidx.compose.ui.Alignment 15 | import androidx.compose.ui.Modifier 16 | import com.sinasamaki.dynamicisland.ui.theme.Green 17 | 18 | @Composable 19 | fun LeadingContent(state: IslandState) { 20 | AnimatedVisibility( 21 | modifier = Modifier.fillMaxHeight(), 22 | visible = state.hasLeadingContent, 23 | enter = fadeIn(animationSpec = tween(300, 300)) 24 | ) { 25 | Box( 26 | Modifier 27 | .width(state.leadingContentSize), 28 | contentAlignment = Alignment.Center, 29 | ) { 30 | when (state) { 31 | is IslandState.CallState -> { 32 | Text(text = "9:41", color = Green) 33 | } 34 | 35 | is IslandState.CallTimerState -> { 36 | Icon( 37 | imageVector = Icons.Rounded.Call, 38 | contentDescription = null, 39 | tint = Green, 40 | ) 41 | } 42 | 43 | else -> {} 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/island/TrailingContent.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.island 2 | 3 | import androidx.compose.animation.AnimatedVisibility 4 | import androidx.compose.animation.core.tween 5 | import androidx.compose.animation.fadeIn 6 | import androidx.compose.foundation.layout.Box 7 | import androidx.compose.foundation.layout.fillMaxHeight 8 | import androidx.compose.foundation.layout.width 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.ui.Alignment 11 | import androidx.compose.ui.Modifier 12 | 13 | @Composable 14 | fun TrailingContent(state: IslandState) { 15 | AnimatedVisibility( 16 | modifier = Modifier.fillMaxHeight(), 17 | visible = state.hasTrailingContent, 18 | enter = fadeIn(animationSpec = tween(300,300)) 19 | ) { 20 | Box( 21 | Modifier 22 | .width(state.trailingContentSize), 23 | contentAlignment = Alignment.Center, 24 | ) { 25 | when (state) { 26 | is IslandState.CallState -> { 27 | CallWaveform() 28 | } 29 | 30 | else -> {} 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/metaball/MetaContainter.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.metaball 2 | 3 | import android.graphics.RenderEffect 4 | import android.graphics.RuntimeShader 5 | import androidx.compose.foundation.layout.Box 6 | import androidx.compose.foundation.layout.BoxScope 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.runtime.remember 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.graphics.asComposeRenderEffect 11 | import androidx.compose.ui.graphics.graphicsLayer 12 | import androidx.compose.ui.layout.onSizeChanged 13 | import org.intellij.lang.annotations.Language 14 | 15 | @Language("AGSL") 16 | const val ShaderSource = """ 17 | uniform shader composable; 18 | 19 | uniform float cutoff; 20 | 21 | half4 main(float2 fragCoord) { 22 | half4 color = composable.eval(fragCoord); 23 | float alpha = color.a; 24 | if (alpha > cutoff) { 25 | alpha = 1.0; 26 | } else { 27 | alpha = 0.0; 28 | } 29 | 30 | color = half4(color.r, color.g, color.b, alpha); 31 | return color; 32 | } 33 | """ 34 | 35 | @Composable 36 | fun MetaContainer( 37 | modifier: Modifier = Modifier, 38 | cutoff: Float = .5f, 39 | content: @Composable BoxScope.() -> Unit, 40 | ) { 41 | val metaShader = remember { RuntimeShader(ShaderSource) } 42 | Box( 43 | modifier 44 | .graphicsLayer { 45 | metaShader.setFloatUniform("cutoff", cutoff) 46 | renderEffect = RenderEffect.createRuntimeShaderEffect( 47 | metaShader, "composable" 48 | ).asComposeRenderEffect() 49 | }, 50 | content = content, 51 | ) 52 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/metaball/MetaEntity.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.metaball 2 | 3 | import androidx.compose.foundation.layout.Box 4 | import androidx.compose.foundation.layout.BoxScope 5 | import androidx.compose.foundation.layout.IntrinsicSize 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.foundation.layout.width 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Alignment 10 | import androidx.compose.ui.Modifier 11 | 12 | @Composable 13 | fun MetaEntity( 14 | modifier: Modifier = Modifier, 15 | blur: Float = 30f, 16 | metaContent: @Composable BoxScope.() -> Unit, 17 | content: @Composable BoxScope.() -> Unit, 18 | ) { 19 | Box( 20 | modifier 21 | .width(IntrinsicSize.Min) 22 | .height(IntrinsicSize.Min), 23 | contentAlignment = Alignment.Center 24 | ) { 25 | Box( 26 | modifier = Modifier 27 | .customBlur(blur), 28 | content = metaContent, 29 | ) 30 | content() 31 | } 32 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/metaball/Modifiers.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.metaball 2 | 3 | import android.graphics.RenderEffect 4 | import android.graphics.Shader 5 | import androidx.compose.ui.Modifier 6 | import androidx.compose.ui.graphics.asComposeRenderEffect 7 | import androidx.compose.ui.graphics.graphicsLayer 8 | 9 | fun Modifier.customBlur(blur: Float) = this.then( 10 | graphicsLayer { 11 | renderEffect = RenderEffect 12 | .createBlurEffect( 13 | blur, 14 | blur, 15 | Shader.TileMode.DECAL, 16 | ) 17 | .asComposeRenderEffect() 18 | } 19 | ) -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple200 = Color(0xFFBB86FC) 6 | val Purple500 = Color(0xFF6200EE) 7 | val Purple700 = Color(0xFF3700B3) 8 | val Teal200 = Color(0xFF03DAC5) 9 | val Green = Color(0xFF6EE228) 10 | val Orange = Color(0xFFFFAD57) 11 | val White = Color(0xffFFFFFF) 12 | val Blue = Color(0xFF2CADF1) -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.ui.theme 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val Shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.ui.theme 2 | 3 | import androidx.compose.foundation.isSystemInDarkTheme 4 | import androidx.compose.material.MaterialTheme 5 | import androidx.compose.material.darkColors 6 | import androidx.compose.material.lightColors 7 | import androidx.compose.runtime.Composable 8 | 9 | private val DarkColorPalette = darkColors( 10 | primary = Purple200, 11 | primaryVariant = Purple700, 12 | secondary = Teal200 13 | ) 14 | 15 | private val LightColorPalette = lightColors( 16 | primary = Purple500, 17 | primaryVariant = Purple700, 18 | secondary = Teal200 19 | 20 | /* Other default colors to override 21 | background = Color.White, 22 | surface = Color.White, 23 | onPrimary = Color.White, 24 | onSecondary = Color.Black, 25 | onBackground = Color.Black, 26 | onSurface = Color.Black, 27 | */ 28 | ) 29 | 30 | @Composable 31 | fun DynamicIslandTheme( 32 | darkTheme: Boolean = isSystemInDarkTheme(), 33 | content: @Composable () -> Unit 34 | ) { 35 | val colors = if (darkTheme) { 36 | DarkColorPalette 37 | } else { 38 | LightColorPalette 39 | } 40 | 41 | MaterialTheme( 42 | colors = colors, 43 | typography = Typography, 44 | shapes = Shapes, 45 | content = content 46 | ) 47 | } -------------------------------------------------------------------------------- /App_Resources/Android/src/main/java/com/sinasamaki/dynamicisland/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.sinasamaki.dynamicisland.ui.theme 2 | 3 | import androidx.compose.material.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.FontFamily 6 | import androidx.compose.ui.text.font.FontWeight 7 | import androidx.compose.ui.unit.sp 8 | 9 | // Set of Material typography styles to start with 10 | val Typography = Typography( 11 | body1 = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp 15 | ) 16 | /* Other default text styles to override 17 | button = TextStyle( 18 | fontFamily = FontFamily.Default, 19 | fontWeight = FontWeight.W500, 20 | fontSize = 14.sp 21 | ), 22 | caption = TextStyle( 23 | fontFamily = FontFamily.Default, 24 | fontWeight = FontWeight.Normal, 25 | fontSize = 12.sp 26 | ) 27 | */ 28 | ) -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-hdpi/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-hdpi/background.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-hdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-hdpi/logo.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-ldpi/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-ldpi/background.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-ldpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-ldpi/logo.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-mdpi/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-mdpi/background.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-mdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-mdpi/logo.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-nodpi/splash_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-xhdpi/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-xhdpi/background.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-xhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-xhdpi/logo.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-xxhdpi/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-xxhdpi/background.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-xxhdpi/logo.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-xxxhdpi/background.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/drawable-xxxhdpi/logo.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/drawable/timer.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/Android/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/values-v21/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 15 | 16 | 17 | 21 | 22 | 23 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/values-v29/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 17 | 18 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #F5F5F5 5 | 6 | 7 | #757575 8 | 9 | 10 | #65ADF1 11 | 12 | #FFBB86FC 13 | #FF6200EE 14 | #FF3700B3 15 | #FF03DAC5 16 | #FF018786 17 | #FF000000 18 | #FFFFFFFF 19 | 20 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | NativeScript ❤️ Jetpack Compose 3 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 17 | 18 | 20 | 21 | 22 | 29 | 30 | 32 | 33 | 34 | 39 | 40 | 42 | 43 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /App_Resources/Android/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "icon-20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "icon-20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "icon-29.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "icon-29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "icon-29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "icon-40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "icon-40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "icon-60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "icon-60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "icon-20.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "icon-20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "icon-29.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "icon-29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "icon-40.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "icon-40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "icon-76.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "icon-76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "icon-83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "icon-1024.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchScreen-AspectFill.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchScreen-AspectFill@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchScreen-AspectFill@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@3x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchScreen-Center.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchScreen-Center@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchScreen-Center@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NativeScript/android-compose-example/995567191d67a910499d09bd152cd84a8bb56b6d/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@3x.png -------------------------------------------------------------------------------- /App_Resources/iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiresFullScreen 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /App_Resources/iOS/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /App_Resources/iOS/build.xcconfig: -------------------------------------------------------------------------------- 1 | // You can add custom settings here 2 | // for example you can uncomment the following line to force distribution code signing 3 | // CODE_SIGN_IDENTITY = iPhone Distribution 4 | // To build for device with XCode you need to specify your development team. 5 | // DEVELOPMENT_TEAM = YOUR_TEAM_ID; 6 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **@nativescript/jetpack-compose** Example 🚀📓♥️ 2 | 3 | 4 | 5 | Android app using [Angular](https://angular.io/) to drive [Jetpack Compose](https://developer.android.com/jetpack/compose) 6 | 7 | - [Drive yourself](#drive-yourself) 8 | - [Credits](#credits) 9 | 10 | ## Drive yourself 11 | 12 | Prerequisites: 13 | - [NativeScript Environment Setup](https://docs.nativescript.org/environment-setup.html) 14 | - Android API Level 33 emulator or device 15 | 16 | *Note*: Uses APIs only available on API Level 33+ 17 | 18 | ``` 19 | ns debug android 20 | ``` 21 | 22 | ## Credits 23 | 24 | Inspired by [@sinasamaki](https://twitter.com/sinasamaki) 25 | 26 | Usage from example shared [here](https://github.com/sinasamaki/DynamicIsland). -------------------------------------------------------------------------------- /nativescript.config.ts: -------------------------------------------------------------------------------- 1 | import { NativeScriptConfig } from '@nativescript/core'; 2 | 3 | export default { 4 | id: 'org.nativescript.nativescriptandroidcompose', 5 | appPath: 'src', 6 | appResourcesPath: 'App_Resources', 7 | android: { 8 | v8Flags: '--expose_gc', 9 | markingMode: 'none' 10 | } 11 | } as NativeScriptConfig; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nativescript-android-compose", 3 | "main": "./src/main.ts", 4 | "version": "1.0.0", 5 | "private": true, 6 | "dependencies": { 7 | "@angular/animations": "~15.1.0", 8 | "@angular/common": "~15.1.0", 9 | "@angular/compiler": "~15.1.0", 10 | "@angular/core": "~15.1.0", 11 | "@angular/forms": "~15.1.0", 12 | "@angular/platform-browser": "~15.1.0", 13 | "@angular/platform-browser-dynamic": "~15.1.0", 14 | "@angular/router": "~15.1.0", 15 | "@nativescript/angular": "^15.0.0", 16 | "@nativescript/core": "~8.4.0", 17 | "@nativescript/jetpack-compose": "^1.0.0-beta.0", 18 | "rxjs": "~7.6.0", 19 | "zone.js": "~0.12.0" 20 | }, 21 | "devDependencies": { 22 | "@angular-devkit/build-angular": "~15.1.0", 23 | "@angular/compiler-cli": "~15.1.0", 24 | "@nativescript/android": "8.4.0", 25 | "@nativescript/tailwind": "^2.0.1", 26 | "@nativescript/types": "~8.4.0", 27 | "@nativescript/webpack": "~5.0.12", 28 | "@ngtools/webpack": "~15.1.0", 29 | "tailwindcss": "^3.2.0", 30 | "typescript": "~4.8.4" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /references.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core' 2 | import { Routes } from '@angular/router' 3 | import { NativeScriptRouterModule } from '@nativescript/angular' 4 | 5 | import { HomeComponent } from './home.component' 6 | 7 | const routes: Routes = [ 8 | { path: '', redirectTo: '/home', pathMatch: 'full' }, 9 | { path: 'home', component: HomeComponent }, 10 | ] 11 | 12 | @NgModule({ 13 | imports: [NativeScriptRouterModule.forRoot(routes)], 14 | exports: [NativeScriptRouterModule], 15 | }) 16 | export class AppRoutingModule {} -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core' 2 | 3 | @Component({ 4 | selector: 'ns-app', 5 | templateUrl: './app.component.html', 6 | }) 7 | export class AppComponent {} 8 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core' 2 | import { NativeScriptModule } from '@nativescript/angular' 3 | 4 | import { AppRoutingModule } from './app-routing.module' 5 | import { AppComponent } from './app.component' 6 | import { HomeComponent } from './home.component' 7 | 8 | @NgModule({ 9 | bootstrap: [AppComponent], 10 | imports: [NativeScriptModule, AppRoutingModule], 11 | declarations: [AppComponent, HomeComponent], 12 | providers: [], 13 | schemas: [NO_ERRORS_SCHEMA], 14 | }) 15 | export class AppModule {} 16 | -------------------------------------------------------------------------------- /src/app/home.component.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 11 | 16 | 17 | 18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/app/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from "@angular/core"; 2 | 3 | 4 | @Component({ 5 | selector: "ns-home", 6 | templateUrl: "./home.component.html", 7 | }) 8 | export class HomeComponent { 9 | 10 | } -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformNativeScript, registerElement, runNativeScriptAngularApp } from '@nativescript/angular'; 2 | 3 | import { AppModule } from './app/app.module'; 4 | import { registerJetpackCompose, ComposeDataDriver, JetpackCompose } from '@nativescript/jetpack-compose'; 5 | 6 | registerElement('JetpackCompose', () => JetpackCompose); 7 | // A. You can generate types for your own Compose Provider with 'ns typings android --aar {path/to/{name}.aar}' 8 | // B. Otherwise you can ignore by declaring the package resolution path you know you provided 9 | declare var com; 10 | registerJetpackCompose('dynamicIsland', (view) => new ComposeDataDriver(new com.sinasamaki.dynamicisland.IslandView(), view)); 11 | 12 | runNativeScriptAngularApp({ 13 | appModuleBootstrap: () => platformNativeScript().bootstrapModule(AppModule), 14 | }); 15 | 16 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * NativeScript Polyfills 3 | */ 4 | 5 | // Install @nativescript/core polyfills (XHR, setTimeout, requestAnimationFrame) 6 | import '@nativescript/core/globals'; 7 | // Install @nativescript/angular specific polyfills 8 | import '@nativescript/angular/polyfills'; 9 | 10 | /** 11 | * Zone.js and patches 12 | */ 13 | // Add pre-zone.js patches needed for the NativeScript platform 14 | import '@nativescript/zone-js/dist/pre-zone-polyfills'; 15 | 16 | // Zone JS is required by default for Angular itself 17 | import 'zone.js'; 18 | 19 | // Add NativeScript specific Zone JS patches 20 | import '@nativescript/zone-js'; 21 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | './src/**/*.{css,xml,html,vue,svelte,ts,tsx}' 5 | ], 6 | // use the .ns-dark class to control dark mode (applied by NativeScript) - since 'media' (default) is not supported. 7 | darkMode: ['class', '.ns-dark'], 8 | theme: { 9 | extend: {}, 10 | }, 11 | plugins: [], 12 | corePlugins: { 13 | preflight: false // disables browser-specific resets 14 | } 15 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "esnext", 4 | "target": "es2017", 5 | "moduleResolution": "node", 6 | "experimentalDecorators": true, 7 | "emitDecoratorMetadata": true, 8 | "noEmitHelpers": true, 9 | "noEmitOnError": true, 10 | "skipLibCheck": true, 11 | "lib": ["es2017", "dom"], 12 | "baseUrl": ".", 13 | "paths": { 14 | "~/*": ["src/*"], 15 | "@/*": ["src/*"] 16 | } 17 | }, 18 | "include": ["src/tests/**/*.ts", "src/**/*.ios.ts", "src/**/*.android.ts"], 19 | "files": ["./src/main.ts", "./references.d.ts", "./src/polyfills.ts"], 20 | "exclude": ["node_modules", "platforms", "e2e"] 21 | } 22 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require("@nativescript/webpack"); 2 | 3 | module.exports = (env) => { 4 | webpack.init(env); 5 | 6 | // Learn how to customize: 7 | // https://docs.nativescript.org/webpack 8 | 9 | return webpack.resolveConfig(); 10 | }; 11 | --------------------------------------------------------------------------------