diff --git a/.github/workflows/build-apk.yml b/.github/workflows/build-apk.yml new file mode 100644 index 00000000..b5d81766 --- /dev/null +++ b/.github/workflows/build-apk.yml @@ -0,0 +1,42 @@ +name: Build and Archive APK + +on: workflow_dispatch + +env: + MAVEN_OPTS: >- + -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: set up JDK 18 + uses: actions/setup-java@v3 + with: + java-version: "18" + distribution: "temurin" + + - uses: gradle/gradle-build-action@v2 + with: + gradle-version: 7.5 + + - name: Execute Gradle build + run: | + # For debugging, an ephemeral key suffice + keytool -genkey -v -keystore ${{ github.workspace }}/debug.keystore -storepass password -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 -keypass password -dname "CN=Android Debug,O=Android,C=US" + + ./gradlew \ + -PDEBUG_STORE_FILE=${{ github.workspace }}/debug.keystore \ + -PDEBUG_STORE_PASSWORD=password \ + -PDEBUG_KEY_ALIAS=androiddebugkey \ + -PDEBUG_KEY_PASSWORD=password \ + -PIS_NEXT=true \ + assembleDebug + + - name: Archive APK + uses: actions/upload-artifact@v3 + with: + name: app-debug.apk + path: "${{ github.workspace }}/app/build/outputs/apk/debug/app-debug.apk" diff --git a/app/src/main/java/com/olup/notable/components/Path.kt b/app/src/main/java/com/olup/notable/components/Path.kt new file mode 100644 index 00000000..4d77fb89 --- /dev/null +++ b/app/src/main/java/com/olup/notable/components/Path.kt @@ -0,0 +1,65 @@ +package com.olup.notable.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* +import androidx.compose.material.Icon +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowDropDown +import androidx.compose.material.icons.rounded.Edit +import androidx.compose.material.icons.sharp.Edit +import androidx.compose.material.icons.sharp.KeyboardArrowDown +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Popup +import com.olup.notable.noRippleClickable + +// It seems wrong to re-implement a Path selector dialog, +// but until now I only saw self drawed UI elements, not built-in android ones +// It should be simple, if I only render a text, +// and if it is clicked upon I open a Directory Selector Dialog +@Composable +fun PathMenu(value: String, onChange: (String) -> Unit) { + var isExpanded by remember { mutableStateOf(false) } + + Box() { + Row() { + Text(text = value, + fontWeight = FontWeight.Light, + modifier = Modifier.noRippleClickable { isExpanded = true } + // Register Directory selector dialog on Click event + ) + + Icon( + Icons.Rounded.ArrowDropDown, contentDescription = "open select", + modifier = Modifier.height(20.dp) + ) + } + if (isExpanded) Popup(onDismissRequest = { isExpanded = false }) { + Column( + modifier = Modifier + .width(IntrinsicSize.Max) + .border(0.5.dp, Color.Black, RectangleShape) + .background(Color.White) + ) { + Text(text = "dialogOpens", // as I am new to Android, first test if the changes until now work + fontWeight = FontWeight.Light, + color = Color.Black, + modifier = Modifier + .fillMaxWidth() + .background(Color.White) + .padding(20.dp, 10.dp) + .noRippleClickable { + //onChange(it.first) + isExpanded = false + }) + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/olup/notable/modals/AppSettings.kt b/app/src/main/java/com/olup/notable/modals/AppSettings.kt index e975fb76..aefa2c4f 100644 --- a/app/src/main/java/com/olup/notable/modals/AppSettings.kt +++ b/app/src/main/java/com/olup/notable/modals/AppSettings.kt @@ -2,6 +2,7 @@ package com.olup.notable import android.content.Intent import android.net.Uri +import android.os.Environment import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.* @@ -18,13 +19,16 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.olup.notable.components.SelectMenu +import com.olup.notable.components.PathMenu import com.olup.notable.db.KvProxy import kotlin.concurrent.thread + @kotlinx.serialization.Serializable data class AppSettings( val version: Int, val defaultNativeTemplate: String = "blank", + val defaultSavePath: String = Environment.DIRECTORY_DOCUMENTS + "/notable", val quickNavPages: List = listOf() ) @@ -62,6 +66,24 @@ fun AppSettingsModal(onClose: () -> Unit) { Box(Modifier.height(0.5.dp).fillMaxWidth().background(Color.Black)) Column(Modifier.padding(20.dp, 10.dp)) { + Row() { + Text(text = "Save path") + Spacer(Modifier.width(10.dp)) + PathMenu( + onChange = { + kv.setKv( + "APP_SETTINGS", + settings!!.copy(defaultSavePath = it), + AppSettings.serializer() + ) + }, + value = settings?.defaultSavePath + ?: (Environment.DIRECTORY_DOCUMENTS + "/notable") + ) + } + + Spacer(Modifier.height(10.dp)) + Row() { Text(text = "Default Page Background Template") Spacer(Modifier.width(10.dp)) diff --git a/app/src/main/java/com/olup/notable/utils/page.kt b/app/src/main/java/com/olup/notable/utils/page.kt index 4949e066..1d53198e 100644 --- a/app/src/main/java/com/olup/notable/utils/page.kt +++ b/app/src/main/java/com/olup/notable/utils/page.kt @@ -3,9 +3,12 @@ package com.olup.notable import android.content.Context import android.graphics.pdf.PdfDocument import android.os.Environment +import androidx.compose.runtime.Composable import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.platform.LocalContext import com.olup.notable.db.BookRepository import com.olup.notable.db.PageRepository +import com.olup.notable.AppRepository import com.olup.notable.db.Stroke import io.shipbook.shipbooksdk.Log import java.io.FileOutputStream @@ -16,23 +19,29 @@ import kotlin.io.path.div fun exportBook(context: Context, bookId: String) { val book = BookRepository(context).getById(bookId) ?: return val pages = PageRepository(context) - exportPdf("notebooks", book.title) { + exportPdf(context, "notebooks", book.title) { book.pageIds.forEachIndexed { i, pageId -> writePage(i + 1, pages, pageId) } } } fun exportPage(context: Context, pageId: String) { val pages = PageRepository(context) - exportPdf("pages", "notable-page-${pageId.takeLast(6)}") { + exportPdf(context, "pages", "notable-page-${pageId.takeLast(6)}") { writePage(1, pages, pageId) } } -private inline fun exportPdf(dir: String, name: String, write: PdfDocument.() -> Unit) { +private inline fun exportPdf(context: Context, dir: String, name: String, write: PdfDocument.() -> Unit) { val document = PdfDocument() document.write() - val filePath = Environment.getExternalStorageDirectory().toPath() / - Environment.DIRECTORY_DOCUMENTS / "notable" / dir / "$name.pdf" + + val appRepository = AppRepository(context) + + val savePath = appRepository.kvProxy.get( + "APP_SETTINGS", AppSettings.serializer() + )?.defaultSavePath ?: (Environment.DIRECTORY_DOCUMENTS + "/notable") + + val filePath = Environment.getExternalStorageDirectory().toPath() / "$savePath/$dir/$name.pdf" Files.createDirectories(filePath.parent) FileOutputStream(filePath.absolutePathString()).use(document::writeTo) document.close() diff --git a/app/src/main/java/com/olup/notable/utils/utils.kt b/app/src/main/java/com/olup/notable/utils/utils.kt index ffb093c2..8855ac0d 100644 --- a/app/src/main/java/com/olup/notable/utils/utils.kt +++ b/app/src/main/java/com/olup/notable/utils/utils.kt @@ -249,7 +249,7 @@ fun handleSelect( } -// touchpoints is in wiew coordinates +// touchpoints is in view coordinates fun handleDraw( page: PageView, historyBucket: MutableList,