Compare commits

..

No commits in common. "f2d5687a5f9f9cd3059725c3f421bfaddbfaf8d1" and "a7d01192501c9466f35b8d97ac1ac5e7ec1cc166" have entirely different histories.

26 changed files with 151 additions and 210 deletions

View file

@ -1,74 +0,0 @@
name: Build & Test
on:
pull_request:
push:
branches: [ main ]
jobs:
validate:
runs-on: ubuntu-latest
name: Validate
steps:
- uses: actions/checkout@v4
- name: set up JDK
uses: https://git.wbrawner.com/actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: Validate Gradle Wrapper
uses: https://git.wbrawner.com/gradle/actions/wrapper-validation@v4
unit_tests:
name: Run Unit Tests
runs-on: ubuntu-latest
needs:
- validate
steps:
- uses: actions/checkout@v4
- name: set up JDK
uses: https://git.wbrawner.com/actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: Setup Android SDK
uses: https://git.wbrawner.com/android-actions/setup-android@v3
- name: Setup Gradle
uses: https://git.wbrawner.com/gradle/actions/setup-gradle@v4
- name: Run checks
run: ./gradlew check
# TODO: Uncomment the following once I get unit tests written
# - 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

10
.gitignore vendored
View file

@ -1,11 +1,15 @@
*.iml
.gradle
/local.properties
.idea
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
keystore.properties
.kotlin
keystore.properties

View file

@ -237,7 +237,6 @@
<option name="preferredColumnWidths">
<map>
<entry key="Duration" value="90" />
<entry key="Medium_Phone_API_35" value="120" />
<entry key="Pixel_3a_API_33_arm64-v8a" value="120" />
<entry key="Tests" value="360" />
</map>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="21" />
<bytecodeTargetLevel target="17" />
</component>
</project>

View file

@ -5,6 +5,18 @@
<entry key="app">
<State />
</entry>
<entry key="app.androidTest">
<State />
</entry>
<entry key="app.unitTest">
<State />
</entry>
<entry key="pihelper-android.Pi-helper.app">
<State />
</entry>
<entry key="testInvalidHost()">
<State />
</entry>
</value>
</component>
</project>

View file

@ -4,7 +4,6 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="CHOOSE_PER_TEST" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
<option name="modules">

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="2.0.21" />
<option name="version" value="1.8.20" />
</component>
</project>

View file

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSettings">
<configurations>
@ -65,7 +64,7 @@
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View file

@ -3,11 +3,10 @@ import java.io.FileNotFoundException
import java.util.*
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.ksp)
alias(libs.plugins.hilt.android)
alias(libs.plugins.compose)
id("com.android.application")
id("kotlin-android")
id("kotlin-kapt")
id("dagger.hilt.android.plugin")
}
val keystoreProperties = Properties()
@ -57,11 +56,11 @@ android {
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "21"
jvmTarget = "1.8"
}
buildFeatures {
compose = true
@ -69,7 +68,6 @@ android {
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
}
namespace = "com.wbrawner.pihelper"
}
dependencies {
@ -78,7 +76,7 @@ dependencies {
implementation(libs.bundles.compose)
implementation(libs.hilt.android.core)
implementation(libs.hilt.navigation.compose)
ksp(libs.hilt.android.ksp)
kapt(libs.hilt.android.kapt)
implementation(libs.androidx.core)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.splash)
@ -93,7 +91,7 @@ dependencies {
androidTestImplementation(libs.test.ext)
androidTestImplementation(libs.espresso)
androidTestImplementation(libs.hilt.android.testing)
kspAndroidTest(libs.hilt.android.ksp)
kaptAndroidTest(libs.hilt.android.kapt)
androidTestImplementation(libs.compose.test.junit)
debugImplementation(libs.compose.test.manifest)
}

View file

@ -4,6 +4,7 @@ import android.content.Context
import androidx.compose.ui.test.*
import androidx.compose.ui.test.junit4.ComposeTestRule
import androidx.test.platform.app.InstrumentationRegistry
import com.wbrawner.pihelper.CONNECT_BUTTON_TAG
fun onAddScreen(testRule: ComposeTestRule, actions: AddScreenRobot.() -> Unit) =
AddScreenRobot(testRule).apply { actions() }
@ -21,7 +22,7 @@ class AddScreenRobot(private val testRule: ComposeTestRule) {
fun inputHost(host: String) =
testRule.onNodeWithContentDescription("Pi-hole host input").performTextInput(host)
fun clickConnect() = testRule.onNode(hasText("Connect")).performClick()
fun clickConnect() = testRule.onNode(hasTestTag(CONNECT_BUTTON_TAG)).performClick()
fun verifyErrorMessageIsDisplayed(message: String) {
testRule.waitUntil(2_000) {

View file

@ -1,12 +1,12 @@
<?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="com.wbrawner.pihelper">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".PiHelperApplication"
android:allowBackup="true"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="@xml/backup_descriptor"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"

View file

@ -6,7 +6,6 @@ import android.net.NetworkCapabilities
import android.os.Build
import android.widget.Toast
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext
@ -25,7 +24,6 @@ val emulatorBuildModels = listOf(
@Composable
fun AddScreen(store: Store) {
val state by store.state.collectAsState()
val effect by store.effects.collectAsState(initial = Effect.Empty)
val context = LocalContext.current
AddScreen(
@ -41,7 +39,8 @@ fun AddScreen(store: Store) {
connectivityManager.allNetworks
.filter {
connectivityManager.getNetworkCapabilities(it)
?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true
?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
?: false
}
.mapNotNull { network ->
connectivityManager.getLinkProperties(network)
@ -62,7 +61,7 @@ fun AddScreen(store: Store) {
connectToPihole = {
store.dispatch(Action.Connect(it))
},
state.loading,
store.state.value.loading,
error = effect as? Effect.Error
)
}

View file

@ -4,15 +4,16 @@ import android.animation.ObjectAnimator
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.WindowInsetsController
import android.view.animation.AnticipateInterpolator
import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.*
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.animation.doOnEnd
import androidx.core.content.ContextCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
@ -38,10 +39,22 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
BackHandler {
store.dispatch(Action.Back)
val isDarkTheme = isSystemInDarkTheme()
LaunchedEffect(key1 = isDarkTheme) {
if (isDarkTheme) return@LaunchedEffect
window.navigationBarColor =
ContextCompat.getColor(this@MainActivity, R.color.colorSurface)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
window.insetsController?.setSystemBarsAppearance(
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS or WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS,
WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS or WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
)
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
@Suppress("DEPRECATION")
window.decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
}
}
val launchIntent = remember { intent }
LaunchedEffect(launchIntent) {
@ -108,6 +121,10 @@ class MainActivity : AppCompatActivity() {
}
}
}
override fun onBackPressed() {
store.dispatch(Action.Back)
}
}
@Composable

View file

@ -4,24 +4,19 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.wbrawner.pihelper.shared.Store
import com.wbrawner.pihelper.shared.ui.component.LoadingSpinner
import com.wbrawner.pihelper.shared.ui.theme.PihelperTheme
@Composable
fun ScanScreen(store: Store) {
val state by store.state.collectAsState()
ScanningStatus(state.scanning?.let { "Scanning $it..." })
ScanningStatus(store.state.value.scanning?.let { "Scanning $it..." })
}
@Composable

View file

@ -1,12 +1,25 @@
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.compose) apply false
alias(libs.plugins.jetbrainsCompose) apply false
alias(libs.plugins.hilt.android) apply false
alias(libs.plugins.kotlin.ksp) apply false
import java.net.URI
buildscript {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
dependencies {
classpath(libs.bundles.plugins)
}
}
allprojects {
repositories {
google()
mavenCentral()
maven {
url = URI("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
maven {
url = URI("https://maven.pkg.jetbrains.space/public/p/compose/dev/")
}
}
}

View file

@ -19,6 +19,3 @@ android.useAndroidX=true
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false

View file

@ -1,27 +1,24 @@
[versions]
androidGradlePlugin = "8.7.2"
androidx-core = "1.15.0"
androidx-appcompat = "1.7.0"
androidx-core = "1.10.1"
androidx-appcompat = "1.6.1"
androidx-splash = "1.0.1"
androidx-test-runner = "1.6.2"
androidx-test-orchestrator = "1.5.1"
compose = "1.7.5"
compose-multiplatform = "1.7.1"
androidx-test-runner = "1.5.2"
androidx-test-orchestrator = "1.4.2"
compose = "1.6.0"
compose-compiler = "1.4.2"
compose-material = "1.7.5"
compose-material3 = "1.3.1"
espresso = "3.6.1"
hilt-android = "2.51.1"
kotlin = "2.0.21"
kotlin-ksp = "2.0.21-1.0.28"
kotlinx-serialization = "1.6.3"
kotlinx-coroutines = "1.9.0"
kotlinx-datetime = "0.6.0"
ktor = "2.3.12"
logbackClassic = "1.5.12"
material = "1.12.0"
maxSdk = "35"
compose-material = "1.5.0"
compose-material3 = "1.1.1"
espresso = "3.5.1"
hilt-android = "2.44"
kotlin = "1.9.22"
kotlinx-serialization = "1.4.1"
kotlinx-coroutines = "1.6.4"
kotlinx-datetime = "0.4.0"
ktor = "2.1.2"
material = "1.9.0"
maxSdk = "33"
minSdk = "23"
navigation = "2.7.0"
okhttp = "4.10.0"
plausible = "0.1.0-SNAPSHOT"
settings = "0.8.1"
@ -29,6 +26,7 @@ versionCode = "5"
versionName = "1.1.1"
[libraries]
android-gradle = { module = "com.android.tools.build:gradle", version = "7.4.2" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
androidx-splash = { module = "androidx.core:core-splashscreen", version.ref = "androidx-splash" }
@ -38,17 +36,25 @@ compose-activity = { module = "androidx.activity:activity-compose", version = "1
compose-material = { module = "androidx.compose.material:material", version.ref = "compose-material" }
compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "compose-material3" }
compose-material3-window = { module = "androidx.compose.material3:material3-window-size-class", version.ref = "compose-material3" }
compose-plugin-jetbrains = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "compose" }
compose-test-junit = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "compose" }
compose-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "compose" }
compose-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
dagger-hilt = { module = "com.google.dagger:hilt-android-gradle-plugin", version.ref = "hilt-android" }
espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso" }
hilt-android-core = { module = "com.google.dagger:hilt-android", version.ref = "hilt-android" }
hilt-android-ksp = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt-android" }
hilt-android-kapt = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt-android" }
hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt-android" }
hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.2.0" }
hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.0.0" }
junit = { module = "junit:junit", version = "4.13.2" }
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
ktor-client-ios = { module = "io.ktor:ktor-client-ios", version.ref = "ktor" }
ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktor" }
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
ktor-client-serialization = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
@ -57,12 +63,14 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-jvm = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
kotlin-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logbackClassic" }
material = { module = "com.google.android.material:material", version.ref = "material" }
mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "okhttp" }
multiplatform-settings = { module = "com.russhwolf:multiplatform-settings-no-arg", version.ref = "settings" }
navigation-compose = { module = "androidx.navigation:navigation-compose", version = "navigation" }
navigation-fragment = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigation" }
navigation-ui = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigation" }
plausible = { module = "com.wbrawner.plausible:plausible-android", version.ref = "plausible" }
preference = { module = "androidx.preference:preference-ktx", version = "1.2.0" }
test-ext = { module = "androidx.test.ext:junit", version = "1.1.5" }
@ -70,15 +78,4 @@ test-ext = { module = "androidx.test.ext:junit", version = "1.1.5" }
[bundles]
compose = ["compose-ui", "compose-material", "compose-material3", "compose-material3-window", "compose-tooling", "compose-activity", "navigation-compose"]
coroutines = ["kotlinx-coroutines-core", "kotlinx-coroutines-android"]
[plugins]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }
compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "kotlin-ksp" }
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt-android" }
jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" }
plugins = ["android-gradle", "compose-plugin-jetbrains", "kotlin-gradle", "dagger-hilt", "kotlin-serialization"]

View file

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip

View file

@ -1,26 +1,4 @@
import java.net.URI
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = URI("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
maven {
url = URI("https://maven.pkg.jetbrains.space/public/p/compose/dev/")
}
}
}
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
rootProject.name = "Pi-helper"
include(":app", ":desktop", ":shared")
include(":app")
include(":desktop")
include(":shared")

View file

@ -1,13 +1,12 @@
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.android.library)
alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.compose)
alias(libs.plugins.kotlin.serialization)
kotlin("multiplatform")
id("com.android.library")
kotlin("plugin.serialization")
id("org.jetbrains.compose")
}
kotlin {
androidTarget()
android()
listOf(iosArm64(), iosSimulatorArm64()).forEach {
it.binaries.framework {
baseName = "Pihelper"
@ -31,14 +30,13 @@ kotlin {
api(compose.foundation)
api(compose.material3)
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
api(compose.components.resources)
implementation(compose.components.resources)
}
}
val androidMain by getting {
dependencies {
implementation(libs.plausible)
api(compose.runtime)
}
}
@ -66,15 +64,15 @@ android {
compileSdk = libs.versions.maxSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.maxSdk.get().toInt()
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
buildTypes {
release {
consumerProguardFiles("proguard-rules.pro")
}
}
namespace = "com.wbrawner.pihelper.shared"
}

View file

@ -1,5 +1,6 @@
<?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="com.wbrawner.pihelper.shared">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View file

@ -8,7 +8,7 @@ import androidx.compose.foundation.text.ClickableText
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.material3.TopAppBarDefaults.topAppBarColors
import androidx.compose.material3.TopAppBarDefaults.smallTopAppBarColors
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -37,7 +37,7 @@ fun InfoScreen(onBackClicked: () -> Unit, onForgetPiholeClicked: () -> Unit) {
Scaffold(
topBar = {
TopAppBar(
colors = topAppBarColors(
colors = smallTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surface
),
title = { Text("About Pi-helper") },

View file

@ -11,7 +11,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.*
import androidx.compose.material3.TopAppBarDefaults.topAppBarColors
import androidx.compose.material3.TopAppBarDefaults.smallTopAppBarColors
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -67,7 +67,7 @@ fun MainScreen(
topBar = {
TopAppBar(
title = { Text("Pi-helper") },
colors = topAppBarColors(
colors = smallTopAppBarColors(
containerColor = MaterialTheme.colorScheme.background,
titleContentColor = MaterialTheme.colorScheme.onBackground
),
@ -109,7 +109,7 @@ fun MainScreen(
Text(
color = MaterialTheme.colorScheme.primary,
textAlign = TextAlign.Center,
text = it.message
text = "${it.message}"
)
}
}

View file

@ -10,12 +10,9 @@ import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.ColorFilter
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.InternalResourceApi
import org.jetbrains.compose.resources.painterResource
import pi_helper.shared.generated.resources.Res
import pi_helper.shared.generated.resources.ic_app_logo
@OptIn(ExperimentalResourceApi::class, InternalResourceApi::class)
@OptIn(ExperimentalResourceApi::class)
@Composable
fun LoadingSpinner(animate: Boolean = false) {
val animation = rememberInfiniteTransition()
@ -30,7 +27,7 @@ fun LoadingSpinner(animate: Boolean = false) {
)
Image(
modifier = Modifier.rotate(if (animate) rotation else 0f),
painter = painterResource(Res.drawable.ic_app_logo),
painter = painterResource(DrawableResource("img/ic_app_logo.xml")),
contentDescription = "Loading",
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground)
)

View file

@ -0,0 +1,11 @@
package com.wbrawner.pihelper.shared.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)
)