dima.avdeev
2 years ago
committed by
GitHub
28 changed files with 683 additions and 100 deletions
@ -1,7 +1,16 @@ |
|||||||
<?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:android="http://schemas.android.com/apk/res/android" |
||||||
package="example.imageviewer.shared"> |
package="example.imageviewer.shared"> |
||||||
|
|
||||||
<uses-permission android:name="android.permission.CAMERA" /> |
<uses-permission android:name="android.permission.CAMERA" /> |
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> |
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> |
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
||||||
|
|
||||||
|
<application> |
||||||
|
<provider |
||||||
|
android:name="example.imageviewer.ImageViewerFileProvider" |
||||||
|
android:authorities="example.imageviewer.fileprovider" |
||||||
|
android:exported="false" |
||||||
|
android:grantUriPermissions="true"></provider> |
||||||
|
</application> |
||||||
</manifest> |
</manifest> |
@ -0,0 +1,6 @@ |
|||||||
|
package example.imageviewer |
||||||
|
|
||||||
|
import androidx.core.content.FileProvider |
||||||
|
import example.imageviewer.shared.R |
||||||
|
|
||||||
|
class ImageViewerFileProvider : FileProvider(R.xml.file_paths) |
@ -0,0 +1,77 @@ |
|||||||
|
package example.imageviewer.view |
||||||
|
|
||||||
|
import androidx.compose.foundation.background |
||||||
|
import androidx.compose.foundation.clickable |
||||||
|
import androidx.compose.foundation.layout.Box |
||||||
|
import androidx.compose.foundation.layout.BoxScope |
||||||
|
import androidx.compose.foundation.layout.Column |
||||||
|
import androidx.compose.foundation.layout.fillMaxSize |
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth |
||||||
|
import androidx.compose.foundation.layout.padding |
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape |
||||||
|
import androidx.compose.material.LocalTextStyle |
||||||
|
import androidx.compose.material.TextField |
||||||
|
import androidx.compose.material.TextFieldDefaults |
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.runtime.getValue |
||||||
|
import androidx.compose.runtime.mutableStateOf |
||||||
|
import androidx.compose.runtime.remember |
||||||
|
import androidx.compose.runtime.setValue |
||||||
|
import androidx.compose.ui.Alignment |
||||||
|
import androidx.compose.ui.Modifier |
||||||
|
import androidx.compose.ui.draw.clip |
||||||
|
import androidx.compose.ui.graphics.Color |
||||||
|
import androidx.compose.ui.text.font.FontWeight |
||||||
|
import androidx.compose.ui.text.style.TextAlign |
||||||
|
import androidx.compose.ui.unit.dp |
||||||
|
import androidx.compose.ui.unit.sp |
||||||
|
|
||||||
|
@Composable |
||||||
|
internal actual fun BoxScope.EditMemoryDialog( |
||||||
|
previousName: String, |
||||||
|
previousDescription: String, |
||||||
|
save: (name: String, description: String) -> Unit |
||||||
|
) { |
||||||
|
var name by remember { mutableStateOf(previousName) } |
||||||
|
var description by remember { mutableStateOf(previousDescription) } |
||||||
|
Box( |
||||||
|
Modifier |
||||||
|
.fillMaxSize() |
||||||
|
.background(Color.Black.copy(alpha = 0.4f)) |
||||||
|
.clickable { |
||||||
|
save(name, description) |
||||||
|
} |
||||||
|
) { |
||||||
|
Column( |
||||||
|
modifier = Modifier |
||||||
|
.align(Alignment.Center) |
||||||
|
.padding(30.dp) |
||||||
|
.clip(RoundedCornerShape(20.dp)) |
||||||
|
.background(Color.White), |
||||||
|
horizontalAlignment = Alignment.CenterHorizontally, |
||||||
|
) { |
||||||
|
TextField( |
||||||
|
value = name, |
||||||
|
onValueChange = { name = it }, |
||||||
|
modifier = Modifier.fillMaxWidth(), |
||||||
|
colors = TextFieldDefaults.textFieldColors( |
||||||
|
backgroundColor = Color.White, |
||||||
|
), |
||||||
|
textStyle = LocalTextStyle.current.copy( |
||||||
|
textAlign = TextAlign.Center, |
||||||
|
fontSize = 20.sp, |
||||||
|
fontWeight = FontWeight.Bold, |
||||||
|
), |
||||||
|
) |
||||||
|
TextField( |
||||||
|
value = description, |
||||||
|
onValueChange = { description = it }, |
||||||
|
colors = TextFieldDefaults.textFieldColors( |
||||||
|
backgroundColor = Color.White, |
||||||
|
unfocusedIndicatorColor = Color.Transparent, |
||||||
|
focusedIndicatorColor = Color.Transparent, |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
<paths xmlns:android="http://schemas.android.com/apk/res/android"> |
||||||
|
<files-path name="my_images" path="share_images/"/> |
||||||
|
</paths> |
@ -1,8 +1,10 @@ |
|||||||
package example.imageviewer.model |
package example.imageviewer.model |
||||||
|
|
||||||
|
import androidx.compose.runtime.MutableState |
||||||
|
|
||||||
sealed interface Page |
sealed interface Page |
||||||
|
|
||||||
class MemoryPage(val picture: PictureData) : Page |
class MemoryPage(val pictureState: MutableState<PictureData>) : Page |
||||||
class CameraPage : Page |
class CameraPage : Page |
||||||
class FullScreenPage(val picture: PictureData) : Page |
class FullScreenPage(val picture: PictureData) : Page |
||||||
class GalleryPage : Page |
class GalleryPage : Page |
||||||
|
@ -0,0 +1,11 @@ |
|||||||
|
package example.imageviewer.view |
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.BoxScope |
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
|
||||||
|
@Composable |
||||||
|
internal expect fun BoxScope.EditMemoryDialog( |
||||||
|
previousName: String, |
||||||
|
previousDescription: String, |
||||||
|
save: (name: String, description: String) -> Unit |
||||||
|
) |
@ -0,0 +1,87 @@ |
|||||||
|
package example.imageviewer.view |
||||||
|
|
||||||
|
import androidx.compose.foundation.background |
||||||
|
import androidx.compose.foundation.clickable |
||||||
|
import androidx.compose.foundation.layout.Box |
||||||
|
import androidx.compose.foundation.layout.BoxScope |
||||||
|
import androidx.compose.foundation.layout.Column |
||||||
|
import androidx.compose.foundation.layout.fillMaxSize |
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth |
||||||
|
import androidx.compose.foundation.layout.padding |
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape |
||||||
|
import androidx.compose.material.AlertDialog |
||||||
|
import androidx.compose.material.ExperimentalMaterialApi |
||||||
|
import androidx.compose.material.LocalTextStyle |
||||||
|
import androidx.compose.material.TextField |
||||||
|
import androidx.compose.material.TextFieldDefaults |
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.runtime.getValue |
||||||
|
import androidx.compose.runtime.mutableStateOf |
||||||
|
import androidx.compose.runtime.remember |
||||||
|
import androidx.compose.runtime.setValue |
||||||
|
import androidx.compose.ui.Alignment |
||||||
|
import androidx.compose.ui.Modifier |
||||||
|
import androidx.compose.ui.draw.clip |
||||||
|
import androidx.compose.ui.graphics.Color |
||||||
|
import androidx.compose.ui.text.font.FontWeight |
||||||
|
import androidx.compose.ui.text.style.TextAlign |
||||||
|
import androidx.compose.ui.unit.dp |
||||||
|
import androidx.compose.ui.unit.sp |
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterialApi::class) |
||||||
|
@Composable |
||||||
|
internal actual fun BoxScope.EditMemoryDialog( |
||||||
|
previousName: String, |
||||||
|
previousDescription: String, |
||||||
|
save: (name: String, description: String) -> Unit |
||||||
|
) { |
||||||
|
var name by remember { mutableStateOf(previousName) } |
||||||
|
var description by remember { mutableStateOf(previousDescription) } |
||||||
|
AlertDialog( |
||||||
|
onDismissRequest = { |
||||||
|
save(name, description) |
||||||
|
}, |
||||||
|
buttons = { |
||||||
|
Column( |
||||||
|
modifier = Modifier |
||||||
|
.align(Alignment.Center) |
||||||
|
.padding(30.dp) |
||||||
|
.clip(RoundedCornerShape(20.dp)) |
||||||
|
.background(Color.White), |
||||||
|
horizontalAlignment = Alignment.CenterHorizontally, |
||||||
|
) { |
||||||
|
TextField( |
||||||
|
value = name, |
||||||
|
onValueChange = { name = it }, |
||||||
|
modifier = Modifier.fillMaxWidth(), |
||||||
|
colors = TextFieldDefaults.textFieldColors( |
||||||
|
backgroundColor = Color.White, |
||||||
|
), |
||||||
|
textStyle = LocalTextStyle.current.copy( |
||||||
|
textAlign = TextAlign.Center, |
||||||
|
fontSize = 20.sp, |
||||||
|
fontWeight = FontWeight.Bold, |
||||||
|
), |
||||||
|
) |
||||||
|
TextField( |
||||||
|
value = description, |
||||||
|
onValueChange = { description = it }, |
||||||
|
colors = TextFieldDefaults.textFieldColors( |
||||||
|
backgroundColor = Color.White, |
||||||
|
unfocusedIndicatorColor = Color.Transparent, |
||||||
|
focusedIndicatorColor = Color.Transparent, |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
}, |
||||||
|
) |
||||||
|
Box( |
||||||
|
Modifier |
||||||
|
.fillMaxSize() |
||||||
|
.background(Color.Black.copy(alpha = 0.4f)) |
||||||
|
.clickable { |
||||||
|
|
||||||
|
} |
||||||
|
) { |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
package example.imageviewer |
||||||
|
|
||||||
|
import androidx.compose.material.icons.materialIcon |
||||||
|
import androidx.compose.material.icons.materialPath |
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector |
||||||
|
|
||||||
|
// TODO Copied from material3, because "material:material-icons-extended" not working on iOS for now |
||||||
|
val IosShareIcon: ImageVector = |
||||||
|
materialIcon(name = "Filled.IosShare") { |
||||||
|
materialPath { |
||||||
|
moveTo(16.0f, 5.0f) |
||||||
|
lineToRelative(-1.42f, 1.42f) |
||||||
|
lineToRelative(-1.59f, -1.59f) |
||||||
|
lineTo(12.99f, 16.0f) |
||||||
|
horizontalLineToRelative(-1.98f) |
||||||
|
lineTo(11.01f, 4.83f) |
||||||
|
lineTo(9.42f, 6.42f) |
||||||
|
lineTo(8.0f, 5.0f) |
||||||
|
lineToRelative(4.0f, -4.0f) |
||||||
|
lineToRelative(4.0f, 4.0f) |
||||||
|
close() |
||||||
|
moveTo(20.0f, 10.0f) |
||||||
|
verticalLineToRelative(11.0f) |
||||||
|
curveToRelative(0.0f, 1.1f, -0.9f, 2.0f, -2.0f, 2.0f) |
||||||
|
lineTo(6.0f, 23.0f) |
||||||
|
curveToRelative(-1.11f, 0.0f, -2.0f, -0.9f, -2.0f, -2.0f) |
||||||
|
lineTo(4.0f, 10.0f) |
||||||
|
curveToRelative(0.0f, -1.11f, 0.89f, -2.0f, 2.0f, -2.0f) |
||||||
|
horizontalLineToRelative(3.0f) |
||||||
|
verticalLineToRelative(2.0f) |
||||||
|
lineTo(6.0f, 10.0f) |
||||||
|
verticalLineToRelative(11.0f) |
||||||
|
horizontalLineToRelative(12.0f) |
||||||
|
lineTo(18.0f, 10.0f) |
||||||
|
horizontalLineToRelative(-3.0f) |
||||||
|
lineTo(15.0f, 8.0f) |
||||||
|
horizontalLineToRelative(3.0f) |
||||||
|
curveToRelative(1.1f, 0.0f, 2.0f, 0.89f, 2.0f, 2.0f) |
||||||
|
close() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
package example.imageviewer.view |
||||||
|
|
||||||
|
import androidx.compose.foundation.background |
||||||
|
import androidx.compose.foundation.clickable |
||||||
|
import androidx.compose.foundation.layout.Box |
||||||
|
import androidx.compose.foundation.layout.BoxScope |
||||||
|
import androidx.compose.foundation.layout.Column |
||||||
|
import androidx.compose.foundation.layout.fillMaxSize |
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth |
||||||
|
import androidx.compose.foundation.layout.padding |
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape |
||||||
|
import androidx.compose.material.LocalTextStyle |
||||||
|
import androidx.compose.material.TextField |
||||||
|
import androidx.compose.material.TextFieldDefaults |
||||||
|
import androidx.compose.runtime.Composable |
||||||
|
import androidx.compose.runtime.getValue |
||||||
|
import androidx.compose.runtime.mutableStateOf |
||||||
|
import androidx.compose.runtime.remember |
||||||
|
import androidx.compose.runtime.setValue |
||||||
|
import androidx.compose.ui.Alignment |
||||||
|
import androidx.compose.ui.Modifier |
||||||
|
import androidx.compose.ui.draw.clip |
||||||
|
import androidx.compose.ui.graphics.Color |
||||||
|
import androidx.compose.ui.text.font.FontWeight |
||||||
|
import androidx.compose.ui.text.style.TextAlign |
||||||
|
import androidx.compose.ui.unit.dp |
||||||
|
import androidx.compose.ui.unit.sp |
||||||
|
|
||||||
|
@Composable |
||||||
|
internal actual fun BoxScope.EditMemoryDialog( |
||||||
|
previousName: String, |
||||||
|
previousDescription: String, |
||||||
|
save: (name: String, description: String) -> Unit |
||||||
|
) { |
||||||
|
var name by remember { mutableStateOf(previousName) } |
||||||
|
var description by remember { mutableStateOf(previousDescription) } |
||||||
|
Box( |
||||||
|
Modifier |
||||||
|
.fillMaxSize() |
||||||
|
.background(Color.Black.copy(alpha = 0.4f)) |
||||||
|
.clickable { |
||||||
|
save(name, description) |
||||||
|
} |
||||||
|
) { |
||||||
|
Column( |
||||||
|
modifier = Modifier |
||||||
|
.align(Alignment.Center) |
||||||
|
.padding(30.dp) |
||||||
|
.clip(RoundedCornerShape(20.dp)) |
||||||
|
.background(Color.White), |
||||||
|
horizontalAlignment = Alignment.CenterHorizontally, |
||||||
|
) { |
||||||
|
TextField( |
||||||
|
value = name, |
||||||
|
onValueChange = { name = it }, |
||||||
|
modifier = Modifier.fillMaxWidth(), |
||||||
|
colors = TextFieldDefaults.textFieldColors( |
||||||
|
backgroundColor = Color.White, |
||||||
|
), |
||||||
|
textStyle = LocalTextStyle.current.copy( |
||||||
|
textAlign = TextAlign.Center, |
||||||
|
fontSize = 20.sp, |
||||||
|
fontWeight = FontWeight.Bold, |
||||||
|
), |
||||||
|
) |
||||||
|
TextField( |
||||||
|
value = description, |
||||||
|
onValueChange = { description = it }, |
||||||
|
colors = TextFieldDefaults.textFieldColors( |
||||||
|
backgroundColor = Color.White, |
||||||
|
unfocusedIndicatorColor = Color.Transparent, |
||||||
|
focusedIndicatorColor = Color.Transparent, |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue