Skip to content

Commit 8d65c0e

Browse files
committed
Improve UI
1 parent 4cfece4 commit 8d65c0e

File tree

22 files changed

+104
-98
lines changed

22 files changed

+104
-98
lines changed

README.md

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,44 @@
11
# PlainApp
22

3-
PlainApp is an open-source application that allows you to manage your phone through a web browser. Access files, videos, music, contacts, sms, calls, and more from your desktop using a secure, easy to use web interface!
3+
PlainApp is an open-source app that lets you securely manage your phone from a web browser. Access files, media, contacts, SMS, calls, and more through a simple, easy-to-use interface on your desktop.
44

55
[<img src="https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png" alt='Get it on Google Play' height="80">](https://play.google.com/store/apps/details?id=com.ismartcoding.plain)
66
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" alt='Get it on F-Droid' height="80">](https://f-droid.org/packages/com.ismartcoding.plain/)
77
[<img src="https://raw.githubusercontent.com/ismartcoding/plain-app/main/assets/get-it-on-github.png" alt='Get it on GitHub' height="80">](https://github.com/ismartcoding/plain-app/releases/latest)
88

99
## Features
1010

11-
- Privacy oriented: We take your privacy seriously and use TLS + AES-GCM-256 encryption to ensure your data is secure.
12-
- Ad-free forever: You won't be bombarded with ads when using PlainApp.
13-
- No cloud services or third-party data storage: All data is kept on your device, so you have complete control over your information.
14-
- No Firebase Cloud Messaging/Analytics: We don't track your activity or use your data for advertising purposes. We only collect crash logs through Firebase Crashlytics.
15-
- User-friendly: PlainApp has a modern, customizable interface with multi-language support, light/dark theme options, and e-ink screen compatibility.
16-
- Desktop management: You can manage your phone from your desktop by visiting a self-hosted webpage wirelessly.
17-
- Contacts management: You can manage these features on the self-hosted webpage as well.
18-
- File management: Manage files(Internal storage, SD card, USB storage), images, videos, and audio on the self-hosted webpage.
19-
- Note-taking: Use PlainApp to manage your notes with a built-in Markdown editor.
20-
- RSS reader: Read articles in a clean UI.
21-
- TV casting: Cast your videos, images, and audio to your TV.
22-
- Video and audio playback: Play videos and audio in the app and on the webpage.
23-
- Backup and export: Backup and export your app data for safekeeping.
24-
- SMS, Calls: Read your SMS and calls on webpage.
25-
- Apps: View your apps and download apk from phone.
26-
- Screen mirror: Mirror your phone on webpage.
27-
- Notifications: You can manage push notifications on the webpage.
28-
- Device info: You can view your device info on the webpage.
29-
- PWA support: You can add webpage to your home screen and experience the convenience of using the webpage like a desktop app.
30-
- And more features are planned for the future.
31-
32-
PlainApp's minimalist design is intentional, so you can focus on what matters most: your valuable data.
11+
**Privacy First**
12+
- All data stays on your device — no cloud, no third-party storage
13+
- No Firebase Messaging or Analytics; only crash logs (optional) via Firebase Crashlytics
14+
- Secured with TLS + AES-GCM-256 encryption
15+
16+
**Ad-Free, Always**
17+
- 100% ad-free experience, forever
18+
19+
**Clean, Modern Interface**
20+
- Minimalist and customizable UI
21+
- Supports multiple languages, light/dark themes
22+
23+
**Web-Based Desktop Management**
24+
Access a self-hosted webpage on the same network to manage your phone:
25+
- Files: Internal storage, SD card, USB, images, videos, audio
26+
- Contacts, SMS, and call logs
27+
- Installed apps (with APK export)
28+
- Notifications and device info
29+
- Screen mirroring
30+
- PWA support — add the web app to your desktop/home screen
31+
32+
**Built-in Tools**
33+
- Markdown note-taking
34+
- RSS reader with clean UI
35+
- Video and audio player (in-app and on the web)
36+
- TV casting for media
37+
38+
**Always Improving**
39+
- More features are on the way
40+
41+
PlainApp is designed with simplicity in mind, so you can focus on what matters most: your data.
3342

3443
Video: https://www.youtube.com/watch?v=TjRhC8pSQ6Q
3544

@@ -78,9 +87,12 @@ PlainApp requires Android 9.0 or higher.
7887

7988
## Support
8089

81-
It's worth mentioning that this is an open-source application.
82-
If you have doubts, you can either build your own version or choose not to use it.
83-
If you encounter any issues, feel free to open an issue on GitHub. I am always happy to help. Please do not give a one-star rating arbitrarily.
90+
PlainApp is fully open-source.
91+
If you have any doubts, you're free to review the code, build your own version, or simply choose not to use it.
92+
93+
If you run into issues, feel free to open a GitHub issue — I'm always happy to help.
94+
95+
Please don’t leave a one-star review without giving it a fair try.
8496

8597
## Build
8698

app/src/main/java/com/ismartcoding/plain/ui/base/NeedPermissionColumn.kt

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ import androidx.compose.foundation.shape.CircleShape
2222
import androidx.compose.foundation.shape.RoundedCornerShape
2323
import androidx.compose.material3.Button
2424
import androidx.compose.material3.ButtonDefaults
25-
import androidx.compose.material3.Card
26-
import androidx.compose.material3.CardDefaults
2725
import androidx.compose.material3.Icon
2826
import androidx.compose.material3.MaterialTheme
2927
import androidx.compose.material3.Surface
@@ -45,7 +43,6 @@ import com.ismartcoding.lib.channel.sendEvent
4543
import com.ismartcoding.plain.R
4644
import com.ismartcoding.plain.data.DFeaturePermission
4745
import com.ismartcoding.plain.features.RequestPermissionsEvent
48-
import com.ismartcoding.plain.ui.theme.cardContainer
4946

5047
@Composable
5148
fun NeedPermissionColumn(
@@ -65,47 +62,45 @@ fun NeedPermissionColumn(
6562
animationSpec = tween(800, easing = FastOutSlowInEasing)
6663
)
6764
) {
68-
PCard {
69-
Column(
65+
Column(
66+
modifier = Modifier
67+
.fillMaxWidth()
68+
.padding(26.dp),
69+
horizontalAlignment = Alignment.CenterHorizontally,
70+
verticalArrangement = Arrangement.spacedBy(20.dp)
71+
) {
72+
AnimatedIconContainer(icon)
73+
74+
Text(
75+
text = permission.permission.getGrantAccessText(),
76+
style = MaterialTheme.typography.titleLarge.copy(
77+
fontWeight = FontWeight.SemiBold,
78+
letterSpacing = 0.sp
79+
),
80+
color = MaterialTheme.colorScheme.onSurface,
81+
textAlign = TextAlign.Center,
82+
modifier = Modifier.padding(top = 8.dp, start = 4.dp, end = 4.dp)
83+
)
84+
85+
Button(
86+
onClick = {
87+
sendEvent(RequestPermissionsEvent(*permission.permissions.toTypedArray()))
88+
},
7089
modifier = Modifier
7190
.fillMaxWidth()
72-
.padding(26.dp),
73-
horizontalAlignment = Alignment.CenterHorizontally,
74-
verticalArrangement = Arrangement.spacedBy(20.dp)
91+
.padding(top = 16.dp, start = 16.dp, end = 16.dp)
92+
.shadow(8.dp, RoundedCornerShape(16.dp)),
93+
colors = ButtonDefaults.buttonColors(
94+
containerColor = MaterialTheme.colorScheme.primary
95+
),
96+
shape = RoundedCornerShape(16.dp),
97+
contentPadding = PaddingValues(vertical = 16.dp, horizontal = 16.dp)
7598
) {
76-
AnimatedIconContainer(icon)
77-
7899
Text(
79-
text = permission.permission.getGrantAccessText(),
80-
style = MaterialTheme.typography.titleLarge.copy(
81-
fontWeight = FontWeight.SemiBold,
82-
letterSpacing = 0.sp
83-
),
84-
color = MaterialTheme.colorScheme.onSurface,
85-
textAlign = TextAlign.Center,
86-
modifier = Modifier.padding(top = 8.dp, start = 4.dp, end = 4.dp)
100+
text = stringResource(id = R.string.grant_access),
101+
style = MaterialTheme.typography.titleMedium,
102+
fontWeight = FontWeight.Medium,
87103
)
88-
89-
Button(
90-
onClick = {
91-
sendEvent(RequestPermissionsEvent(*permission.permissions.toTypedArray()))
92-
},
93-
modifier = Modifier
94-
.fillMaxWidth()
95-
.padding(top = 16.dp, start = 16.dp, end = 16.dp)
96-
.shadow(8.dp, RoundedCornerShape(16.dp)),
97-
colors = ButtonDefaults.buttonColors(
98-
containerColor = MaterialTheme.colorScheme.primary
99-
),
100-
shape = RoundedCornerShape(16.dp),
101-
contentPadding = PaddingValues(vertical = 16.dp, horizontal = 16.dp)
102-
) {
103-
Text(
104-
text = stringResource(id = R.string.grant_access),
105-
style = MaterialTheme.typography.titleMedium,
106-
fontWeight = FontWeight.Medium,
107-
)
108-
}
109104
}
110105
}
111106
}
@@ -132,7 +127,7 @@ private fun AnimatedIconContainer(
132127
repeatMode = RepeatMode.Reverse
133128
)
134129
)
135-
130+
136131
// Outer pulsing circle
137132
Surface(
138133
modifier = Modifier
@@ -143,7 +138,7 @@ private fun AnimatedIconContainer(
143138
) {
144139
Box(modifier = Modifier.fillMaxSize())
145140
}
146-
141+
147142
// Inner circle with icon
148143
Surface(
149144
modifier = Modifier

app/src/main/java/com/ismartcoding/plain/ui/base/PAlert.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ import androidx.compose.foundation.layout.Row
55
import androidx.compose.foundation.layout.RowScope
66
import androidx.compose.foundation.layout.fillMaxWidth
77
import androidx.compose.foundation.layout.padding
8+
import androidx.compose.foundation.layout.size
89
import androidx.compose.material3.Icon
910
import androidx.compose.material3.MaterialTheme
1011
import androidx.compose.material3.Text
1112
import androidx.compose.runtime.Composable
1213
import androidx.compose.ui.Alignment
1314
import androidx.compose.ui.Modifier
14-
import androidx.compose.ui.res.colorResource
1515
import androidx.compose.ui.res.painterResource
1616
import androidx.compose.ui.text.font.FontWeight
1717
import androidx.compose.ui.text.style.TextAlign
1818
import androidx.compose.ui.unit.dp
1919
import com.ismartcoding.plain.R
20+
import com.ismartcoding.plain.ui.theme.orange
2021
import com.ismartcoding.plain.ui.theme.red
21-
import com.ismartcoding.plain.ui.theme.yellow
2222

2323
enum class AlertType {
2424
WARNING,
@@ -40,15 +40,16 @@ fun PAlert(
4040
verticalAlignment = Alignment.CenterVertically
4141
) {
4242
Icon(
43-
painter = painterResource(R.drawable.circle_alert),
43+
painter = painterResource(if (type == AlertType.WARNING) R.drawable.circle_alert else R.drawable.circle_x),
4444
contentDescription = "",
45-
tint = if (type == AlertType.WARNING) MaterialTheme.colorScheme.yellow else MaterialTheme.colorScheme.red,
45+
modifier = Modifier.size(20.dp),
46+
tint = if (type == AlertType.WARNING) MaterialTheme.colorScheme.orange else MaterialTheme.colorScheme.red,
4647
)
4748
HorizontalSpace(dp = 8.dp)
4849
Text(
4950
text = title,
5051
style = MaterialTheme.typography.titleMedium.copy(
51-
color = MaterialTheme.colorScheme.onSurface,
52+
color = if (type == AlertType.WARNING) MaterialTheme.colorScheme.orange else MaterialTheme.colorScheme.red,
5253
fontWeight = FontWeight.SemiBold
5354
),
5455
textAlign = TextAlign.Start,
@@ -59,7 +60,7 @@ fun PAlert(
5960
.padding(16.dp, 0.dp, 16.dp, 16.dp)
6061
.fillMaxWidth(),
6162
text = description,
62-
style = MaterialTheme.typography.bodyLarge.copy(color = MaterialTheme.colorScheme.onSurface),
63+
style = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onSurface),
6364
)
6465
if (actions != null) {
6566
Row(

app/src/main/java/com/ismartcoding/plain/ui/theme/ColorScheme.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,18 @@ val ColorScheme.yellow: Color
6767
@Composable
6868
@ReadOnlyComposable
6969
get() = if (DarkTheme.isDarkTheme(LocalDarkTheme.current)) {
70-
Color(0xFFFFEB3B)
70+
Color(0xFFFFB300)
7171
} else {
72-
Color(0xFFFFEB3B)
72+
Color(0xFFFFCC00)
7373
}
7474

7575
val ColorScheme.orange: Color
7676
@Composable
7777
@ReadOnlyComposable
7878
get() = if (DarkTheme.isDarkTheme(LocalDarkTheme.current)) {
79-
Color(0xFFFF9800)
79+
Color(0xFFFFB74D)
8080
} else {
81-
Color(0xFFFF9800)
81+
Color(0xFFF57C00)
8282
}
8383

8484
val ColorScheme.navBarBackground: Color

app/src/main/java/com/ismartcoding/plain/web/HttpModule.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ import com.ismartcoding.lib.extensions.compress
1111
import com.ismartcoding.lib.extensions.getFinalPath
1212
import com.ismartcoding.lib.extensions.isImageFast
1313
import com.ismartcoding.lib.extensions.isUrl
14-
import com.ismartcoding.plain.extensions.newFile
1514
import com.ismartcoding.lib.extensions.scanFileByConnection
16-
import com.ismartcoding.plain.extensions.toThumbBytesAsync
1715
import com.ismartcoding.lib.extensions.urlEncode
1816
import com.ismartcoding.lib.helpers.CoroutinesHelper.coIO
1917
import com.ismartcoding.lib.helpers.CoroutinesHelper.withIO
@@ -33,6 +31,8 @@ import com.ismartcoding.plain.data.UploadInfo
3331
import com.ismartcoding.plain.enums.DataType
3432
import com.ismartcoding.plain.enums.ImageType
3533
import com.ismartcoding.plain.enums.PasswordType
34+
import com.ismartcoding.plain.extensions.newFile
35+
import com.ismartcoding.plain.extensions.toThumbBytesAsync
3636
import com.ismartcoding.plain.features.ConfirmToAcceptLoginEvent
3737
import com.ismartcoding.plain.features.PackageHelper
3838
import com.ismartcoding.plain.features.file.FileSortBy
@@ -48,7 +48,6 @@ import com.ismartcoding.plain.preference.PasswordPreference
4848
import com.ismartcoding.plain.preference.PasswordTypePreference
4949
import com.ismartcoding.plain.web.websocket.WebSocketSession
5050
import io.ktor.client.request.get
51-
import io.ktor.client.statement.readBytes
5251
import io.ktor.client.statement.readRawBytes
5352
import io.ktor.http.CacheControl
5453
import io.ktor.http.ContentType
@@ -111,7 +110,6 @@ import java.io.IOException
111110
import java.util.Date
112111
import java.util.zip.ZipEntry
113112
import java.util.zip.ZipOutputStream
114-
import kotlin.collections.set
115113

116114
object HttpModule {
117115
@SuppressLint("SuspiciousIndentation")

app/src/main/res/values-bn/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
<string name="privacy_policy">গোপনীয়তা নীতি</string>
166166
<string name="terms_of_use">ব্যবহারের শর্তাবলী</string>
167167
<string name="grant_permission">অনুমতি দান করুন</string>
168-
<string name="system_alert_window_warning">‘অন্য অ্যাপস উপর প্রদর্শন’ অনুমতি দেওয়া গুরুত্বপূর্ণ। এই অনুমতি না থাকলে, যদি অ্যাপটি ব্যাকগ্রাউন্ডে চলছে, আপনি অ্যাপ দ্বারা সৃষ্টিকৃত মৌলিক সিস্টেম ডায়ালগ, যেমন অনইনস্টলেশন নিশ্চিতকরণ ডায়ালগ, অনুমতি দেওয়া না থাকলে আপনি এটি হারতে পারেন।</string>
168+
<string name="system_alert_window_warning">অ্যাপটি পেছনে চলাকালীন গুরুত্বপূর্ণ সিস্টেম পপ-আপ যেমন আনইনস্টল নিশ্চিতকরণ মিস না করতে “অন্যান্য অ্যাপের উপরে প্রদর্শন” অনুমতি দিন।</string>
169169
<string name="version_name_with_code">সংস্করণ {{version_name}} ({{version_code}})</string>
170170
<string name="optimized_batter_usage_warning">অপটিমাইজড ব্যাটারি ব্যবহার সক্রিয় আছে। অবিরত কাজের জন্য, এই অ্যাপ এর জন্য ব্যাটারি অপটিমাইজেশন অক্ষম করতে বিবেচনা করুন।</string>
171171
<string name="apps">অ্যাপস</string>

app/src/main/res/values-de/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
<string name="privacy_policy">Datenschutzrichtlinie</string>
166166
<string name="terms_of_use">Nutzungsbedingungen</string>
167167
<string name="grant_permission">Berechtigung erteilen</string>
168-
<string name="system_alert_window_warning">Die Gewährung der \'Über anderen Apps anzeigen\'-Berechtigung ist unerlässlich. Ohne diese Berechtigung könnten bei laufender App im Hintergrund wichtige Systemdialoge, wie etwa Deinstallationsbestätigungsdialoge, übersehen werden.</string>
168+
<string name="system_alert_window_warning">Bitte erlauben Sie „Über anderen Apps anzeigen“, damit Sie wichtige System-Popups wie Deinstallationsbestätigungen im Hintergrund nicht verpassen.</string>
169169
<string name="version_name_with_code">Version {{version_name}} ({{version_code}})</string>
170170
<string name="optimized_batter_usage_warning">Optimierte Batterienutzung ist derzeit aktiv. Um eine unterbrechungsfreie Leistung zu gewährleisten, erwägen Sie bitte, die Batterieoptimierung speziell für diese App zu deaktivieren.</string>
171171
<string name="apps">Apps</string>

app/src/main/res/values-es/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
<string name="privacy_policy">Política de privacidad</string>
166166
<string name="terms_of_use">Términos de uso</string>
167167
<string name="grant_permission">Conceder permiso</string>
168-
<string name="system_alert_window_warning">Conceder el permiso de \'Mostrar sobre otras aplicaciones\' es esencial. Sin este permiso, si la aplicación se está ejecutando en segundo plano, podrías perder diálogos cruciales del sistema provocados por la aplicación, como los diálogos de confirmación de desinstalación.</string>
168+
<string name="system_alert_window_warning">Permite “Mostrar sobre otras apps” para no perderte ventanas emergentes importantes del sistema como la confirmación de desinstalación cuando la app se ejecuta en segundo plano.</string>
169169
<string name="version_name_with_code">Versión {{version_name}} ({{version_code}})</string>
170170
<string name="optimized_batter_usage_warning">La optimización de la batería está actualmente activa. Para garantizar un rendimiento ininterrumpido, considere desactivar la optimización de la batería específicamente para esta aplicación.</string>
171171
<string name="apps">Aplicaciones</string>

app/src/main/res/values-fr/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
<string name="privacy_policy">Politique de confidentialité</string>
166166
<string name="terms_of_use">Conditions d\'utilisation</string>
167167
<string name="grant_permission">Accorder l\'autorisation</string>
168-
<string name="system_alert_window_warning">Accorder l\'autorisation \'Affichage par-dessus d\'autres applications\' est essentiel. Sans cette autorisation, si l\'application est en cours d\'exécution en arrière-plan, vous pourriez manquer des dialogues système cruciaux déclenchés par l\'application, tels que les dialogues de confirmation de désinstallation.</string>
168+
<string name="system_alert_window_warning">Veuillez autoriser “Afficher par-dessus les autres applications” pour ne pas manquer les pop-ups système importants comme la confirmation de désinstallation lorsque l\'application s\'exécute en arrière-plan.</string>
169169
<string name="version_name_with_code">Version {{version_name}} ({{version_code}})</string>
170170
<string name="optimized_batter_usage_warning">L\'optimisation de l\'utilisation de la batterie est actuellement active. Pour garantir des performances ininterrompues, veuillez envisager de désactiver l\'optimisation de la batterie spécifiquement pour cette application.</string>
171171
<string name="apps">Applications</string>

0 commit comments

Comments
 (0)