From 8e002cc61bb62a33933ab15b98a4f472b8dccc0d Mon Sep 17 00:00:00 2001 From: Marian Jureczko Date: Sat, 18 May 2024 20:36:20 +0200 Subject: [PATCH] #17 in progress - facebook --- README.md | 6 +- .../commemorative/n/CommemorativeScreen.kt | 3 +- .../activity/facebook/ElementDescription.kt | 4 +- .../activity/facebook/FacebookViewModel.kt | 28 +-- .../facebook/ReportCommemorativePhotos.kt | 2 +- .../activity/facebook/ReportGenerator.kt | 20 +- .../activity/facebook/ReportMap.kt | 2 +- .../activity/facebook/ReportMapHeader.kt | 2 +- .../activity/facebook/ReportMapSummary.kt | 2 +- .../activity/facebook/ReportSummary.kt | 2 +- .../activity/facebook/ReportTitle.kt | 3 +- .../activity/facebook/n/FacebookHelper.kt | 38 +++ .../activity/facebook/n/FacebookScreen.kt | 235 ++++++++++++++++++ .../activity/facebook/n/FacebookState.kt | 39 +++ .../activity/facebook/n/FacebookViewModel.kt | 71 ++++++ .../activity/main/CustomScreenBody.kt | 12 +- .../poszukiwacz/activity/main/MainActivity.kt | 51 ++-- .../poszukiwacz/activity/main/MainScreen.kt | 4 +- .../poszukiwacz/activity/map/n/MapScreen.kt | 6 +- .../activity/photo/n/TipPhotoScreen.kt | 5 +- .../activity/result/n/ResultScreen.kt | 56 +++-- .../activity/searching/n/SearchingScreen.kt | 5 +- .../activity/searching/n/SharedState.kt | 8 +- .../activity/searching/n/SharedViewModel.kt | 38 ++- .../treasureselector/n/SelectorScreen.kt | 5 +- .../poszukiwacz/ui/components/LargeButton.kt | 17 +- .../poszukiwacz/ui/components/TopBar.kt | 4 +- app/src/main/res/layout/activity_facebook.xml | 2 +- app/src/main/res/values-pl/strings.xml | 4 +- app/src/main/res/values/strings.xml | 4 +- app/src/main/res/xml/files.xml | 1 + assets/kalinowice/assets/custom.xml | 57 +++-- 32 files changed, 608 insertions(+), 128 deletions(-) create mode 100644 app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookHelper.kt create mode 100644 app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookScreen.kt create mode 100644 app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookState.kt create mode 100644 app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookViewModel.kt diff --git a/README.md b/README.md index ef7ca15..bbf45f9 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,8 @@ GPLv3 (https://www.gnu.org/licenses/gpl-3.0.html) TODO: - add screens titles -- on searching screen title show which treasure is being searched -- \ No newline at end of file +- add all translations +- w introduction dodać widok-instrukcję z kodem QR +- kopiowanie "assetów" podczas wyświetlania splash screen +- remove dead code +- do not show splash when switching back to app \ No newline at end of file diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/commemorative/n/CommemorativeScreen.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/commemorative/n/CommemorativeScreen.kt index aed1a32..79b361d 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/commemorative/n/CommemorativeScreen.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/commemorative/n/CommemorativeScreen.kt @@ -50,11 +50,12 @@ fun CommemorativeScreen( navController: NavController, navBackStackEntry: NavBackStackEntry, onClickOnGuide: () -> Unit, + goToFacebook: () -> Unit, ) { val scaffoldState: ScaffoldState = rememberScaffoldState() Scaffold( scaffoldState = scaffoldState, - topBar = { TopBar(navController, onClickOnGuide) }, + topBar = { TopBar(navController, onClickOnGuide, goToFacebook) }, content = { CommemorativeScreenBody( navController, diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ElementDescription.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ElementDescription.kt index a05f60f..b0e921e 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ElementDescription.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ElementDescription.kt @@ -1,6 +1,8 @@ package pl.marianjureczko.poszukiwacz.activity.facebook -class ElementDescription( +//TODO: change var to val to avoid missing compose refreshes +data class ElementDescription( + val index: Int, var type: Type, var isSelected: Boolean, val description: String, diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/FacebookViewModel.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/FacebookViewModel.kt index 386068e..de19f20 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/FacebookViewModel.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/FacebookViewModel.kt @@ -9,29 +9,29 @@ import pl.marianjureczko.poszukiwacz.model.Route import pl.marianjureczko.poszukiwacz.model.TreasuresProgress import pl.marianjureczko.poszukiwacz.shared.StorageHelper -class FacebookViewModel(private val state: SavedStateHandle) : ViewModel() { +class FacebookViewModel(private val state: SavedStateHandle) : FacebookReportModel, ViewModel() { private val TAG = javaClass.simpleName - lateinit var progress: TreasuresProgress + override lateinit var progress: TreasuresProgress private set - var hunterPath: HunterPath? = null + override var hunterPath: HunterPath? = null private set lateinit var elements: List private set - lateinit var route: Route + override lateinit var route: Route fun initialize(context: Context, hunterPath: HunterPath?, progress: TreasuresProgress) { this.progress = progress this.hunterPath = hunterPath val elements = mutableListOf() - elements.add(ElementDescription(Type.TREASURES_SUMMARY, true, context.getString(R.string.collected_treasures))) + elements.add(ElementDescription(0, Type.TREASURES_SUMMARY, true, context.getString(R.string.collected_treasures))) val treasure = context.getString(R.string.treasure) progress.commemorativePhotosByTreasuresDescriptionIds.forEach { (id, photo) -> - elements.add(ElementDescription(Type.COMMEMORATIVE_PHOTO, true, "$treasure $id", orderNumber = id, photo = photo)) + elements.add(ElementDescription(0, Type.COMMEMORATIVE_PHOTO, true, "$treasure $id", orderNumber = id, photo = photo)) } - elements.add(ElementDescription(Type.MAP, true, context.getString(R.string.treasures_map))) - elements.add(ElementDescription(Type.MAP_ROUTE, true, context.getString(R.string.route_on_map))) - elements.add(ElementDescription(Type.MAP_SUMMARY, true, context.getString(R.string.treasures_map_summary))) + elements.add(ElementDescription(0, Type.MAP, true, context.getString(R.string.treasures_map))) + elements.add(ElementDescription(0, Type.MAP_ROUTE, true, context.getString(R.string.route_on_map))) + elements.add(ElementDescription(0, Type.MAP_SUMMARY, true, context.getString(R.string.treasures_map_summary))) this.route = StorageHelper(context).loadRoute(progress.routeName) this.elements = elements } @@ -40,13 +40,13 @@ class FacebookViewModel(private val state: SavedStateHandle) : ViewModel() { fun getElementsCount(): Int = elements.size - fun getSummaryElement(): ElementDescription = elements[0] + override fun getSummaryElement(): ElementDescription = elements[0] - fun getCommemorativePhotoElements(): List = elements.filter { it.type == Type.COMMEMORATIVE_PHOTO } + override fun getCommemorativePhotoElements(): List = elements.filter { it.type == Type.COMMEMORATIVE_PHOTO } - fun getMap(): ElementDescription? = elements.find { it.type == Type.MAP } + override fun getMap(): ElementDescription? = elements.find { it.type == Type.MAP } - fun getMapRoute(): ElementDescription? = elements.find { it.type == Type.MAP_ROUTE } + override fun getMapRoute(): ElementDescription? = elements.find { it.type == Type.MAP_ROUTE } - fun getMapSummary(): ElementDescription? = elements.find { it.type == Type.MAP_SUMMARY } + override fun getMapSummary(): ElementDescription? = elements.find { it.type == Type.MAP_SUMMARY } } \ No newline at end of file diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportCommemorativePhotos.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportCommemorativePhotos.kt index 9173912..15744bd 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportCommemorativePhotos.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportCommemorativePhotos.kt @@ -17,7 +17,7 @@ import kotlin.math.min import kotlin.random.Random class ReportCommemorativePhotos( - model: FacebookViewModel, + model: FacebookReportModel, private val font: Typeface, rotationSeed: Long = currentTimeMillis() ) : ReportPart { diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportGenerator.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportGenerator.kt index 6e2bb80..3363747 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportGenerator.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportGenerator.kt @@ -5,17 +5,32 @@ import android.graphics.Bitmap import android.graphics.Canvas import androidx.core.content.res.ResourcesCompat import pl.marianjureczko.poszukiwacz.R +import pl.marianjureczko.poszukiwacz.model.HunterPath +import pl.marianjureczko.poszukiwacz.model.Route +import pl.marianjureczko.poszukiwacz.model.TreasuresProgress import java.util.Collections interface ReportPart { fun height(): Float } +interface FacebookReportModel { + fun getSummaryElement(): ElementDescription + fun getCommemorativePhotoElements(): List + fun getMap(): ElementDescription? + fun getMapSummary(): ElementDescription? + fun getMapRoute(): ElementDescription? + + val hunterPath: HunterPath? + val route: Route + val progress: TreasuresProgress +} + class ReportGenerator { /** * @return it is returned for testing purposes */ - fun create(context: Context, model: FacebookViewModel, reportPublisher: (Bitmap) -> Unit): Bitmap { + fun create(context: Context, model: FacebookReportModel, reportPublisher: (Bitmap) -> Unit): Bitmap { val typeface = ResourcesCompat.getFont(context, R.font.akaya_telivigala)!! val title = ReportTitle(model, typeface) val summary = ReportSummary(model, typeface) @@ -24,7 +39,8 @@ class ReportGenerator { val map = ReportMap(model) val mapSummary = ReportMapSummary(model, typeface) val footer = ReportFooter() - val height = title.height() + summary.height() + commemorativePhotos.height() + mapHeader.height() + map.height() + mapSummary.height() + footer.height() + val height = + title.height() + summary.height() + commemorativePhotos.height() + mapHeader.height() + map.height() + mapSummary.height() + footer.height() val bitmap = Bitmap.createBitmap(ReportCommons.REPORT_WIDTH, height.toInt(), Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMap.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMap.kt index 1810a1a..16f0cfe 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMap.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMap.kt @@ -22,7 +22,7 @@ import pl.marianjureczko.poszukiwacz.model.TreasuresProgress class ReportMap( - private val model: FacebookViewModel + private val model: FacebookReportModel ) : ReportPart { companion object { diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMapHeader.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMapHeader.kt index 7fa2964..9e1d9e8 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMapHeader.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMapHeader.kt @@ -6,7 +6,7 @@ import android.graphics.Typeface import pl.marianjureczko.poszukiwacz.R class ReportMapHeader( - private val model: FacebookViewModel, + private val model: FacebookReportModel, private val font: Typeface ) : ReportPart { override fun height(): Float { diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMapSummary.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMapSummary.kt index ebb080b..e3c6dad 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMapSummary.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportMapSummary.kt @@ -11,7 +11,7 @@ import java.text.DateFormat import java.util.Locale class ReportMapSummary( - private val model: FacebookViewModel, + private val model: FacebookReportModel, private val font: Typeface ) : ReportPart { diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportSummary.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportSummary.kt index cee1a97..0e0ca5c 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportSummary.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportSummary.kt @@ -8,7 +8,7 @@ import pl.marianjureczko.poszukiwacz.R import pl.marianjureczko.poszukiwacz.model.TreasuresProgress class ReportSummary( - private val model: FacebookViewModel, + private val model: FacebookReportModel, private val font: Typeface ) : ReportPart { diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportTitle.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportTitle.kt index e9e9685..4f00144 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportTitle.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/ReportTitle.kt @@ -2,14 +2,13 @@ package pl.marianjureczko.poszukiwacz.activity.facebook import android.content.Context import android.graphics.Canvas -import android.graphics.Color import android.graphics.Paint import android.graphics.Typeface import pl.marianjureczko.poszukiwacz.R import pl.marianjureczko.poszukiwacz.model.TreasuresProgress class ReportTitle( - private val model: FacebookViewModel, + private val model: FacebookReportModel, private val font: Typeface ) : ReportPart { override fun height(): Float = 150f diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookHelper.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookHelper.kt new file mode 100644 index 0000000..0bb852f --- /dev/null +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookHelper.kt @@ -0,0 +1,38 @@ +package pl.marianjureczko.poszukiwacz.activity.facebook.n + +import android.content.Context +import android.content.pm.PackageManager +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.navigation.NavHostController +import pl.marianjureczko.poszukiwacz.R +import pl.marianjureczko.poszukiwacz.activity.main.FACEBOOK_PATH + +object FacebookHelper { + private const val facebookPackage = "com.facebook.katana" + @Composable + fun createFacebookCallback(navController: NavHostController): () -> Unit { + val context = LocalContext.current + val noFacebookErrorMsg = stringResource(id = R.string.facebook_share_impossible) + val goToFacebook = { +// if (isFacebookInstalled(context)) { + navController.navigate(FACEBOOK_PATH) +// } else { +// Toast.makeText(App.getAppContext(), noFacebookErrorMsg, Toast.LENGTH_LONG).show() +// } + } + return goToFacebook + } + + private fun isFacebookInstalled(context: Context): Boolean { + val packageManager = context.packageManager + return try { + //the not deprecated version requires API 33 + packageManager.getPackageInfo(facebookPackage, PackageManager.GET_ACTIVITIES) + true + } catch (e: PackageManager.NameNotFoundException) { + false + } + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookScreen.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookScreen.kt new file mode 100644 index 0000000..3620f5b --- /dev/null +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookScreen.kt @@ -0,0 +1,235 @@ +package pl.marianjureczko.poszukiwacz.activity.facebook.n + +import android.annotation.SuppressLint +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.net.Uri +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Card +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.material.ScaffoldState +import androidx.compose.material.Text +import androidx.compose.material.rememberScaffoldState +import androidx.compose.runtime.Composable +import androidx.compose.ui.AbsoluteAlignment +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.core.content.FileProvider +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavController +import pl.marianjureczko.poszukiwacz.R +import pl.marianjureczko.poszukiwacz.activity.facebook.ElementDescription +import pl.marianjureczko.poszukiwacz.activity.facebook.FacebookReportModel +import pl.marianjureczko.poszukiwacz.activity.facebook.ReportGenerator +import pl.marianjureczko.poszukiwacz.shared.PhotoHelper +import pl.marianjureczko.poszukiwacz.ui.components.AdvertBanner +import pl.marianjureczko.poszukiwacz.ui.components.LargeButton +import pl.marianjureczko.poszukiwacz.ui.components.TopBar +import pl.marianjureczko.poszukiwacz.ui.theme.FANCY_FONT +import pl.marianjureczko.poszukiwacz.ui.theme.Typography +import java.io.File +import java.io.FileOutputStream + + +@SuppressLint("UnusedMaterialScaffoldPaddingParameter") +@Composable +fun FacebookScreen( + navController: NavController, + navBackStackEntry: NavBackStackEntry, + onClickOnGuide: () -> Unit +) { + val scaffoldState: ScaffoldState = rememberScaffoldState() + Scaffold( + scaffoldState = scaffoldState, + topBar = { TopBar(navController, onClickOnGuide, {}) }, + content = { FacebookScreenBody(navController) } + ) +} + +@Composable +fun FacebookScreenBody(navController: NavController) { + val viewModel: FacebookViewModel = hiltViewModel() + val state: FacebookState = viewModel.state.value + + + Column(Modifier.background(Color.White)) { + SubHeader() + Elements(Modifier.weight(0.99f), state, viewModel, {viewModel.rotatePhoto(it)}) + Spacer(modifier = Modifier.weight(0.01f)) + ShareOnFacebookButton(state) + AdvertBanner() + } +} + +@Composable +private fun SubHeader() { + Text( + stringResource(R.string.facebook_screen_subheader), + modifier = Modifier.fillMaxWidth(), + style = MaterialTheme.typography.h5, + textAlign = TextAlign.Center, + color = Color.Black, + fontFamily = FANCY_FONT, + ) +} + +@Composable +private fun Elements( + modifier: Modifier, + state: FacebookState, + viewModel: FacebookViewModel, + onRotatePhoto: (String) -> Unit +) { + LazyColumn( + contentPadding = PaddingValues(vertical = 8.dp, horizontal = 8.dp), + modifier = modifier + ) { + items(state.elements) { + FacebookElement(it, viewModel, onRotatePhoto) + } + } +} + +@Composable +private fun ShareOnFacebookButton(model: FacebookReportModel) { + Box() { + val context = LocalContext.current + LargeButton(R.string.share_button) { + ReportGenerator().create(context, model) { bitmap -> + FacebookShareHelper.shareBitmapOnFacebook(context, bitmap) + } + } + FacebookImage(Modifier.align(AbsoluteAlignment.CenterLeft)) + FacebookImage(Modifier.align(AbsoluteAlignment.CenterRight)) + } +} + +@Composable +private fun FacebookImage(modifier: Modifier) { + Image( + painter = painterResource(id = R.drawable.facebook), + contentDescription = "Share on Facebook icon", + modifier = modifier + .height(50.dp) + .padding(10.dp), + contentScale = ContentScale.Inside + ) +} + +@Composable +fun FacebookElement(it: ElementDescription, viewModel: FacebookViewModel, onRotatePhoto: (String) -> Unit) { + Card( + elevation = 4.dp, + modifier = Modifier.padding(4.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start, + modifier = Modifier + .padding(8.dp) + .fillMaxWidth() + ) { + val imageId: Int = if (it.isSelected) { + R.drawable.checkbox_checked + } else { + R.drawable.checkbox_empty + } + Image( + painterResource(imageId), + modifier = Modifier + .padding(2.dp) + .height(40.dp) + .clickable { viewModel.changeSelectionAt(it.index) }, + contentDescription = "Change treasure button", + contentScale = ContentScale.Inside, + ) + Text( + text = it.description, + fontFamily = FANCY_FONT, + fontSize = Typography.h6.fontSize + ) + it.photo?.let { photoFile -> + val imageBitmap = renderPhoto(photoFile).asImageBitmap() + Image( + modifier = Modifier.padding(8.dp), + painter = BitmapPainter(imageBitmap), + contentDescription = "Small photo" + ) + Image( + painter = painterResource(id = R.drawable.rotate_arc), + contentDescription = "Rotate photo", + modifier = Modifier + .padding(1.dp) + .height(60.dp) + .clickable { onRotatePhoto(photoFile) }, + contentScale = ContentScale.Inside + ) + } + } + } +} + +private fun renderPhoto(photoFile: String): Bitmap { + val photo = BitmapFactory.decodeFile(photoFile) + return PhotoHelper.scalePhotoKeepRatio(photo, 250f, 300f) +} + +object FacebookShareHelper { + + fun shareBitmapOnFacebook(context: Context, bitmap: Bitmap) { + val uri = bitmapToUri(context, bitmap) + if (uri != null) { + shareContent(context, uri) + } else { + // Handle error: Unable to convert Bitmap to Uri + } + } + + private fun bitmapToUri(context: Context, bitmap: Bitmap): Uri? { + val file = File(context.cacheDir, "shared_bitmap.png") + try { + val outputStream = FileOutputStream(file) + bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream) + outputStream.flush() + outputStream.close() + return FileProvider.getUriForFile(context, context.packageName + ".fileprovider", file) + } catch (e: Exception) { + e.printStackTrace() + } + return null + } + + private fun shareContent(context: Context, contentUri: Uri) { + val shareIntent = Intent(Intent.ACTION_SEND) + shareIntent.type = "image/*" + shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri) + shareIntent.`package` = "com.facebook.katana" // Specify Facebook package + context.startActivity(shareIntent) + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookState.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookState.kt new file mode 100644 index 0000000..4f74757 --- /dev/null +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookState.kt @@ -0,0 +1,39 @@ +package pl.marianjureczko.poszukiwacz.activity.facebook.n + +import pl.marianjureczko.poszukiwacz.activity.facebook.ElementDescription +import pl.marianjureczko.poszukiwacz.activity.facebook.FacebookReportModel +import pl.marianjureczko.poszukiwacz.activity.facebook.Type +import pl.marianjureczko.poszukiwacz.model.HunterPath +import pl.marianjureczko.poszukiwacz.model.Route +import pl.marianjureczko.poszukiwacz.model.TreasuresProgress +import java.util.Random + + +//TODO: chack if facebook works when no path data is persisted yet +data class FacebookState( + override val hunterPath: HunterPath?, + override val progress: TreasuresProgress, + override val route: Route, + val elements: List, + val recompose: Int = Random().nextInt() +) : FacebookReportModel { + override fun getSummaryElement(): ElementDescription { + return elements[0] + } + + override fun getCommemorativePhotoElements(): List { + return elements.filter { it.type == Type.COMMEMORATIVE_PHOTO } + } + + override fun getMap(): ElementDescription? { + return elements.find { it.type == Type.MAP } + } + + override fun getMapSummary(): ElementDescription? { + return elements.find { it.type == Type.MAP_SUMMARY } + } + + override fun getMapRoute(): ElementDescription? { + return elements.find { it.type == Type.MAP_ROUTE } + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookViewModel.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookViewModel.kt new file mode 100644 index 0000000..d1e1be8 --- /dev/null +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/facebook/n/FacebookViewModel.kt @@ -0,0 +1,71 @@ +package pl.marianjureczko.poszukiwacz.activity.facebook.n + +import android.content.res.Resources +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.launch +import pl.marianjureczko.poszukiwacz.R +import pl.marianjureczko.poszukiwacz.activity.facebook.ElementDescription +import pl.marianjureczko.poszukiwacz.activity.facebook.Type +import pl.marianjureczko.poszukiwacz.model.TreasuresProgress +import pl.marianjureczko.poszukiwacz.shared.PhotoHelper +import pl.marianjureczko.poszukiwacz.shared.StorageHelper +import java.util.Random +import javax.inject.Inject + +//TODO: should be configurable for the sake of classic version +private const val ROUTE_NAME = "custom" +@HiltViewModel +class FacebookViewModel @Inject constructor( + private val storageHelper: StorageHelper, + private val resources: Resources, + private val dispatcher: CoroutineDispatcher +) : ViewModel() { + + private var _state: MutableState = mutableStateOf(createState()) + + val state: State + get() = _state + + fun changeSelectionAt(index:Int) { + val updated = state.value.elements.toMutableList() + updated[index] = updated[index].copy(isSelected = !updated[index].isSelected) + _state.value = state.value.copy(elements = updated.toList()) + } + + fun rotatePhoto(photoFile: String){ + viewModelScope.launch(dispatcher) { + PhotoHelper.rotateGraphicClockwise(photoFile) { + recompose() + } + } + } + + private fun createState(): FacebookState { + var index = 0 + val progress = storageHelper.loadProgress(ROUTE_NAME) ?: TreasuresProgress(ROUTE_NAME) + val path = storageHelper.loadHunterPath(ROUTE_NAME) + val route = storageHelper.loadRoute(ROUTE_NAME) + + val elements = mutableListOf() + elements.add(ElementDescription(index++, Type.TREASURES_SUMMARY, true, resources.getString(R.string.collected_treasures))) + val treasure = resources.getString(R.string.treasure) + progress.commemorativePhotosByTreasuresDescriptionIds.forEach { (id, photo) -> + elements.add(ElementDescription(index++, Type.COMMEMORATIVE_PHOTO, true, "$treasure $id", orderNumber = id, photo = photo)) + } + elements.add(ElementDescription(index++, Type.MAP, true, resources.getString(R.string.treasures_map))) + elements.add(ElementDescription(index++, Type.MAP_ROUTE, true, resources.getString(R.string.route_on_map))) + elements.add(ElementDescription(index++, Type.MAP_SUMMARY, true, resources.getString(R.string.treasures_map_summary))) + + return FacebookState(path, progress, route, elements) + } + + private fun recompose() { + _state.value = state.value.copy(recompose = Random().nextInt()) + } +} \ No newline at end of file diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/CustomScreenBody.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/CustomScreenBody.kt index 0773e0b..187af9d 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/CustomScreenBody.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/CustomScreenBody.kt @@ -1,6 +1,7 @@ package pl.marianjureczko.poszukiwacz.activity.main import android.content.res.Resources +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -11,6 +12,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ButtonDefaults import androidx.compose.material.MaterialTheme import androidx.compose.material.OutlinedButton import androidx.compose.material.Text @@ -31,6 +33,7 @@ import pl.marianjureczko.poszukiwacz.ui.components.LargeButton import pl.marianjureczko.poszukiwacz.ui.theme.PrimaryBackground /** Kalinowice */ +//TODO t: use stringResource @Composable fun CustomScreenBody(resources: Resources, goToSearching: (String) -> Unit) { val viewModel: CustomMainViewModel = hiltViewModel() @@ -92,12 +95,19 @@ private fun NextButton(viewModel: CustomMainViewModel) { OutlinedButton( shape = RoundedCornerShape(50), onClick = { viewModel.nextLeadMessage() }, + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.White, + contentColor = Color.Black + ), + border = BorderStroke(2.dp, Color.LightGray), // Border color and thickness + elevation = ButtonDefaults.elevation(4.dp), +// modifier = Modifier.colo(Color.Gray), content = { Image( imageVector = Icons.Rounded.ArrowForward, contentDescription = null, modifier = Modifier.background(color = Color.Transparent), - colorFilter = ColorFilter.tint(PrimaryBackground) + colorFilter = ColorFilter.tint(Color.Black) ) } ) diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/MainActivity.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/MainActivity.kt index 9ba0c56..03a13b5 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/MainActivity.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/MainActivity.kt @@ -19,6 +19,8 @@ import dagger.hilt.android.AndroidEntryPoint import pl.marianjureczko.poszukiwacz.R import pl.marianjureczko.poszukiwacz.activity.commemorative.n.CommemorativeScreen import pl.marianjureczko.poszukiwacz.activity.commemorative.n.PARAMETER_TREASURE_DESCRIPTION_ID +import pl.marianjureczko.poszukiwacz.activity.facebook.n.FacebookHelper +import pl.marianjureczko.poszukiwacz.activity.facebook.n.FacebookScreen import pl.marianjureczko.poszukiwacz.activity.map.n.MapScreen import pl.marianjureczko.poszukiwacz.activity.map.n.PARAMETER_ROUTE_NAME_2 import pl.marianjureczko.poszukiwacz.activity.photo.n.PARAMETER_TIP_PHOTO @@ -44,6 +46,8 @@ val SELECTOR_PATH = "selector" val SELECTOR_ROUTE = "$SELECTOR_PATH/{$PARAMETER_JUST_FOUND_TREASURE}" val COMMEMORATIVE_PATH = "commemorative" val COMMEMORATIVE_ROUTE = "$COMMEMORATIVE_PATH/{$PARAMETER_TREASURE_DESCRIPTION_ID}" +val FACEBOOK_PATH = "facebook" +val FACEBOOK_ROUTE = "$FACEBOOK_PATH" /** * Routes creation and selection activity @@ -52,6 +56,7 @@ val COMMEMORATIVE_ROUTE = "$COMMEMORATIVE_PATH/{$PARAMETER_TREASURE_DESCRIPTION_ @AndroidEntryPoint class MainActivity : PermissionActivity() { private val TAG = javaClass.simpleName + @Inject lateinit var settings: Settings @@ -99,9 +104,11 @@ class MainActivity : PermissionActivity() { @Composable private fun ComposeRoot(settings: Settings, resources: Resources, onClickGuide: () -> Unit) { val navController = rememberNavController() + val goToFacebook = FacebookHelper.createFacebookCallback(navController) + NavHost(navController, startDestination = "main") { composable(route = "main") { - MainScreen(navController, settings.isClassicMode(), resources, onClickGuide) { routeName -> + MainScreen(navController, settings.isClassicMode(), resources, onClickGuide, goToFacebook) { routeName -> navController.navigate("$SEARCHING_PATH/$routeName") } } @@ -118,7 +125,8 @@ private fun ComposeRoot(settings: Settings, resources: Resources, onClickGuide: goToTipPhoto = { navController.navigate("tipPhoto/$it") }, goToResult = { resultType, treasureId -> navController.navigate("$RESULTS_PATH/$resultType/$treasureId") }, goToMap = { navController.navigate("map/$it") }, - goToTreasureSelector = { navController.navigate("$SELECTOR_PATH/$it") } + goToTreasureSelector = { navController.navigate("$SELECTOR_PATH/$it") }, + goToFacebook = goToFacebook ) } composable( @@ -127,33 +135,48 @@ private fun ComposeRoot(settings: Settings, resources: Resources, onClickGuide: navArgument(PARAMETER_RESULT_TYPE) { type = NavType.EnumType(ResultType::class.java) }, navArgument(PARAMETER_TREASURE_ID) { type = NavType.IntType } ) - ) { navBackStackEntry -> ResultScreen(navController, navBackStackEntry, onClickGuide) } + ) { navBackStackEntry -> ResultScreen(navController, navBackStackEntry, onClickGuide, goToFacebook) } composable( route = "tipPhoto/{$PARAMETER_TIP_PHOTO}", arguments = listOf(navArgument(PARAMETER_TIP_PHOTO) { type = NavType.StringType }) ) { - TipPhotoScreen(navController = navController, onClickOnGuide = onClickGuide) + TipPhotoScreen( + navController = navController, + onClickOnGuide = onClickGuide, + onClickOnFacebook = goToFacebook + ) } composable( route = "map/{$PARAMETER_ROUTE_NAME_2}", arguments = listOf(navArgument(PARAMETER_ROUTE_NAME) { type = NavType.StringType }), ) { - MapScreen(navController = navController, onClickOnGuide = onClickGuide, resources = resources) + MapScreen( + navController = navController, + onClickOnGuide = onClickGuide, + resources = resources, + onClickOnFacebook = goToFacebook + ) } composable( route = SELECTOR_ROUTE, arguments = listOf(navArgument(PARAMETER_JUST_FOUND_TREASURE) { type = NavType.IntType }), - ) { navBackStackEntry -> SelectorScreen( - navController, - navBackStackEntry, - resources, - onClickGuide, - goToResult = { treasureId -> navController.navigate("$RESULTS_PATH/${ResultType.TREASURE}/$treasureId") }, - goToCommemorative = {treasureId -> navController.navigate("$COMMEMORATIVE_PATH/$treasureId")} - ) } + ) { navBackStackEntry -> + SelectorScreen( + navController, + navBackStackEntry, + resources, + onClickGuide, + goToResult = { treasureId -> navController.navigate("$RESULTS_PATH/${ResultType.TREASURE}/$treasureId") }, + goToCommemorative = { treasureId -> navController.navigate("$COMMEMORATIVE_PATH/$treasureId") }, + onClickOnFacebook = goToFacebook + ) + } composable( route = COMMEMORATIVE_ROUTE, arguments = listOf(navArgument(PARAMETER_TREASURE_DESCRIPTION_ID) { type = NavType.IntType }) - ) { navBackStackEntry -> CommemorativeScreen(navController, navBackStackEntry, onClickGuide) } + ) { navBackStackEntry -> CommemorativeScreen(navController, navBackStackEntry, onClickGuide, goToFacebook) } + composable( + route = FACEBOOK_ROUTE, + ) { navBackStackEntry -> FacebookScreen(navController, navBackStackEntry, onClickGuide) } } } \ No newline at end of file diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/MainScreen.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/MainScreen.kt index 8a2e8a6..23e30a4 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/MainScreen.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/main/MainScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.runtime.Composable import androidx.navigation.NavController import pl.marianjureczko.poszukiwacz.ui.components.TopBar +//TODO: add sample qr code to introduction @SuppressLint("UnusedMaterialScaffoldPaddingParameter") @Composable fun MainScreen( @@ -14,10 +15,11 @@ fun MainScreen( isClassic: Boolean, resources: Resources, onClickOnGuide: () -> Unit, + onClickOnFacebook: () -> Unit, goToSearching: (String) -> Unit ) { Scaffold( - topBar = { TopBar(navController, onClickOnGuide) }, + topBar = { TopBar(navController, onClickOnGuide, onClickOnFacebook) }, content = { _ -> if (isClassic) { ClassicScreenBody(goToSearching) diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/map/n/MapScreen.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/map/n/MapScreen.kt index c5e0554..2f3562f 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/map/n/MapScreen.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/map/n/MapScreen.kt @@ -21,11 +21,13 @@ import pl.marianjureczko.poszukiwacz.ui.components.TopBar @Composable fun MapScreen( navController: NavController, + //TODO t: use StringResource instead resources: Resources, - onClickOnGuide: () -> Unit + onClickOnGuide: () -> Unit, + onClickOnFacebook: () -> Unit ) { Scaffold( - topBar = { TopBar(navController, onClickOnGuide) }, + topBar = { TopBar(navController, onClickOnGuide, onClickOnFacebook) }, content = { MapScreenBody(resources) } diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/photo/n/TipPhotoScreen.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/photo/n/TipPhotoScreen.kt index e7be190..2d058d8 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/photo/n/TipPhotoScreen.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/photo/n/TipPhotoScreen.kt @@ -28,10 +28,11 @@ import pl.marianjureczko.poszukiwacz.ui.theme.SecondaryBackground @Composable fun TipPhotoScreen( navController: NavController, - onClickOnGuide: () -> Unit + onClickOnGuide: () -> Unit, + onClickOnFacebook: () -> Unit ) { Scaffold( - topBar = { TopBar(navController, onClickOnGuide) }, + topBar = { TopBar(navController, onClickOnGuide, onClickOnFacebook) }, content = { TipPhotoScreenBody() } diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/result/n/ResultScreen.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/result/n/ResultScreen.kt index c74fa70..6ffebee 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/result/n/ResultScreen.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/result/n/ResultScreen.kt @@ -51,10 +51,11 @@ private const val SUBTITLES_MIME_TYPE = "application/x-subrip" fun ResultScreen( navController: NavController, navBackStackEntry: NavBackStackEntry, - onClickOnGuide: () -> Unit + onClickOnGuide: () -> Unit, + onClickOnFacebook: () -> Unit ) { Scaffold( - topBar = { TopBar(navController, onClickOnGuide) }, + topBar = { TopBar(navController, onClickOnGuide, onClickOnFacebook) }, content = { ResultScreenBody(shareViewModelStoreOwner(navBackStackEntry, navController)) } @@ -80,7 +81,8 @@ fun ResultScreenBody(viewModelStoreOwner: NavBackStackEntry) { localViewModel, localState.moviePath, localState.subtitlesLine, - localState.subtitlesPath + localState.subtitlesPath, + localState.localesWithSubtitles ) { localViewModel.setSubtitlesLine(it) } } else { Message(localState) @@ -123,6 +125,7 @@ private fun Movie( moviePath: String = "/data/user/0/pl.marianjureczko.poszukiwacz.kalinowice/files/treasures_lists/kalinowice_01.mp4", subtitlesLine: String? = null, subtitlesPath: String? = null, + localesWithSubtitles: Boolean = false, updateSubtitlesLine: (String) -> Unit = {} ) { Column( @@ -136,18 +139,21 @@ private fun Movie( ) { val context = LocalContext.current val videoView: VideoView = remember { VideoView(context) } - Video(videoView, subtitlesPath, updateSubtitlesLine, movieController, moviePath) + Video(videoView, subtitlesPath, updateSubtitlesLine, movieController, moviePath, localesWithSubtitles) PlayButton(isPlayVisible, videoView, movieController) - subtitlesLine?.let { - Text( - fontSize = 45.sp, - fontFamily = FANCY_FONT, - color = Color.White, - textAlign = TextAlign.Center, - text = it, - modifier = Modifier.align(Alignment.BottomCenter), - style = TextStyle(shadow = Shadow(color = Color.Black, blurRadius = 12f)) - ) + //TODO t: merge conditions, and maybe move to state + if (localesWithSubtitles) { + subtitlesLine?.let { + Text( + fontSize = 45.sp, + fontFamily = FANCY_FONT, + color = Color.White, + textAlign = TextAlign.Center, + text = it, + modifier = Modifier.align(Alignment.BottomCenter), + style = TextStyle(shadow = Shadow(color = Color.Black, blurRadius = 12f)) + ) + } } } } @@ -159,18 +165,22 @@ private fun Video( subtitlesPath: String?, updateSubtitlesLine: (String) -> Unit, movieController: MovieController, - moviePath: String + moviePath: String, + localesWithSubtitles: Boolean ) { videoView.setOnPreparedListener { mediaPlayer -> - subtitlesPath?.let { - mediaPlayer.addTimedTextSource(subtitlesPath, SUBTITLES_MIME_TYPE) - val textTrackIndex: Int = findTrackIndexFor( - TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT, mediaPlayer.getTrackInfo() - ) - if (textTrackIndex >= 0) { - mediaPlayer.selectTrack(textTrackIndex); + //TODO t: merge conditions, and maybe move to state + if (localesWithSubtitles) { + subtitlesPath?.let { + mediaPlayer.addTimedTextSource(subtitlesPath, SUBTITLES_MIME_TYPE) + val textTrackIndex: Int = findTrackIndexFor( + TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT, mediaPlayer.getTrackInfo() + ) + if (textTrackIndex >= 0) { + mediaPlayer.selectTrack(textTrackIndex) + } + mediaPlayer.setOnTimedTextListener { _, text -> updateSubtitlesLine(text.text) } } - mediaPlayer.setOnTimedTextListener { _, text -> updateSubtitlesLine(text.text) } } } AndroidView( diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SearchingScreen.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SearchingScreen.kt index 7ada22b..f83bff4 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SearchingScreen.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SearchingScreen.kt @@ -66,13 +66,14 @@ fun SearchingScreen( goToTipPhoto: (String) -> Unit, goToResult: (ResultType, Int) -> Unit, goToMap: (String) -> Unit, - goToTreasureSelector: (Int) -> Unit + goToTreasureSelector: (Int) -> Unit, + goToFacebook: () -> Unit ) { val scaffoldState: ScaffoldState = rememberScaffoldState() Scaffold( scaffoldState = scaffoldState, - topBar = { TopBar(navController, onClickOnGuide) }, + topBar = { TopBar(navController, onClickOnGuide, goToFacebook) }, content = { SearchingScreenBody( navController, diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SharedState.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SharedState.kt index ebdcca0..a8e7733 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SharedState.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SharedState.kt @@ -2,9 +2,11 @@ package pl.marianjureczko.poszukiwacz.activity.searching.n import android.location.Location import android.media.MediaPlayer +import pl.marianjureczko.poszukiwacz.model.HunterPath import pl.marianjureczko.poszukiwacz.model.Route import pl.marianjureczko.poszukiwacz.model.TreasureDescription import pl.marianjureczko.poszukiwacz.model.TreasuresProgress + interface SelectorSharedState { val route: Route val currentLocation: Location? @@ -21,6 +23,7 @@ interface SearchingSharedState { val currentLocation: Location? val stepsToTreasure: Int? var needleRotation: Float + var hunterPath: HunterPath fun treasureFoundAndResultAlreadyPresented(): Boolean } @@ -37,13 +40,14 @@ data class SharedState( override var treasuresProgress: TreasuresProgress, override var currentLocation: Location?, override var stepsToTreasure: Int?, + override var hunterPath: HunterPath, override var needleRotation: Float = 0.0f, override val distancesInSteps: Map = route.treasures .associate { it.id to null } .toMap() ) : SelectorSharedState, SearchingSharedState, CommemorativeSharedState { - constructor(mediaPlayer: MediaPlayer, route: Route, treasuresProgress: TreasuresProgress) : - this(mediaPlayer, route, route.treasures[0], treasuresProgress, null, null) + constructor(mediaPlayer: MediaPlayer, route: Route, treasuresProgress: TreasuresProgress, hunterPath: HunterPath) : + this(mediaPlayer, route, route.treasures[0], treasuresProgress, null, null, hunterPath) override fun isTreasureCollected(treasureId: Int): Boolean = treasuresProgress.collectedTreasuresDescriptionId.contains(treasureId) diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SharedViewModel.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SharedViewModel.kt index 232e8a9..b604bce 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SharedViewModel.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/searching/n/SharedViewModel.kt @@ -17,6 +17,8 @@ import pl.marianjureczko.poszukiwacz.activity.result.n.NOTHING_FOUND_TREASURE_ID import pl.marianjureczko.poszukiwacz.activity.result.n.ResultType import pl.marianjureczko.poszukiwacz.activity.searching.ArcCalculator import pl.marianjureczko.poszukiwacz.activity.searching.LocationCalculator +import pl.marianjureczko.poszukiwacz.activity.treasureselector.Coordinates +import pl.marianjureczko.poszukiwacz.model.HunterPath import pl.marianjureczko.poszukiwacz.model.Route import pl.marianjureczko.poszukiwacz.model.Treasure import pl.marianjureczko.poszukiwacz.model.TreasureDescription @@ -171,6 +173,10 @@ class SharedViewModel @Inject constructor( .associate { it.id to locationCalculator.distanceInSteps(it, location) } .toMap() ) + val currentCoordinates = Coordinates(location.latitude, location.longitude) + if (state.value.hunterPath.addLocation(currentCoordinates)) { + storageHelper.save(state.value.hunterPath) + } } } @@ -178,20 +184,14 @@ class SharedViewModel @Inject constructor( Log.i(TAG, "Create state") val route = loadRoute() val treasuresProgress = loadProgress(route.name) + val hunterPath = loadHunterPath(route.name) val mediaPlayer = MediaPlayer() mediaPlayer.isLooping = false mediaPlayer.setOnErrorListener { mp, what, extra -> handleMediaPlayerError(what, extra) } - return SharedState(mediaPlayer, route, treasuresProgress) + return SharedState(mediaPlayer, route, treasuresProgress, hunterPath) } private fun loadRoute(): Route { -// return Route( -// "Kalinowice", mutableListOf( -// TreasureDescription( -// 1, 25.1, 26.1, "g01abc", null, null -// ) -// ) -// ) return storageHelper.loadRoute(stateHandle.get(PARAMETER_ROUTE_NAME)!!) } @@ -203,19 +203,15 @@ class SharedViewModel @Inject constructor( } return loadedProgress } -// fun loadProgressFromStorage(storageHelper: StorageHelper) { -// var loadedProgress = storageHelper.loadProgress(route.name) -// if (loadedProgress == null) { -// loadedProgress = TreasuresProgress(route.name) -// storageHelper.save(loadedProgress) -// } -// treasuresProgress = loadedProgress -// hunterPath = storageHelper.loadHunterPath(route.name) -// if(hunterPath == null) { -// hunterPath = HunterPath(route.name) -// storageHelper.save(hunterPath!!) -// } -// } + + private fun loadHunterPath(routeName: String): HunterPath { + var hunterPath = storageHelper.loadHunterPath(routeName) + if (hunterPath == null) { + hunterPath = HunterPath(routeName) + storageHelper.save(hunterPath) + } + return hunterPath + } private fun handleMediaPlayerError(what: Int, extra: Int): Boolean { when (what) { diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/treasureselector/n/SelectorScreen.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/treasureselector/n/SelectorScreen.kt index 8a11042..5143c4b 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/treasureselector/n/SelectorScreen.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/activity/treasureselector/n/SelectorScreen.kt @@ -58,12 +58,13 @@ fun SelectorScreen( resources: Resources, onClickOnGuide: () -> Unit, goToResult: (Int) -> Unit, - goToCommemorative: (Int) -> Unit + goToCommemorative: (Int) -> Unit, + onClickOnFacebook: () -> Unit ) { val scaffoldState: ScaffoldState = rememberScaffoldState() Scaffold( scaffoldState = scaffoldState, - topBar = { TopBar(navController, onClickOnGuide) }, + topBar = { TopBar(navController, onClickOnGuide, onClickOnFacebook) }, content = { SelectorScreenBody( navController, diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/ui/components/LargeButton.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/ui/components/LargeButton.kt index 7709e3d..0c5f198 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/ui/components/LargeButton.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/ui/components/LargeButton.kt @@ -1,20 +1,33 @@ package pl.marianjureczko.poszukiwacz.ui.components +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.shape.CutCornerShape +import androidx.compose.material.ButtonDefaults import androidx.compose.material.OutlinedButton import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import pl.marianjureczko.poszukiwacz.App +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp @Composable fun LargeButton(title: Int, onClick: () -> Unit) { OutlinedButton( shape = CutCornerShape(percent = 25), modifier = Modifier.fillMaxWidth(), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color.White, + contentColor = Color.Black + ), + border = BorderStroke(2.dp, Color.LightGray), + elevation = ButtonDefaults.elevation(4.dp), onClick = onClick ) { - Text(App.getResources().getString(title)) + Text( + stringResource(title), + color = Color.Black + ) } } \ No newline at end of file diff --git a/app/src/main/java/pl/marianjureczko/poszukiwacz/ui/components/TopBar.kt b/app/src/main/java/pl/marianjureczko/poszukiwacz/ui/components/TopBar.kt index 4b3a73e..3ed76f9 100644 --- a/app/src/main/java/pl/marianjureczko/poszukiwacz/ui/components/TopBar.kt +++ b/app/src/main/java/pl/marianjureczko/poszukiwacz/ui/components/TopBar.kt @@ -32,7 +32,7 @@ import pl.marianjureczko.poszukiwacz.R import pl.marianjureczko.poszukiwacz.ui.theme.Primary @Composable -fun TopBar(navController: NavController, onClickOnGuide: () -> Unit) { +fun TopBar(navController: NavController, onClickOnGuide: () -> Unit, onClickOnFacebook: () -> Unit) { val showMenu = remember { mutableStateOf(false) } TopAppBar( backgroundColor = Primary, @@ -53,7 +53,7 @@ fun TopBar(navController: NavController, onClickOnGuide: () -> Unit) { onDismissRequest = { showMenu.value = false } ) { MenuEntry(R.drawable.question_mark, R.string.menu_help, onClickOnGuide) - MenuEntry(R.drawable.facebook, R.string.menu_facebook) { /* TODO */ } + MenuEntry(R.drawable.facebook, R.string.menu_facebook, onClickOnFacebook) } }, diff --git a/app/src/main/res/layout/activity_facebook.xml b/app/src/main/res/layout/activity_facebook.xml index 1d4ac08..140b498 100644 --- a/app/src/main/res/layout/activity_facebook.xml +++ b/app/src/main/res/layout/activity_facebook.xml @@ -17,7 +17,7 @@ android:padding="4dp" android:textSize="20sp" android:gravity="center" - android:text="@string/facebook_activity_header" /> + android:text="@string/facebook_screen_subheader" /> Instrukcja obsługi Opublikuj na Facebook Opublikuj na Facebook - Wybierz elementy do opublikowania + Wybierz elementy do opublikowania Opublikuj Zrezygnowano z publikacji Opublikowano - Udostępnienie jest niemożliwe. Proszę, sprawdź czy aplikacja Facebook jest zainstalowana i czy przyznane są uprawnienia. + Nie znaleziono aplikacji Facebook. Proszę, sprawdź czy jest zainstalowana i czy przyznano uprawnienia. "Wystąpił błąd podczas publikowania. Aplikacja Facebook odpowiedziała: " Wybierz trasę do udostępnienia Nie można opublikować tej trasy diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4c457d7..fccbb34 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -77,11 +77,11 @@ Share on Facebook 732722584920929 Share on Facebook - Select elements to share + Select elements to share Share Sharing was cancelled Shared - Sharing content is currently not possible. Please ensure that you have the Facebook app installed and that you have granted the necessary permissions. + Facebook app not found. Please make sure that you have installed the Facebook app and granted the necessary permissions. An error occurred while sharing content. The Facebook application responded with: Please select the route you would like to share It is not possible to share shit route diff --git a/app/src/main/res/xml/files.xml b/app/src/main/res/xml/files.xml index ddb84cb..5662d20 100644 --- a/app/src/main/res/xml/files.xml +++ b/app/src/main/res/xml/files.xml @@ -1,5 +1,6 @@ + diff --git a/assets/kalinowice/assets/custom.xml b/assets/kalinowice/assets/custom.xml index 7b4cb7c..177e2e9 100644 --- a/assets/kalinowice/assets/custom.xml +++ b/assets/kalinowice/assets/custom.xml @@ -1,25 +1,36 @@ - custom - - - 1 - 50.501055 - 18.180191 - photo_3035c809-d834-4dc6-a7ef-c8a0b670b945.jpg - sound_ddaa89a4-2925-45a1-a5a1-93f72c04aeff.3gp - k01001 - kalinowice_01.mp4 - en_01.srt - - - 2 - 50.505667 - 18.185020 - photo_2185c623-ef91-4e00-b1fc-3c6d4082d1be.jpg - sound_72686712-ceb1-40b6-a420-2d4016bf3872.3gp - k01002 - kalinowice_01.mp4 - en_01.srt - - + custom + + + 1 + 50.501055 + 18.180191 + photo_3035c809-d834-4dc6-a7ef-c8a0b670b945.jpg + sound_ddaa89a4-2925-45a1-a5a1-93f72c04aeff.3gp + k01001 + kalinowice_01.mp4 + en_01.srt + + + + 2 + 50.5079648 + 18.1846258 + + + k01002 + kalinowice_01.mp4 + en_01.srt + + + 6 + 50.505667 + 18.185020 + photo_2185c623-ef91-4e00-b1fc-3c6d4082d1be.jpg + sound_72686712-ceb1-40b6-a420-2d4016bf3872.3gp + k01002 + kalinowice_01.mp4 + en_01.srt + + \ No newline at end of file