diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index e7d51bf..22dbf1f 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -51,6 +51,7 @@ android {
dependencies {
val composeBom = platform("androidx.compose:compose-bom:2024.10.01")
implementation(composeBom)
+ implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.activity:activity-compose:1.9.3")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b901d03..f6f2585 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -27,6 +27,16 @@
android:name=".TimerService"
android:exported="false"
android:foregroundServiceType="mediaPlayback" />
+
+
+
+
diff --git a/app/src/main/assets/reading/jhanas-guide.pdf b/app/src/main/assets/reading/jhanas-guide.pdf
new file mode 100644
index 0000000..243462f
Binary files /dev/null and b/app/src/main/assets/reading/jhanas-guide.pdf differ
diff --git a/app/src/main/assets/reading/retreat-instructions.pdf b/app/src/main/assets/reading/retreat-instructions.pdf
new file mode 100644
index 0000000..363c3f0
Binary files /dev/null and b/app/src/main/assets/reading/retreat-instructions.pdf differ
diff --git a/app/src/main/java/com/marcus/meditationtimer/MainActivity.kt b/app/src/main/java/com/marcus/meditationtimer/MainActivity.kt
index ebeec7e..8d60245 100644
--- a/app/src/main/java/com/marcus/meditationtimer/MainActivity.kt
+++ b/app/src/main/java/com/marcus/meditationtimer/MainActivity.kt
@@ -1,10 +1,14 @@
package com.marcus.meditationtimer
import android.Manifest
+import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
+import android.widget.Toast
+import androidx.core.content.FileProvider
+import java.io.File
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
@@ -136,6 +140,7 @@ private fun App() {
) {
Tab(selected = tab == 0, onClick = { tab = 0 }, text = { Text("Timer") })
Tab(selected = tab == 1, onClick = { tab = 1 }, text = { Text("History") })
+ Tab(selected = tab == 2, onClick = { tab = 2 }, text = { Text("Reading") })
}
when (tab) {
0 -> TimerTab()
@@ -143,6 +148,7 @@ private fun App() {
onEditSession = { ratingFor = it },
onOpenToken = { showTokenDialog = true },
)
+ 2 -> ReadingTab()
}
}
@@ -430,6 +436,67 @@ private fun SessionRow(s: Session, onClick: () -> Unit) {
}
}
+// -------------------------------------------------------------- Reading tab
+
+private data class Doc(val title: String, val subtitle: String, val asset: String)
+
+private val DOCS = listOf(
+ Doc("Pragmatic Jhanas Guide", "v4.3", "jhanas-guide.pdf"),
+ Doc("Retreat Instructions", "v6.0.3 ยท Day 1 & 2", "retreat-instructions.pdf"),
+)
+
+@Composable
+private fun ReadingTab() {
+ val context = LocalContext.current
+ Column(
+ Modifier
+ .fillMaxSize()
+ .padding(20.dp)
+ ) {
+ DOCS.forEach { doc ->
+ Column(
+ Modifier
+ .fillMaxWidth()
+ .clickable { openPdf(context, doc) }
+ .background(Color.White.copy(alpha = 0.05f), RoundedCornerShape(12.dp))
+ .padding(20.dp)
+ ) {
+ Text(doc.title, color = Color.White.copy(alpha = 0.9f), fontSize = 16.sp)
+ Spacer(Modifier.height(4.dp))
+ Text(doc.subtitle, color = Dim, fontSize = 12.sp)
+ }
+ Spacer(Modifier.height(12.dp))
+ }
+ Text(
+ "Opens in the system PDF viewer.",
+ color = Dim,
+ fontSize = 11.sp,
+ textAlign = TextAlign.Center,
+ modifier = Modifier.fillMaxWidth(),
+ )
+ }
+}
+
+private fun openPdf(context: Context, doc: Doc) {
+ try {
+ val dir = File(context.cacheDir, "reading").apply { mkdirs() }
+ val outFile = File(dir, doc.asset)
+ if (!outFile.exists() || outFile.length() == 0L) {
+ context.assets.open("reading/${doc.asset}").use { input ->
+ outFile.outputStream().use { input.copyTo(it) }
+ }
+ }
+ val uri = FileProvider.getUriForFile(context, "${context.packageName}.files", outFile)
+ context.startActivity(
+ Intent(Intent.ACTION_VIEW)
+ .setDataAndType(uri, "application/pdf")
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ )
+ } catch (e: Exception) {
+ Toast.makeText(context, "Could not open PDF: ${e.message}", Toast.LENGTH_SHORT).show()
+ }
+}
+
// ----------------------------------------------------------------- Dialogs
@Composable
diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml
new file mode 100644
index 0000000..e6b4e2a
--- /dev/null
+++ b/app/src/main/res/xml/file_paths.xml
@@ -0,0 +1,4 @@
+
+
+
+