Skip to content

Commit

Permalink
Enhance UI & add apps search feature
Browse files Browse the repository at this point in the history
  • Loading branch information
ismartcoding committed Mar 24, 2024
1 parent e3fec0f commit ca8fb29
Show file tree
Hide file tree
Showing 135 changed files with 1,209 additions and 671 deletions.
10 changes: 5 additions & 5 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ android {
else -> 0
}

val vCode = 256
val vCode = 259
versionCode = vCode - singleAbiNum
versionName = "1.2.41"
versionName = "1.2.42"

ndk {
//noinspection ChromeOsAbiSupport
Expand Down Expand Up @@ -152,8 +152,8 @@ dependencies {
val apollo = "3.2.1"
val kgraphql = "0.19.0"
val ktor = "3.0.0-beta-1"
val media3 = "1.2.1"
val compose = "1.6.1"
val media3 = "1.3.0"
val compose = "1.6.3"

implementation(platform("androidx.compose:compose-bom:2024.01.00"))

Expand All @@ -163,7 +163,7 @@ dependencies {
implementation("androidx.compose.ui:ui:$compose")
implementation("androidx.compose.foundation:foundation:$compose")
implementation("androidx.compose.foundation:foundation-layout:$compose")
implementation("androidx.compose.material3:material3:1.2.0")
implementation("androidx.compose.material3:material3:1.2.1")
implementation("androidx.compose.material:material-icons-extended:$compose")
implementation("com.google.accompanist:accompanist-drawablepainter:0.34.0")
// implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha12")
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,16 @@
</intent-filter>
</receiver>

<receiver
android:name=".receivers.PlugInControlReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
</intent-filter>
</receiver>

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
Expand Down
7 changes: 6 additions & 1 deletion app/src/main/java/com/ismartcoding/plain/MainApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import coil.memory.MemoryCache
import coil.request.CachePolicy
import coil.util.DebugLogger
import com.ismartcoding.lib.brv.utils.BRV
import com.ismartcoding.lib.channel.sendEvent
import com.ismartcoding.lib.helpers.CoroutinesHelper.coIO
import com.ismartcoding.lib.isUPlus
import com.ismartcoding.lib.logcat.DiskLogAdapter
Expand All @@ -34,9 +35,11 @@ import com.ismartcoding.plain.data.preference.PasswordTypePreference
import com.ismartcoding.plain.data.preference.UrlTokenPreference
import com.ismartcoding.plain.data.preference.WebPreference
import com.ismartcoding.plain.data.preference.dataStore
import com.ismartcoding.plain.features.AcquireWakeLockEvent
import com.ismartcoding.plain.features.AppEvents
import com.ismartcoding.plain.features.bluetooth.BluetoothEvents
import com.ismartcoding.plain.features.pkg.PackageHelper
import com.ismartcoding.plain.receivers.PlugInControlReceiver
import com.ismartcoding.plain.services.NotificationListenerMonitorService
import com.ismartcoding.plain.ui.helpers.PageHelper
import com.ismartcoding.plain.web.HttpServerManager
Expand Down Expand Up @@ -119,7 +122,9 @@ class MainApp : Application(), ImageLoaderFactory {
UrlTokenPreference.ensureValueAsync(instance, preferences)

DarkThemePreference.setDarkMode(DarkTheme.parse(DarkThemePreference.get(preferences)))

if (PlugInControlReceiver.isUSBConnected(this@MainApp)) {
sendEvent(AcquireWakeLockEvent())
}
if (PasswordPreference.get(preferences).isEmpty()) {
HttpServerManager.resetPasswordAsync()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ object KeepScreenOnPreference : BasePreference<Boolean>() {
override val key = booleanPreferencesKey("keep_screen_on")
}

object KeepAwakePreference : BasePreference<Boolean>() {
override val default = false
override val key = booleanPreferencesKey("keep_awake")
}

object SystemScreenTimeoutPreference : BasePreference<Int>() {
override val default = 0
override val key = intPreferencesKey("system_screen_timeout")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ data class WebSettings(
val password: String,
val authTwoFactor: Boolean,
val authDevToken: String,
val keepAwake: Boolean,
val apiPermissions: Set<String>,
)

Expand All @@ -21,6 +22,7 @@ val LocalPassword = compositionLocalOf { PasswordPreference.default }
val LocalAuthTwoFactor = compositionLocalOf { AuthTwoFactorPreference.default }
val LocalApiPermissions = compositionLocalOf { ApiPermissionsPreference.default }
val LocalAuthDevToken = compositionLocalOf { AuthDevTokenPreference.default }
val LocalKeepAwake = compositionLocalOf { KeepAwakePreference.default }

@Composable
fun WebSettingsProvider(content: @Composable () -> Unit) {
Expand All @@ -31,6 +33,7 @@ fun WebSettingsProvider(content: @Composable () -> Unit) {
password = PasswordPreference.default,
authTwoFactor = AuthTwoFactorPreference.default,
authDevToken = AuthDevTokenPreference.default,
keepAwake = KeepAwakePreference.default,
apiPermissions = ApiPermissionsPreference.default,
)
val settings =
Expand All @@ -41,6 +44,7 @@ fun WebSettingsProvider(content: @Composable () -> Unit) {
password = PasswordPreference.get(it),
authTwoFactor = AuthTwoFactorPreference.get(it),
authDevToken = AuthDevTokenPreference.get(it),
keepAwake = KeepAwakePreference.get(it),
apiPermissions = ApiPermissionsPreference.get(it),
)
}
Expand All @@ -53,6 +57,7 @@ fun WebSettingsProvider(content: @Composable () -> Unit) {
LocalPassword provides settings.password,
LocalAuthTwoFactor provides settings.authTwoFactor,
LocalAuthDevToken provides settings.authDevToken,
LocalKeepAwake provides settings.keepAwake,
LocalApiPermissions provides settings.apiPermissions,
) {
content()
Expand Down
22 changes: 22 additions & 0 deletions app/src/main/java/com/ismartcoding/plain/features/AppEvents.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.ismartcoding.plain.features
import android.content.Intent
import android.media.MediaPlayer
import android.net.Uri
import android.os.PowerManager
import com.aallam.openai.api.BetaOpenAI
import com.aallam.openai.api.chat.ChatCompletionRequest
import com.aallam.openai.api.chat.ChatMessage
Expand All @@ -17,6 +18,7 @@ import com.ismartcoding.lib.helpers.CoroutinesHelper.coIO
import com.ismartcoding.lib.helpers.JsonHelper.jsonEncode
import com.ismartcoding.lib.helpers.SslHelper
import com.ismartcoding.lib.logcat.LogCat
import com.ismartcoding.plain.BuildConfig
import com.ismartcoding.plain.MainApp
import com.ismartcoding.plain.data.enums.*
import com.ismartcoding.plain.data.preference.ChatGPTApiKeyPreference
Expand All @@ -25,6 +27,7 @@ import com.ismartcoding.plain.features.aichat.AIChatHelper
import com.ismartcoding.plain.features.audio.AudioAction
import com.ismartcoding.plain.features.audio.AudioPlayer
import com.ismartcoding.plain.features.feed.FeedWorkerStatus
import com.ismartcoding.plain.powerManager
import com.ismartcoding.plain.services.HttpServerService
import com.ismartcoding.plain.web.AuthRequest
import com.ismartcoding.plain.web.websocket.EventType
Expand Down Expand Up @@ -89,6 +92,8 @@ class ActionEvent(val source: ActionSourceType, val action: ActionType, val ids:
class AudioActionEvent(val action: AudioAction)

class IgnoreBatteryOptimizationEvent
class AcquireWakeLockEvent
class ReleaseWakeLockEvent

class IgnoreBatteryOptimizationResultEvent

Expand All @@ -107,6 +112,7 @@ class AIChatCreatedEvent(val item: DAIChat)
object AppEvents {
private lateinit var mediaPlayer: MediaPlayer
private var mediaPlayingUri: Uri? = null
private val wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "${BuildConfig.APPLICATION_ID}:http_server")

@OptIn(BetaOpenAI::class)
fun register() {
Expand Down Expand Up @@ -145,6 +151,22 @@ object AppEvents {
}
}

receiveEventHandler<AcquireWakeLockEvent> {
coIO {
LogCat.d("AcquireWakeLockEvent")
if (!wakeLock.isHeld) {
wakeLock.acquire()
}
}
}

receiveEventHandler<ReleaseWakeLockEvent> {
coIO {
LogCat.d("ReleaseWakeLockEvent")
wakeLock.release()
}
}

receiveEventHandler<PermissionsResultEvent> { event ->
if (event.map.containsKey(Permission.POST_NOTIFICATIONS.toSysPermission())) {
if (AudioPlayer.isPlaying()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,27 +73,31 @@ object FileSystemHelper {

fun getInternalStoragePath(): String {
return (
if (isRPlus()) {
storageManager.primaryStorageVolume.directory?.path
} else {
null
}
) ?: Environment.getExternalStorageDirectory()?.absolutePath?.trimEnd('/') ?: ""
if (isRPlus()) {
storageManager.primaryStorageVolume.directory?.path
} else {
null
}
) ?: Environment.getExternalStorageDirectory()?.absolutePath?.trimEnd('/') ?: ""
}

fun getInternalStorageName(context: Context): String {
return storageManager.primaryStorageVolume.getDescription(context) ?: getString(R.string.internal_storage)
}

fun getExternalFilesDirPath(context: Context): String {
return context.getExternalFilesDir(null)!!.absolutePath
}

fun getSDCardPath(context: Context): String {
val internalPath = getInternalStoragePath()
val directories =
getStorageDirectories(context).filter {
it != internalPath &&
!it.equals(
"/storage/emulated/0",
true,
)
!it.equals(
"/storage/emulated/0",
true,
)
}

val fullSDPattern = Pattern.compile("^/storage/[A-Za-z0-9]{4}-[A-Za-z0-9]{4}$")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,47 @@
package com.ismartcoding.plain.receivers

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import com.ismartcoding.lib.channel.sendEvent
import com.ismartcoding.lib.helpers.CoroutinesHelper.coIO
import com.ismartcoding.lib.isTPlus
import com.ismartcoding.lib.logcat.LogCat
import com.ismartcoding.plain.data.preference.KeepAwakePreference
import com.ismartcoding.plain.features.AcquireWakeLockEvent
import com.ismartcoding.plain.features.ReleaseWakeLockEvent

object PlugInControlReceiver {
private const val ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"
class PlugInControlReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (action == Intent.ACTION_POWER_CONNECTED) {
LogCat.d("ACTION_POWER_CONNECTED")
sendEvent(AcquireWakeLockEvent())
} else if (action == Intent.ACTION_POWER_DISCONNECTED) {
LogCat.d("ACTION_POWER_DISCONNECTED")
coIO {
val keepAwake = KeepAwakePreference.getAsync(context)
if (!keepAwake) {
sendEvent(ReleaseWakeLockEvent())
}
}
}
}

fun isUSBConnected(context: Context): Boolean {
val intent = if (isTPlus()) {
context.registerReceiver(
null,
IntentFilter(ACTION_USB_STATE),
Context.RECEIVER_NOT_EXPORTED,
)
} else {
context.registerReceiver(null, IntentFilter(ACTION_USB_STATE))
companion object {
private const val ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"
fun isUSBConnected(context: Context): Boolean {
val intent = if (isTPlus()) {
context.registerReceiver(
null,
IntentFilter(ACTION_USB_STATE),
Context.RECEIVER_NOT_EXPORTED,
)
} else {
context.registerReceiver(null, IntentFilter(ACTION_USB_STATE))
}
return intent?.extras?.getBoolean("connected") == true
}
return intent?.extras?.getBoolean("connected") == true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import com.ismartcoding.lib.logcat.LogCat
class NotificationListenerMonitorService : Service() {
override fun onCreate() {
super.onCreate()
LogCat.d("onCreate() called")
LogCat.d("NotificationListenerMonitorService.onCreate() called")
ensureCollectorRunning()
}

Expand Down
11 changes: 11 additions & 0 deletions app/src/main/java/com/ismartcoding/plain/ui/base/ActionButtons.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.ismartcoding.plain.ui.base

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
Expand All @@ -27,3 +28,13 @@ fun ActionButtonSettings(onClick: () -> Unit) {
onClick = onClick,
)
}

@Composable
fun ActionButtonSearch(onClick: () -> Unit) {
PIconButton(
imageVector = Icons.Outlined.Search,
contentDescription = stringResource(R.string.search),
tint = MaterialTheme.colorScheme.onSurface,
onClick = onClick,
)
}
10 changes: 6 additions & 4 deletions app/src/main/java/com/ismartcoding/plain/ui/base/Alert.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
Expand Down Expand Up @@ -54,18 +55,19 @@ fun Alert(
HorizontalSpace(dp = 8.dp)
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
style = MaterialTheme.typography.titleMedium.copy(
color = MaterialTheme.colorScheme.onSurface,
fontWeight = FontWeight.SemiBold
),
textAlign = TextAlign.Start,
color = MaterialTheme.colorScheme.onSurface,
)
}
Text(
modifier = Modifier
.padding(16.dp, 0.dp, 16.dp, 16.dp)
.fillMaxWidth(),
text = description,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.bodyLarge.copy(color = MaterialTheme.colorScheme.onSurface),
)
if (actions != null) {
Row(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import androidx.compose.ui.res.stringResource
import com.ismartcoding.plain.R

@Composable
fun NoDataColumn(loading: Boolean = false) {
fun NoDataColumn(loading: Boolean = false, search: Boolean = false) {
LazyColumn(
Modifier
.fillMaxWidth()
Expand All @@ -22,8 +22,13 @@ fun NoDataColumn(loading: Boolean = false) {
horizontalAlignment = Alignment.CenterHorizontally,
) {
item {
val text = if (search) {
if (loading) R.string.searching else R.string.no_results_found
} else {
if (loading) R.string.loading else R.string.no_data
}
Text(
text = stringResource(id = if (loading) R.string.loading else R.string.no_data),
text = stringResource(id = text),
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Expand Down
Loading

0 comments on commit ca8fb29

Please sign in to comment.