Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
41 changes: 32 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,43 @@ A GUI application for Android <code>sysctl</code> to edit kernel variables
## Features
- Browse filesystem for specific kernel parameters
- Select parameters from a searchable list
- Information about known parameters
- Show documentation for known parameters
- Load parameters from a configuration file
- Reapply parameters at startup
- Mark parameters as favorite for easy access

## Technologies

- MVI / MVVM for user params
- [Jetpack Compose](https://developer.android.com/jetpack/compose) Material 3 UI
- [Jetpack Data Binding](https://developer.android.com/topic/libraries/data-binding)
- [Jetpack View Binding](https://developer.android.com/topic/libraries/view-binding)
- Lifecycle-aware Kotlin Coroutines
- Kotlin Flows
- Dependency injection with [Koin](https://insert-koin.io/)
This project utilizes a modern Android development stack, leveraging a comprehensive suite of libraries and tools:

- **Core & Architecture:**
- Architectural Patterns: MVI, reactive and maintainable.
- [Kotlin](https://kotlinlang.org/): For modern, concise, and safe programming.
- Android Jetpack:
- [Lifecycle](https://developer.android.com/jetpack/androidx/releases/lifecycle)
- [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel)
- [Navigation Component](https://developer.android.com/guide/navigation)
- [Room](https://developer.android.com/training/data-storage/room): For local data persistence.
- [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager): For deferrable, asynchronous tasks.
- **UI Development:**
- [Jetpack Compose](https://developer.android.com/jetpack/compose): For building native UIs with a declarative approach.
- Compose Material 3 & Material Components
- [Jetpack Glance](https://developer.android.com/develop/ui/compose/glance): For creating App Widgets with Jetpack Compose.
- **Asynchronous Programming:**
- [Kotlin Coroutines](https://kotlinlang.org/docs/coroutines-overview.html) & [Flows](https://kotlinlang.org/docs/flow.html): For efficient and structured background tasks and reactive data streams.
- **Utilities:**
- [Koin](https://insert-koin.io/): Dependency injection framework for Kotlin.
- [Ktor Client](https://ktor.io/docs/client-reference.html): For making HTTP requests (used for parameter documentation).
- [Libsu](https://github.com/topjohnwu/libsu): For interacting with root services.
- [Jsoup](https://jsoup.org/): For parsing HTML (used for parameter documentation).
- [Kotlinx Serialization](https://github.com/Kotlin/kotlinx.serialization): For JSON serialization/deserialization.

## Contributing

We welcome contributions to SysctlGUI!

### Translations
If you'd like to help translate the app into other languages, please see the [translation guide](TRANSLATING.md) for instructions on how to get started. Your contributions will help make SysctlGUI accessible to a wider audience.

## Download

Expand All @@ -47,7 +70,7 @@ A GUI application for Android <code>sysctl</code> to edit kernel variables

This project is licensed under the terms of the MIT license.

> Copyright (c) 2019-2024 Lennoard.
> Copyright (c) 2019-2025 Lennoard.
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
>
Expand Down
62 changes: 62 additions & 0 deletions TRANSLATING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Translating SysctlGUI

Thank you for your interest in translating SysctlGUI! Your contributions help make the app accessible to a wider audience.

## How to Contribute

1. **Fork the Repository:** Start by forking the [SysctlGUI repository](https://github.com/your-github-username/SysctlGUI) (replace `your-github-username/SysctlGUI` with the actual repository URL) to your own GitHub account.
2. **Clone Your Fork:** Clone your forked repository to your local machine.
```bash
git clone https://github.com/YOUR_USERNAME/SysctlGUI.git
cd SysctlGUI
```
3. **Create a New Branch:** Create a new branch for your translation.
```bash
git checkout -b translate-yourlanguage
```
4. **Translate the Files:**
* **String Resources:** These are the primary files for translation.
* `app/src/main/res/values/strings.xml`
* `app/src/main/res/values/params_info.xml`
* `data/src/main/res/values/strings.xml`

To translate these files, create a new `values-xx` directory in the same `res` folder, where `xx` is the ISO 639-1 code for the language you are translating to (e.g., `values-es` for Spanish, `values-de` for German). Then, copy the original `strings.xml` or `params_info.xml` into this new directory and translate the string values within the XML tags.

**Example (strings.xml for Spanish):**
Create `app/src/main/res/values-es/strings.xml` and translate the content, preserving special format tags (%s, %1$s, etc)
```xml
<resources>
<string name="app_name">SysctlGUI</string>
<!-- Translate this -->
<string name="undo">Undo</string>
<string name="selected_file_format">Selected file: %s</string>
<!-- To this -->
<string name="undo">Deshacer</string>
<string name="selected_file_format">Archivo seleccionado: %s</string>
</resources>
```

* **Raw Text Files (Optional):** If you feel brave, you can also translate the `.txt` files located in `data/src/main/res/raw/`.
* When translating these files, it is **crucial** to respect their original format. These files often have a specific structure that the app relies on.
* Translate the text content, but leave any special characters, newlines, or formatting intact.
* Place the translated `.txt` files in a new `raw-xx` directory within `data/src/main/res/` (e.g., `data/src/main/res/raw-es/` for Spanish).

5. **Commit Your Changes:** Commit your translated files with a clear commit message.
```bash
git add .
git commit -m "Add translation to [Your Language]"
```
6. **Push to Your Fork:** Push your changes to your forked repository.
```bash
git push origin translate-yourlanguage
```
7. **Create a Pull Request:** Go to the original SysctlGUI repository on GitHub and create a new Pull Request from your forked branch. Provide a clear description of your changes.

## Important Notes

* Ensure your translations are accurate and natural-sounding in the target language.
* Do not translate resource names (e.g., `app_name` in `<string name="app_name">`). Only translate the text content between the XML tags.
* For `.txt` files, preserving the exact original formatting is critical for the app to function correctly with the translated content.
* If you are unsure about any part of the translation process, feel free to open an issue on the main repository to ask for clarification.

Thank you for your contribution!
91 changes: 46 additions & 45 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import java.util.Properties

plugins {
id("com.android.application")
kotlin("android")
kotlin("kapt")
id("com.google.devtools.ksp")
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.ksp)
alias(libs.plugins.jetbrains.kotlin.serialization)
id("kotlin-parcelize")
}

Expand All @@ -17,10 +17,12 @@ android {
applicationId = AppConfig.appId
minSdk = AppConfig.minSdkVersion
targetSdk = AppConfig.targetSdkVersion
versionCode = 16
versionName = "2.2.2"
versionCode = 17
versionName = "3.0.0"
vectorDrawables.useSupportLibrary = true
resourceConfigurations.addAll(listOf("en", "de", "pt-rBR"))
androidResources {
localeFilters += listOf("en", "de", "pt-rBR", "tr")
}
javaCompileOptions {
annotationProcessorOptions {
arguments += mapOf(
Expand All @@ -29,6 +31,7 @@ android {
)
}
}
multiDexEnabled = true
}

signingConfigs {
Expand Down Expand Up @@ -56,15 +59,13 @@ android {
signingConfig = signingConfigs.getByName("release")
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
"proguard-kt.pro"
"proguard-rules.pro"
)
}
}

buildFeatures {
viewBinding = true
dataBinding = true
compose = true
}

Expand Down Expand Up @@ -93,41 +94,41 @@ android {
targetCompatibility = JavaVersion.VERSION_17
}

kotlin {
jvmToolchain(17)
}

composeOptions {
kotlinCompilerExtensionVersion = Compose.kotlinCompilerExtensionVersion
kotlinOptions {
jvmTarget = "17"
}
}

dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation(kotlin("stdlib-jdk8", KotlinCompilerVersion.VERSION))

implementation(project(Modules.domain))
implementation(project(Modules.data))
implementation(project(Modules.utils))
implementation(project(Modules.design))

implementation(AndroidX.activity)
implementation(AndroidX.splashScreen)
implementation(AndroidX.lifecycleLiveData)
implementation(AndroidX.lifecycleRuntimeCompose)
implementation(AndroidX.navigationFragment)
implementation(AndroidX.navigationUi)
implementation(AndroidX.preference)
implementation(AndroidX.room)
implementation(AndroidX.roomRuntime)
implementation(AndroidX.workManager)
ksp(AndroidX.roomCompiler)

implementation(Google.gson)

implementation(Dependencies.koinAndroid)
implementation(Dependencies.libSuCore)
implementation(Dependencies.libSuIo)
implementation(Dependencies.liveEvent)
implementation(Dependencies.tapTargetView)
}
implementation(project(":common:design"))
implementation(project(":common:utils"))
implementation(project(":domain"))
implementation(project(":data"))

implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines.android)

implementation(libs.androidx.activity.compose)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.core.splashscreen)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.material)
implementation(libs.androidx.glance.appwidget)
implementation(libs.androidx.navigation.compose)
implementation(libs.androidx.window)
implementation(libs.androidx.work.runtime.ktx)
implementation(libs.androidx.multidex)

// Lifecycle
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.androidx.lifecycle.viewmodel.navigation3)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.lifecycle.viewmodel.savedstate)
//ksp(libs.androidx.lifecycle.compiler)

implementation(libs.koin)
implementation(libs.koin.compose)
implementation(libs.bundles.libsu)
}
13 changes: 0 additions & 13 deletions app/proguard-kt.pro

This file was deleted.

35 changes: 17 additions & 18 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,20 @@
# hide the original source file name.
#-renamesourcefileattribute SourceFile

-keep class android.support.v7.widget.SearchView { *; }
-keep class androidx.appcompat.widget.SearchView { *; }
-keep class android.widget.SearchView { *; }

-keepclassmembers enum * { *; }

# GSON config
-keep public class com.google.gson.**
-keep public class com.google.gson.** {public private protected *;}
-keepattributes *Annotation*,Signature

# Gson specific classes
-keep class sun.misc.Unsafe { *; }

# Application classes that will be serialized/deserialized over Gson
-keep class com.androidvip.sysctlgui.data.models.KernelParam { *; }
-keep class com.androidvip.sysctlgui.data.models.RoomKernelParam { *; }
-keep class com.androidvip.sysctlgui.domain.models.DomainKernelParam { *; }
-keepnames class androidx.lifecycle.ViewModel
-keepclassmembers class * extends androidx.lifecycle.ViewModel { <init>(...); }
-keepclassmembers class * implements androidx.lifecycle.LifecycleObserver { <init>(...); }
-keepclassmembers class * implements androidx.lifecycle.LifecycleOwner { <init>(...); }
-keepclassmembers class androidx.lifecycle.Lifecycle$State { *; }
-keepclassmembers class androidx.lifecycle.Lifecycle$Event { *; }
-keep class * implements androidx.lifecycle.LifecycleOwner { public <init>(...); }
-keep class * implements androidx.lifecycle.LifecycleObserver { public <init>(...); }

-keepclassmembers class com.androidvip.sysctlgui.ui.main.MainViewModel {
static void <clinit>();
}

-keep class org.koin.core.instance.InstanceFactory { *; }
-keep class * extends org.koin.core.module.Module
-keep class org.koin.core.registry.ScopeRegistry { *; }
-keep class org.koin.android.scope.AndroidScopeComponent
28 changes: 3 additions & 25 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,7 @@
android:theme="@style/AppTheme"
android:enableOnBackInvokedCallback="true"
tools:ignore="GoogleAppIndexingWarning">

<activity
android:name=".ui.params.user.ManageFavoritesParamsActivity"
android:label="@string/tasker_list_plugin_favorites"
android:launchMode="singleTask"
android:theme="@style/AppTheme" />
<activity
android:name=".ui.params.edit.EditKernelParamActivity"
android:label="@string/edit_params"
android:launchMode="singleTask"
android:theme="@style/AppTheme" />
<activity
android:name=".ui.main.MainActivity"
android:theme="@style/AppTheme" />
<activity
android:name=".ui.params.user.ManageOnStartUpParamsActivity"
android:launchMode="singleTask"
android:label="@string/manage_parameters"
android:theme="@style/AppTheme" />
<activity android:name=".ui.main.MainActivity" />
<activity
android:name=".ui.start.StartActivity"
android:exported="true"
Expand Down Expand Up @@ -76,15 +58,14 @@
</intent-filter>
</receiver>
<receiver
android:name=".widgets.FavoritesWidget"
android:name=".widgets.FavoritesGlanceWidgetReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>

<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/favorites_widget_info" />
android:resource="@xml/favorites_glance_widget_info" />
</receiver>
<receiver
android:name=".receivers.TaskerReceiver"
Expand All @@ -94,9 +75,6 @@
</intent-filter>
</receiver>

<service
android:name=".widgets.FavoritesWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<service
android:name=".services.tiles.StartUpTileService"
android:exported="true"
Expand Down
Loading
Loading