Skip to content

Commit fad5c58

Browse files
committed
Add log export, fix cooldown
1 parent 15149ba commit fad5c58

9 files changed

Lines changed: 501 additions & 335 deletions

File tree

app/src/main/AndroidManifest.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,16 @@
122122
</intent-filter>
123123
</receiver>
124124

125+
<provider
126+
android:name="androidx.core.content.FileProvider"
127+
android:authorities="${applicationId}.fileprovider"
128+
android:exported="false"
129+
android:grantUriPermissions="true">
130+
<meta-data
131+
android:name="android.support.FILE_PROVIDER_PATHS"
132+
android:resource="@xml/file_paths" />
133+
</provider>
134+
125135
<provider
126136
android:name="rikka.shizuku.ShizukuProvider"
127137
android:authorities="${applicationId}.shizuku"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package dev.pranav.applock.core.utils
2+
3+
import android.content.Context
4+
import android.net.Uri
5+
import android.util.Log
6+
import androidx.core.content.FileProvider
7+
import java.io.File
8+
import java.io.FileWriter
9+
10+
object LogUtils {
11+
private const val TAG = "LogUtils"
12+
private const val FILE_NAME = "app_logs.txt"
13+
14+
fun exportLogs(context: Context): Uri? {
15+
val file = File(context.cacheDir, FILE_NAME)
16+
try {
17+
// Clear previous logs if file exists
18+
if (file.exists()) {
19+
file.delete()
20+
}
21+
file.createNewFile()
22+
23+
// Run logcat command to get logs
24+
val process = Runtime.getRuntime().exec("logcat -d")
25+
val bufferedReader = process.inputStream.bufferedReader()
26+
val writer = FileWriter(file)
27+
28+
// Write logs to file
29+
bufferedReader.use { reader ->
30+
writer.use { out ->
31+
var line: String?
32+
while (reader.readLine().also { line = it } != null) {
33+
out.write(line + "\n")
34+
}
35+
}
36+
}
37+
38+
// Return Uri using FileProvider
39+
return FileProvider.getUriForFile(
40+
context,
41+
"${context.packageName}.fileprovider",
42+
file
43+
)
44+
45+
} catch (e: Exception) {
46+
Log.e(TAG, "Error exporting logs", e)
47+
return null
48+
}
49+
}
50+
}

app/src/main/java/dev/pranav/applock/features/applist/ui/MainScreen.kt

Lines changed: 67 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -11,54 +11,18 @@ import android.util.Log
1111
import android.widget.Toast
1212
import androidx.compose.foundation.Image
1313
import androidx.compose.foundation.clickable
14-
import androidx.compose.foundation.layout.Arrangement
15-
import androidx.compose.foundation.layout.Box
16-
import androidx.compose.foundation.layout.Column
17-
import androidx.compose.foundation.layout.PaddingValues
18-
import androidx.compose.foundation.layout.Row
19-
import androidx.compose.foundation.layout.Spacer
20-
import androidx.compose.foundation.layout.fillMaxSize
21-
import androidx.compose.foundation.layout.fillMaxWidth
22-
import androidx.compose.foundation.layout.height
23-
import androidx.compose.foundation.layout.padding
24-
import androidx.compose.foundation.layout.size
14+
import androidx.compose.foundation.layout.*
2515
import androidx.compose.foundation.lazy.LazyColumn
2616
import androidx.compose.foundation.lazy.items
2717
import androidx.compose.foundation.shape.RoundedCornerShape
2818
import androidx.compose.material.icons.Icons
29-
import androidx.compose.material.icons.filled.Block
30-
import androidx.compose.material.icons.filled.FilterList
31-
import androidx.compose.material.icons.filled.Search
32-
import androidx.compose.material.icons.filled.Settings
33-
import androidx.compose.material.icons.filled.Shield
19+
import androidx.compose.material.icons.filled.*
3420
import androidx.compose.material.icons.outlined.Security
3521
import androidx.compose.material.icons.outlined.Shield
36-
import androidx.compose.material3.AlertDialog
37-
import androidx.compose.material3.CircularProgressIndicator
38-
import androidx.compose.material3.DropdownMenu
39-
import androidx.compose.material3.DropdownMenuItem
40-
import androidx.compose.material3.ExperimentalMaterial3Api
41-
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
42-
import androidx.compose.material3.FilledTonalButton
43-
import androidx.compose.material3.Icon
44-
import androidx.compose.material3.IconButton
45-
import androidx.compose.material3.MaterialTheme
46-
import androidx.compose.material3.MediumFlexibleTopAppBar
47-
import androidx.compose.material3.Scaffold
48-
import androidx.compose.material3.SearchBar
49-
import androidx.compose.material3.SearchBarDefaults
50-
import androidx.compose.material3.Surface
51-
import androidx.compose.material3.Switch
52-
import androidx.compose.material3.Text
53-
import androidx.compose.material3.TextButton
54-
import androidx.compose.material3.TopAppBarDefaults
55-
import androidx.compose.runtime.Composable
56-
import androidx.compose.runtime.LaunchedEffect
57-
import androidx.compose.runtime.collectAsState
58-
import androidx.compose.runtime.getValue
59-
import androidx.compose.runtime.mutableStateOf
60-
import androidx.compose.runtime.remember
61-
import androidx.compose.runtime.setValue
22+
import androidx.compose.material.icons.rounded.Forum
23+
import androidx.compose.material.icons.rounded.Groups
24+
import androidx.compose.material3.*
25+
import androidx.compose.runtime.*
6226
import androidx.compose.ui.Alignment
6327
import androidx.compose.ui.Modifier
6428
import androidx.compose.ui.graphics.ImageBitmap
@@ -84,10 +48,7 @@ import dev.pranav.applock.core.utils.hasUsagePermission
8448
import dev.pranav.applock.core.utils.isAccessibilityServiceEnabled
8549
import dev.pranav.applock.core.utils.openAccessibilitySettings
8650
import dev.pranav.applock.data.repository.BackendImplementation
87-
import dev.pranav.applock.ui.components.AccessibilityServiceGuideDialog
88-
import dev.pranav.applock.ui.components.AntiUninstallAccessibilityPermissionDialog
89-
import dev.pranav.applock.ui.components.ShizukuPermissionDialog
90-
import dev.pranav.applock.ui.components.UsageStatsPermission
51+
import dev.pranav.applock.ui.components.*
9152
import rikka.shizuku.Shizuku
9253

9354
@OptIn(
@@ -273,63 +234,27 @@ fun MainScreen(
273234
var showCommunityLink by remember { mutableStateOf(appLockRepository.isShowCommunityLink()) }
274235

275236
if (showCommunityLink && !showAccessibilityDialog && !showShizukuDialog && !showUsageStatsDialog && !showAntiUninstallAccessibilityDialog && !showAntiUninstallDeviceAdminDialog && !showOverlayDialog) {
276-
AlertDialog(
277-
onDismissRequest = { appLockRepository.setCommunityLinkShown(true) },
278-
title = { Text(stringResource(R.string.main_screen_join_community_dialog_title)) },
279-
text = { Text(stringResource(R.string.main_screen_join_community_dialog_text)) },
280-
confirmButton = {
281-
TextButton(onClick = {
282-
appLockRepository.setCommunityLinkShown(true)
283-
showCommunityLink = false
284-
context.startActivity(
285-
Intent(
286-
Intent.ACTION_VIEW,
287-
"https://discord.gg/46wCMRVAre".toUri() // Keep this as is, not a user-facing string
288-
)
289-
)
290-
}) {
291-
Text(stringResource(R.string.main_screen_join_community_join_discord_button))
292-
}
237+
CommunityDialog(
238+
onDismiss = {
239+
appLockRepository.setCommunityLinkShown(true)
240+
showCommunityLink = false
293241
},
294-
dismissButton = {
295-
TextButton(onClick = {
296-
appLockRepository.setCommunityLinkShown(true)
297-
showCommunityLink = false
298-
}) {
299-
Text(stringResource(R.string.main_screen_join_community_dismiss_button))
300-
}
242+
onJoin = {
243+
appLockRepository.setCommunityLinkShown(true)
244+
showCommunityLink = false
245+
context.startActivity(
246+
Intent(
247+
Intent.ACTION_VIEW,
248+
"https://discord.gg/46wCMRVAre".toUri()
249+
)
250+
)
301251
}
302252
)
303253
}
304254

305255
var showDonateDialog by remember { mutableStateOf(appLockRepository.isShowDonateLink()) }
306256
if (showDonateDialog && !showAccessibilityDialog && !showShizukuDialog && !showUsageStatsDialog && !showAntiUninstallAccessibilityDialog && !showAntiUninstallDeviceAdminDialog && !showCommunityLink && !showOverlayDialog) {
307-
AlertDialog(
308-
onDismissRequest = { showDonateDialog = false },
309-
title = { Text(stringResource(R.string.main_screen_support_development_dialog_title)) },
310-
text = { Text(stringResource(R.string.support_development_text)) },
311-
confirmButton = {
312-
FilledTonalButton(
313-
onClick = {
314-
context.startActivity(
315-
Intent(
316-
Intent.ACTION_VIEW,
317-
"https://paypal.me/pranavpurwar".toUri() // Keep this as is, not a user-facing string
318-
)
319-
)
320-
showDonateDialog = false
321-
appLockRepository.setShowDonateLink(false)
322-
}
323-
) { Text(stringResource(R.string.main_screen_support_development_donate_button)) }
324-
},
325-
dismissButton = {
326-
TextButton(onClick = {
327-
showDonateDialog = false
328-
appLockRepository.setShowDonateLink(false)
329-
}) { Text(stringResource(R.string.cancel_button)) }
330-
},
331-
containerColor = MaterialTheme.colorScheme.surfaceContainer
332-
)
257+
DonateModalBottomSheet { showDonateDialog = false }
333258
}
334259

335260
Scaffold(
@@ -665,3 +590,49 @@ private fun AppItem(
665590
)
666591
}
667592
}
593+
594+
@Composable
595+
private fun CommunityDialog(
596+
onDismiss: () -> Unit,
597+
onJoin: () -> Unit
598+
) {
599+
AlertDialog(
600+
onDismissRequest = onDismiss,
601+
icon = {
602+
Icon(
603+
Icons.Rounded.Groups,
604+
contentDescription = null,
605+
modifier = Modifier.size(32.dp),
606+
tint = MaterialTheme.colorScheme.primary
607+
)
608+
},
609+
title = {
610+
Text(
611+
text = stringResource(R.string.join_community),
612+
style = MaterialTheme.typography.headlineSmall
613+
)
614+
},
615+
text = {
616+
Text(
617+
text = stringResource(R.string.join_community_desc),
618+
style = MaterialTheme.typography.bodyMedium
619+
)
620+
},
621+
confirmButton = {
622+
Button(onClick = onJoin) {
623+
Icon(
624+
Icons.Rounded.Forum,
625+
contentDescription = null,
626+
modifier = Modifier.size(18.dp)
627+
)
628+
Spacer(Modifier.width(8.dp))
629+
Text(stringResource(R.string.join_discord))
630+
}
631+
},
632+
dismissButton = {
633+
TextButton(onClick = onDismiss) {
634+
Text(stringResource(R.string.maybe_later))
635+
}
636+
}
637+
)
638+
}

0 commit comments

Comments
 (0)