Add Forgejo workflow #2
17 changed files with 188 additions and 123 deletions
73
.forgejo/workflows/pull_request.yml
Normal file
73
.forgejo/workflows/pull_request.yml
Normal file
|
@ -0,0 +1,73 @@
|
|||
name: Build & Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
name: Validate
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK
|
||||
uses: https://git.wbrawner.com/actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: '17'
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: https://git.wbrawner.com/gradle/actions/wrapper-validation@v3
|
||||
unit_tests:
|
||||
name: Run Unit Tests
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- validate
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK
|
||||
uses: https://git.wbrawner.com/actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: '17'
|
||||
- name: Setup Android SDK
|
||||
uses: https://git.wbrawner.com/android-actions/setup-android@v3
|
||||
- name: Run unit tests
|
||||
uses: https://git.wbrawner.com/gradle/actions/setup-gradle@v3
|
||||
with:
|
||||
arguments: check
|
||||
- name: Publish JUnit Results
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: Unit Test Results
|
||||
path: "*/build/reports/*"
|
||||
if-no-files-found: error
|
||||
# TODO: Uncomment the following once I get UI tests written
|
||||
# ui_tests:
|
||||
# runs-on: ubuntu-latest
|
||||
# name: Run UI Tests
|
||||
# needs:
|
||||
# - validate
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - name: set up JDK
|
||||
# uses: https://git.wbrawner.com/actions/setup-java@v3
|
||||
# with:
|
||||
# distribution: 'zulu'
|
||||
# java-version: '17'
|
||||
# - name: Build with Gradle
|
||||
# uses: https://git.wbrawner.com/gradle/gradle-build-action@v2
|
||||
# with:
|
||||
# arguments: assembleDebug assembleDebugAndroidTest
|
||||
# - name: Grant execute permission for flank_auth.sh
|
||||
# run: chmod +x flank_auth.sh
|
||||
# - name: Add auth for flank
|
||||
# env:
|
||||
# GCLOUD_KEY: ${{ secrets.GCLOUD_KEY }}
|
||||
# run: |
|
||||
# ./flank_auth.sh
|
||||
# - name: Run UI tests
|
||||
# uses: https://git.wbrawner.com/gradle/gradle-build-action@v2
|
||||
# with:
|
||||
# arguments: runFlank
|
|
@ -4,9 +4,8 @@
|
|||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="GRADLE" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="jbr-17" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,16 +1,17 @@
|
|||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.compose.compiler)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.wbrawner.skerge"
|
||||
compileSdk = 34
|
||||
compileSdk = libs.versions.maxSdk.get().toInt()
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.wbrawner.skerge"
|
||||
minSdk = 29
|
||||
targetSdk = 34
|
||||
minSdk = libs.versions.minSdk.get().toInt()
|
||||
targetSdk = libs.versions.maxSdk.get().toInt()
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
|
@ -20,7 +21,7 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
packaging {
|
||||
resources.pickFirsts.addAll(listOf("META-INF/AL2.0", "META-INF/LGPL2.1"))
|
||||
}
|
||||
|
||||
|
@ -43,31 +44,28 @@ android {
|
|||
buildFeatures {
|
||||
compose = true
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = "1.5.4"
|
||||
lint {
|
||||
warningsAsErrors = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
val composeBom = platform("androidx.compose:compose-bom:2023.10.01")
|
||||
val composeBom = enforcedPlatform(libs.compose.bom)
|
||||
implementation(composeBom)
|
||||
implementation("androidx.core:core-ktx:1.12.0")
|
||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||
implementation("com.google.android.material:material:1.10.0")
|
||||
implementation("androidx.compose.ui:ui")
|
||||
implementation("androidx.compose.material:material")
|
||||
implementation("androidx.compose.material3:material3")
|
||||
implementation("androidx.compose.ui:ui-tooling")
|
||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
|
||||
implementation("androidx.preference:preference-ktx:1.2.1")
|
||||
implementation("androidx.activity:activity-compose:1.8.0")
|
||||
val ktorVersion = "2.3.6"
|
||||
implementation("io.ktor:ktor-client-cio:$ktorVersion")
|
||||
implementation("io.ktor:ktor-client-android:$ktorVersion")
|
||||
androidTestImplementation("io.ktor:ktor-client-mock:$ktorVersion")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||
implementation(libs.androidx.preference.ktx)
|
||||
implementation(libs.compose.material3)
|
||||
implementation(libs.compose.ui)
|
||||
implementation(libs.compose.ui.tooling)
|
||||
implementation(libs.ktor.client.android)
|
||||
implementation(libs.ktor.client.cio)
|
||||
androidTestImplementation(composeBom)
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.ui.test.junit4)
|
||||
androidTestImplementation(libs.ktor.client.mock)
|
||||
testImplementation(libs.junit)
|
||||
}
|
|
@ -14,9 +14,8 @@
|
|||
<activity
|
||||
android:name="com.wbrawner.skerge.MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:windowSoftInputMode="adjustPan|adjustResize"
|
||||
android:theme="@style/Theme.Skerge.NoActionBar">
|
||||
android:theme="@style/Theme.Skerge">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
|
|
@ -4,25 +4,49 @@ import android.graphics.Bitmap
|
|||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.material.rememberSwipeableState
|
||||
import androidx.compose.material.swipeable
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
|
@ -32,12 +56,10 @@ import androidx.compose.ui.text.input.KeyboardType
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.view.WindowCompat
|
||||
import com.wbrawner.skerge.ui.theme.SkergeTheme
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
private val viewModel: MainViewModel by viewModels {
|
||||
|
@ -46,13 +68,8 @@ class MainActivity : ComponentActivity() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
val darkMode = isSystemInDarkTheme()
|
||||
LaunchedEffect(darkMode) {
|
||||
WindowCompat.getInsetsController(window, window.decorView)
|
||||
.isAppearanceLightNavigationBars = !darkMode
|
||||
}
|
||||
val pages by viewModel.pages.collectAsState(initial = emptyList())
|
||||
val scannerUrl by viewModel.scannerUrl.collectAsState(initial = "")
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
@ -229,7 +246,7 @@ fun PageList(pages: List<Page>, removePage: (Page) -> Unit, modifier: Modifier)
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class)
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun PagePreview(page: Page, removePage: (Page) -> Unit) {
|
||||
val (pageBitmap, setPageBitmap) = remember { mutableStateOf<Bitmap?>(null) }
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package com.wbrawner.skerge.ui.theme
|
||||
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Shapes
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
val Shapes = Shapes(
|
||||
small = RoundedCornerShape(4.dp),
|
||||
medium = RoundedCornerShape(4.dp),
|
||||
large = RoundedCornerShape(0.dp)
|
||||
)
|
|
@ -1,15 +0,0 @@
|
|||
package com.wbrawner.skerge.ui.theme
|
||||
|
||||
import androidx.compose.material.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
val Typography = Typography(
|
||||
body1 = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
)
|
|
@ -2,4 +2,5 @@
|
|||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
|
@ -2,4 +2,5 @@
|
|||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
|
@ -1,16 +0,0 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.Skerge" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/skerge_blue</item>
|
||||
<item name="colorPrimaryVariant">@color/skerge_blue</item>
|
||||
<item name="colorOnPrimary">@color/black</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/skerge_blue</item>
|
||||
<item name="colorSecondaryVariant">@color/skerge_blue</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">#FF282828</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
|
@ -1,7 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="skerge_blue">#FF0096d6</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="ic_launcher_background">#0096D6</color>
|
||||
</resources>
|
|
@ -1,23 +1,6 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.Skerge" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/skerge_blue</item>
|
||||
<item name="colorPrimaryVariant">@color/skerge_blue</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<item name="colorSecondary">@color/skerge_blue</item>
|
||||
<item name="colorSecondaryVariant">@color/skerge_blue</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Skerge.NoActionBar">
|
||||
<style name="Theme.Skerge" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Skerge.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="Theme.Skerge.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
</resources>
|
|
@ -1,11 +1,5 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:8.1.2")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20")
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
alias(libs.plugins.compose.compiler) apply false
|
||||
}
|
38
gradle/libs.versions.toml
Normal file
38
gradle/libs.versions.toml
Normal file
|
@ -0,0 +1,38 @@
|
|||
[versions]
|
||||
activityCompose = "1.9.0"
|
||||
androidGradlePlugin = "8.5.0"
|
||||
appcompat = "1.7.0"
|
||||
composeBom = "2024.06.00"
|
||||
coreKtx = "1.13.1"
|
||||
espressoCore = "3.6.1"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.2.1"
|
||||
kotlin = "2.0.0"
|
||||
ktorVersion = "2.3.6"
|
||||
lifecycleRuntimeKtx = "2.8.3"
|
||||
maxSdk = "34"
|
||||
minSdk = "29"
|
||||
preferenceKtx = "1.2.1"
|
||||
|
||||
[libraries]
|
||||
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
|
||||
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
|
||||
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
|
||||
androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espressoCore" }
|
||||
androidx-junit = { module = "androidx.test.ext:junit", version.ref = "junitVersion" }
|
||||
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
|
||||
androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preferenceKtx" }
|
||||
androidx-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" }
|
||||
compose-bom = { module = "androidx.compose:compose-bom", version.ref = "composeBom" }
|
||||
compose-material3 = { module = "androidx.compose.material3:material3" }
|
||||
compose-ui = { module = "androidx.compose.ui:ui" }
|
||||
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
|
||||
junit = { module = "junit:junit", version.ref = "junit" }
|
||||
ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktorVersion" }
|
||||
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktorVersion" }
|
||||
ktor-client-mock = { module = "io.ktor:ktor-client-mock", version.ref = "ktorVersion" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
|
||||
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
#Tue Jun 29 09:32:45 MDT 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
|
@ -5,6 +5,13 @@ dependencyResolutionManagement {
|
|||
mavenCentral()
|
||||
}
|
||||
}
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
rootProject.name = "Skerge"
|
||||
include(":app")
|
||||
|
Loading…
Reference in a new issue