Compare commits
6 commits
a7d0119250
...
f2d5687a5f
Author | SHA1 | Date | |
---|---|---|---|
f2d5687a5f | |||
4bf56a5918 | |||
d533682af6 | |||
b5c23fc5ca | |||
7447a5ca6d | |||
a4ec4c8aa4 |
26 changed files with 210 additions and 151 deletions
74
.forgejo/workflows/pull_request.yml
Normal file
74
.forgejo/workflows/pull_request.yml
Normal file
|
@ -0,0 +1,74 @@
|
|||
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
|
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -1,15 +1,11 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.idea
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
keystore.properties
|
||||
.kotlin
|
||||
|
|
|
@ -237,6 +237,7 @@
|
|||
<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>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
</project>
|
|
@ -5,18 +5,6 @@
|
|||
<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>
|
|
@ -4,6 +4,7 @@
|
|||
<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">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.8.20" />
|
||||
<option name="version" value="2.0.21" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,3 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeSettings">
|
||||
<configurations>
|
||||
|
@ -64,7 +65,7 @@
|
|||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
|
@ -3,10 +3,11 @@ import java.io.FileNotFoundException
|
|||
import java.util.*
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
id("kotlin-kapt")
|
||||
id("dagger.hilt.android.plugin")
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.ksp)
|
||||
alias(libs.plugins.hilt.android)
|
||||
alias(libs.plugins.compose)
|
||||
}
|
||||
|
||||
val keystoreProperties = Properties()
|
||||
|
@ -56,11 +57,11 @@ android {
|
|||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
jvmTarget = "21"
|
||||
}
|
||||
buildFeatures {
|
||||
compose = true
|
||||
|
@ -68,6 +69,7 @@ android {
|
|||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
|
||||
}
|
||||
namespace = "com.wbrawner.pihelper"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -76,7 +78,7 @@ dependencies {
|
|||
implementation(libs.bundles.compose)
|
||||
implementation(libs.hilt.android.core)
|
||||
implementation(libs.hilt.navigation.compose)
|
||||
kapt(libs.hilt.android.kapt)
|
||||
ksp(libs.hilt.android.ksp)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.androidx.splash)
|
||||
|
@ -91,7 +93,7 @@ dependencies {
|
|||
androidTestImplementation(libs.test.ext)
|
||||
androidTestImplementation(libs.espresso)
|
||||
androidTestImplementation(libs.hilt.android.testing)
|
||||
kaptAndroidTest(libs.hilt.android.kapt)
|
||||
kspAndroidTest(libs.hilt.android.ksp)
|
||||
androidTestImplementation(libs.compose.test.junit)
|
||||
debugImplementation(libs.compose.test.manifest)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ 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() }
|
||||
|
@ -22,7 +21,7 @@ class AddScreenRobot(private val testRule: ComposeTestRule) {
|
|||
fun inputHost(host: String) =
|
||||
testRule.onNodeWithContentDescription("Pi-hole host input").performTextInput(host)
|
||||
|
||||
fun clickConnect() = testRule.onNode(hasTestTag(CONNECT_BUTTON_TAG)).performClick()
|
||||
fun clickConnect() = testRule.onNode(hasText("Connect")).performClick()
|
||||
|
||||
fun verifyErrorMessageIsDisplayed(message: String) {
|
||||
testRule.waitUntil(2_000) {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.wbrawner.pihelper">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<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"
|
||||
|
|
|
@ -6,6 +6,7 @@ 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
|
||||
|
@ -24,6 +25,7 @@ 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(
|
||||
|
@ -39,8 +41,7 @@ fun AddScreen(store: Store) {
|
|||
connectivityManager.allNetworks
|
||||
.filter {
|
||||
connectivityManager.getNetworkCapabilities(it)
|
||||
?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
?: false
|
||||
?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true
|
||||
}
|
||||
.mapNotNull { network ->
|
||||
connectivityManager.getLinkProperties(network)
|
||||
|
@ -61,7 +62,7 @@ fun AddScreen(store: Store) {
|
|||
connectToPihole = {
|
||||
store.dispatch(Action.Connect(it))
|
||||
},
|
||||
store.state.value.loading,
|
||||
state.loading,
|
||||
error = effect as? Effect.Error
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,16 +4,15 @@ 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
|
||||
|
@ -39,22 +38,10 @@ class MainActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
installSplashScreen()
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
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
|
||||
}
|
||||
BackHandler {
|
||||
store.dispatch(Action.Back)
|
||||
}
|
||||
val launchIntent = remember { intent }
|
||||
LaunchedEffect(launchIntent) {
|
||||
|
@ -121,10 +108,6 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
store.dispatch(Action.Back)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -4,19 +4,24 @@ 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.material.Text
|
||||
import androidx.compose.material3.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) {
|
||||
ScanningStatus(store.state.value.scanning?.let { "Scanning $it..." })
|
||||
val state by store.state.collectAsState()
|
||||
ScanningStatus(state.scanning?.let { "Scanning $it..." })
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -1,25 +1,12 @@
|
|||
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/")
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
|
@ -19,3 +19,6 @@ 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
|
||||
|
|
|
@ -1,24 +1,27 @@
|
|||
[versions]
|
||||
androidx-core = "1.10.1"
|
||||
androidx-appcompat = "1.6.1"
|
||||
androidGradlePlugin = "8.7.2"
|
||||
androidx-core = "1.15.0"
|
||||
androidx-appcompat = "1.7.0"
|
||||
androidx-splash = "1.0.1"
|
||||
androidx-test-runner = "1.5.2"
|
||||
androidx-test-orchestrator = "1.4.2"
|
||||
compose = "1.6.0"
|
||||
androidx-test-runner = "1.6.2"
|
||||
androidx-test-orchestrator = "1.5.1"
|
||||
compose = "1.7.5"
|
||||
compose-multiplatform = "1.7.1"
|
||||
compose-compiler = "1.4.2"
|
||||
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"
|
||||
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"
|
||||
minSdk = "23"
|
||||
navigation = "2.7.0"
|
||||
okhttp = "4.10.0"
|
||||
plausible = "0.1.0-SNAPSHOT"
|
||||
settings = "0.8.1"
|
||||
|
@ -26,7 +29,6 @@ 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" }
|
||||
|
@ -36,25 +38,17 @@ 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-kapt = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt-android" }
|
||||
hilt-android-ksp = { 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.0.0" }
|
||||
hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.2.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" }
|
||||
|
@ -63,14 +57,12 @@ 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" }
|
||||
|
@ -78,4 +70,15 @@ 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-gradle", "compose-plugin-jetbrains", "kotlin-gradle", "dagger-hilt", "kotlin-serialization"]
|
||||
|
||||
[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" }
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -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.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
|
||||
|
|
|
@ -1,4 +1,26 @@
|
|||
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")
|
||||
include(":desktop")
|
||||
include(":shared")
|
||||
include(":app", ":desktop", ":shared")
|
|
@ -1,12 +1,13 @@
|
|||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("com.android.library")
|
||||
kotlin("plugin.serialization")
|
||||
id("org.jetbrains.compose")
|
||||
alias(libs.plugins.kotlin.multiplatform)
|
||||
alias(libs.plugins.android.library)
|
||||
alias(libs.plugins.jetbrainsCompose)
|
||||
alias(libs.plugins.compose)
|
||||
alias(libs.plugins.kotlin.serialization)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
android()
|
||||
androidTarget()
|
||||
listOf(iosArm64(), iosSimulatorArm64()).forEach {
|
||||
it.binaries.framework {
|
||||
baseName = "Pihelper"
|
||||
|
@ -30,13 +31,14 @@ kotlin {
|
|||
api(compose.foundation)
|
||||
api(compose.material3)
|
||||
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
|
||||
implementation(compose.components.resources)
|
||||
api(compose.components.resources)
|
||||
}
|
||||
}
|
||||
|
||||
val androidMain by getting {
|
||||
dependencies {
|
||||
implementation(libs.plausible)
|
||||
api(compose.runtime)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,15 +66,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_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
consumerProguardFiles("proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
namespace = "com.wbrawner.pihelper.shared"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.wbrawner.pihelper.shared">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
|
@ -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.smallTopAppBarColors
|
||||
import androidx.compose.material3.TopAppBarDefaults.topAppBarColors
|
||||
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 = smallTopAppBarColors(
|
||||
colors = topAppBarColors(
|
||||
containerColor = MaterialTheme.colorScheme.surface
|
||||
),
|
||||
title = { Text("About Pi-helper") },
|
||||
|
|
|
@ -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.smallTopAppBarColors
|
||||
import androidx.compose.material3.TopAppBarDefaults.topAppBarColors
|
||||
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 = smallTopAppBarColors(
|
||||
colors = topAppBarColors(
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,12 @@ 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)
|
||||
@OptIn(ExperimentalResourceApi::class, InternalResourceApi::class)
|
||||
@Composable
|
||||
fun LoadingSpinner(animate: Boolean = false) {
|
||||
val animation = rememberInfiniteTransition()
|
||||
|
@ -27,7 +30,7 @@ fun LoadingSpinner(animate: Boolean = false) {
|
|||
)
|
||||
Image(
|
||||
modifier = Modifier.rotate(if (animate) rotation else 0f),
|
||||
painter = painterResource(DrawableResource("img/ic_app_logo.xml")),
|
||||
painter = painterResource(Res.drawable.ic_app_logo),
|
||||
contentDescription = "Loading",
|
||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground)
|
||||
)
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
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)
|
||||
)
|
Loading…
Reference in a new issue