Skip to content

Commit 6b4e12e

Browse files
committed
Enhance peer chat
1 parent 8868d94 commit 6b4e12e

File tree

105 files changed

+230
-127
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+230
-127
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Access a self-hosted webpage on the same network to manage your phone:
2525
- Files: Internal storage, SD card, USB, images, videos, audio
2626
- Contacts, SMS, and call logs
2727
- Installed apps (with APK export)
28-
- Notifications and device info
28+
- Notifications mirroring and device info
2929
- Screen mirroring
3030
- PWA support — add the web app to your desktop/home screen
3131

@@ -35,6 +35,7 @@ Access a self-hosted webpage on the same network to manage your phone:
3535
- Video and audio player (in-app and on the web)
3636
- TV casting for media
3737
- Pomodoro timer
38+
- Sound meter
3839
- Peer-to-peer chat and file sharing
3940

4041
**Always Improving**

app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ android {
4141
else -> 0
4242
}
4343

44-
val vCode = 382
44+
val vCode = 385
4545
versionCode = vCode - singleAbiNum
46-
versionName = "2.1.0"
46+
versionName = "2.1.1"
4747

4848
ndk {
4949
//noinspection ChromeOsAbiSupport

app/src/main/java/com/ismartcoding/plain/events/WebSocketEvents.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ enum class EventType(val value: Int) {
4646
NOTIFICATION_REFRESHED(10),
4747
POMODORO_ACTION(11),
4848
POMODORO_SETTINGS_UPDATE(12),
49+
CHAT_SETTINGS_UPDATE(13),
4950
}
5051

5152

app/src/main/java/com/ismartcoding/plain/features/Permissions.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ enum class Permission {
5555
READ_PHONE_STATE,
5656
READ_PHONE_NUMBERS,
5757
SCHEDULE_EXACT_ALARM,
58+
QUERY_ALL_PACKAGES,
5859
NONE
5960
;
6061

@@ -75,6 +76,10 @@ enum class Permission {
7576
return "android.permission.${this.name}"
7677
}
7778

79+
suspend fun enabledAndCanAsync(context: Context): Boolean {
80+
return can(context) && isEnabledAsync(context)
81+
}
82+
7883
fun can(context: Context): Boolean {
7984
return when {
8085
this == WRITE_EXTERNAL_STORAGE -> {
@@ -85,6 +90,10 @@ enum class Permission {
8590
Settings.System.canWrite(context)
8691
}
8792

93+
this == QUERY_ALL_PACKAGES -> {
94+
true
95+
}
96+
8897
this == POST_NOTIFICATIONS -> {
8998
if (isTPlus()) {
9099
context.hasPermission(this.toSysPermission())
@@ -302,6 +311,11 @@ object Permissions {
302311
list.add(
303312
PermissionItem.create(context, R.drawable.file_digit, Permission.READ_PHONE_NUMBERS, setOf(Permission.READ_PHONE_STATE, Permission.READ_PHONE_NUMBERS))
304313
)
314+
if (AppFeatureType.APPS.has()) {
315+
list.add(
316+
PermissionItem.create(context, R.drawable.package2, Permission.QUERY_ALL_PACKAGES)
317+
)
318+
}
305319
return list
306320
}
307321

app/src/main/java/com/ismartcoding/plain/ui/page/chat/ChatSettingsPage.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ import androidx.navigation.NavHostController
2222
import com.ismartcoding.lib.channel.Channel
2323
import com.ismartcoding.lib.channel.sendEvent
2424
import com.ismartcoding.lib.helpers.CoroutinesHelper.withIO
25+
import com.ismartcoding.lib.helpers.JsonHelper
2526
import com.ismartcoding.plain.R
2627
import com.ismartcoding.plain.enums.PickFileTag
2728
import com.ismartcoding.plain.enums.PickFileType
29+
import com.ismartcoding.plain.events.EventType
2830
import com.ismartcoding.plain.events.PickFileEvent
2931
import com.ismartcoding.plain.events.PickFileResultEvent
32+
import com.ismartcoding.plain.events.WebSocketEvent
3033
import com.ismartcoding.plain.preferences.ChatFilesSaveFolderPreference
3134
import com.ismartcoding.plain.ui.base.BottomSpace
3235
import com.ismartcoding.plain.ui.base.PCard
@@ -108,6 +111,7 @@ fun ChatSettingsPage(navController: NavHostController) {
108111
ChatFilesSaveFolderPreference.putAsync(context, actualPath)
109112
chatFilesSaveFolder = actualPath
110113
}
114+
sendEvent(WebSocketEvent(EventType.CHAT_SETTINGS_UPDATE, ""))
111115
}
112116
}
113117
} catch (ex: Exception) {

app/src/main/java/com/ismartcoding/plain/ui/page/root/RootPage.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ fun RootPage(
285285
RootTabType.CHAT.value -> {
286286
TabContentChat(
287287
navController = navController,
288+
mainVM = mainVM,
288289
chatListVM = chatListVM,
289290
paddingValues = paddingValues,
290291
pagerState = pagerState,

app/src/main/java/com/ismartcoding/plain/ui/page/root/contents/TabContentChat.kt

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,17 @@ import com.ismartcoding.lib.logcat.LogCat
3030
import com.ismartcoding.plain.R
3131
import com.ismartcoding.plain.enums.DeviceType
3232
import com.ismartcoding.plain.features.nearby.NearbyDiscoverManager
33+
import com.ismartcoding.plain.preferences.LocalWeb
3334
import com.ismartcoding.plain.preferences.NearbyDiscoverablePreference
3435
import com.ismartcoding.plain.preferences.dataFlow
3536
import com.ismartcoding.plain.preferences.dataStore
37+
import com.ismartcoding.plain.ui.base.AlertType
3638
import com.ismartcoding.plain.ui.base.BottomSpace
39+
import com.ismartcoding.plain.ui.base.PAlert
3740
import com.ismartcoding.plain.ui.base.PCard
3841
import com.ismartcoding.plain.ui.base.PListItem
42+
import com.ismartcoding.plain.ui.base.PMiniOutlineButton
43+
import com.ismartcoding.plain.ui.base.PSwitch
3944
import com.ismartcoding.plain.ui.base.Subtitle
4045
import com.ismartcoding.plain.ui.base.TopSpace
4146
import com.ismartcoding.plain.ui.base.VerticalSpace
@@ -44,6 +49,7 @@ import com.ismartcoding.plain.ui.base.pullrefresh.RefreshContentState
4449
import com.ismartcoding.plain.ui.base.pullrefresh.rememberRefreshLayoutState
4550
import com.ismartcoding.plain.ui.extensions.collectAsStateValue
4651
import com.ismartcoding.plain.ui.models.ChatListViewModel
52+
import com.ismartcoding.plain.ui.models.MainViewModel
4753
import com.ismartcoding.plain.ui.nav.Routing
4854
import com.ismartcoding.plain.ui.page.root.components.PeerListItem
4955
import com.ismartcoding.plain.ui.page.root.components.RootTabType
@@ -58,6 +64,7 @@ import kotlinx.coroutines.launch
5864
@Composable
5965
fun TabContentChat(
6066
navController: NavHostController,
67+
mainVM: MainViewModel,
6168
chatListVM: ChatListViewModel,
6269
paddingValues: PaddingValues,
6370
pagerState: PagerState
@@ -66,6 +73,7 @@ fun TabContentChat(
6673
val lifecycleOwner = androidx.lifecycle.compose.LocalLifecycleOwner.current
6774
val pairedPeers = chatListVM.pairedPeers
6875
val unpairedPeers = chatListVM.unpairedPeers
76+
val webEnabled = LocalWeb.current
6977

7078
val scope = rememberCoroutineScope()
7179

@@ -176,19 +184,37 @@ fun TabContentChat(
176184
TopSpace()
177185
}
178186

187+
// Web service alert - similar to TabContentHome
188+
item {
189+
if (!webEnabled) {
190+
PAlert(
191+
title = stringResource(id = R.string.attention),
192+
description = stringResource(id = R.string.web_service_required_for_chat),
193+
AlertType.WARNING
194+
) {
195+
PMiniOutlineButton(
196+
label = stringResource(R.string.enable_web_service),
197+
click = {
198+
mainVM.enableHttpServer(context, true)
199+
}
200+
)
201+
}
202+
}
203+
}
204+
179205
item {
180206
PCard {
181207
PListItem(
182208
title = stringResource(R.string.make_discoverable),
183209
subtitle = stringResource(R.string.make_discoverable_desc),
184210
icon = R.drawable.wifi,
185211
action = {
186-
Switch(
187-
checked = isDiscoverable,
188-
onCheckedChange = { enabled ->
189-
chatListVM.updateDiscoverable(context, enabled)
190-
}
212+
PSwitch(
213+
activated = isDiscoverable
191214
)
215+
{ enabled ->
216+
chatListVM.updateDiscoverable(context, enabled)
217+
}
192218
}
193219
)
194220
}

app/src/main/java/com/ismartcoding/plain/ui/page/root/contents/TabContentHome.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ fun TabContentHome(
7373
mainVM.isNetworkConnected = NetworkHelper.isNetworkConnected(context)
7474
mainVM.ip4s = NetworkHelper.getDeviceIP4s().filter { it.isNotEmpty() }
7575
mainVM.ip4 = NetworkHelper.getDeviceIP4().ifEmpty { "127.0.0.1" }
76+
systemAlertWindow = Permission.SYSTEM_ALERT_WINDOW.can(context)
7677
}
7778
}
7879
}

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

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@ import com.ismartcoding.lib.extensions.isAudioFast
2020
import com.ismartcoding.lib.extensions.isImageFast
2121
import com.ismartcoding.lib.extensions.isVideoFast
2222
import com.ismartcoding.lib.extensions.scanFileByConnection
23-
import com.ismartcoding.lib.extensions.toAppUrl
2423
import com.ismartcoding.lib.helpers.CoroutinesHelper.coIO
2524
import com.ismartcoding.lib.helpers.CoroutinesHelper.coMain
2625
import com.ismartcoding.lib.helpers.CoroutinesHelper.withIO
2726
import com.ismartcoding.lib.helpers.CryptoHelper
2827
import com.ismartcoding.lib.helpers.JsonHelper.jsonEncode
29-
import com.ismartcoding.plain.helpers.PhoneHelper
3028
import com.ismartcoding.lib.isQPlus
3129
import com.ismartcoding.lib.isRPlus
3230
import com.ismartcoding.lib.logcat.LogCat
@@ -39,9 +37,6 @@ import com.ismartcoding.plain.data.DScreenMirrorQuality
3937
import com.ismartcoding.plain.data.TagRelationStub
4038
import com.ismartcoding.plain.db.AppDatabase
4139
import com.ismartcoding.plain.db.DChat
42-
import com.ismartcoding.plain.db.DMessageFile
43-
import com.ismartcoding.plain.db.DMessageFiles
44-
import com.ismartcoding.plain.db.DMessageImages
4540
import com.ismartcoding.plain.db.DMessageType
4641
import com.ismartcoding.plain.enums.AppFeatureType
4742
import com.ismartcoding.plain.enums.DataType
@@ -82,6 +77,7 @@ import com.ismartcoding.plain.helpers.AppHelper
8277
import com.ismartcoding.plain.helpers.DeviceInfoHelper
8378
import com.ismartcoding.plain.helpers.FileHelper
8479
import com.ismartcoding.plain.helpers.NotificationsHelper
80+
import com.ismartcoding.plain.helpers.PhoneHelper
8581
import com.ismartcoding.plain.helpers.QueryHelper
8682
import com.ismartcoding.plain.helpers.TempHelper
8783
import com.ismartcoding.plain.packageManager
@@ -198,7 +194,7 @@ class MainGraphQL(val schema: Schema) {
198194
}
199195
query("messageCount") {
200196
resolver { query: String ->
201-
if (Permission.READ_SMS.can(MainApp.instance)) {
197+
if (Permission.READ_SMS.enabledAndCanAsync(MainApp.instance)) {
202198
SmsMediaStoreHelper.countAsync(MainApp.instance, query)
203199
} else {
204200
0
@@ -228,7 +224,7 @@ class MainGraphQL(val schema: Schema) {
228224
query("imageCount") {
229225
resolver { query: String ->
230226
val context = MainApp.instance
231-
if (Permission.WRITE_EXTERNAL_STORAGE.can(context)) {
227+
if (Permission.WRITE_EXTERNAL_STORAGE.enabledAndCanAsync(context)) {
232228
ImageMediaStoreHelper.countAsync(context, query)
233229
} else {
234230
0
@@ -238,7 +234,7 @@ class MainGraphQL(val schema: Schema) {
238234
query("mediaBuckets") {
239235
resolver { type: DataType ->
240236
val context = MainApp.instance
241-
if (Permission.WRITE_EXTERNAL_STORAGE.can(context)) {
237+
if (Permission.WRITE_EXTERNAL_STORAGE.enabledAndCanAsync(context)) {
242238
if (type == DataType.IMAGE) {
243239
ImageMediaStoreHelper.getBucketsAsync(context).map { it.toModel() }
244240
} else if (type == DataType.AUDIO) {
@@ -279,7 +275,7 @@ class MainGraphQL(val schema: Schema) {
279275
}
280276
query("videoCount") {
281277
resolver { query: String ->
282-
if (Permission.WRITE_EXTERNAL_STORAGE.can(MainApp.instance)) {
278+
if (Permission.WRITE_EXTERNAL_STORAGE.enabledAndCanAsync(MainApp.instance)) {
283279
VideoMediaStoreHelper.countAsync(MainApp.instance, query)
284280
} else {
285281
0
@@ -308,7 +304,7 @@ class MainGraphQL(val schema: Schema) {
308304
}
309305
query("audioCount") {
310306
resolver { query: String ->
311-
if (Permission.WRITE_EXTERNAL_STORAGE.can(MainApp.instance)) {
307+
if (Permission.WRITE_EXTERNAL_STORAGE.enabledAndCanAsync(MainApp.instance)) {
312308
AudioMediaStoreHelper.countAsync(MainApp.instance, query)
313309
} else {
314310
0
@@ -341,7 +337,7 @@ class MainGraphQL(val schema: Schema) {
341337
query("contactCount") {
342338
resolver { query: String ->
343339
val context = MainApp.instance
344-
if (Permission.READ_CONTACTS.can(context)) {
340+
if (Permission.READ_CONTACTS.enabledAndCanAsync(context)) {
345341
ContactMediaStoreHelper.countAsync(context, query)
346342
} else {
347343
0
@@ -385,7 +381,7 @@ class MainGraphQL(val schema: Schema) {
385381
query("callCount") {
386382
resolver { query: String ->
387383
val context = MainApp.instance
388-
if (Permission.READ_CALL_LOG.can(context)) {
384+
if (Permission.READ_CALL_LOG.enabledAndCanAsync(context)) {
389385
CallMediaStoreHelper.countAsync(context, query)
390386
} else {
391387
0
@@ -399,11 +395,13 @@ class MainGraphQL(val schema: Schema) {
399395
}
400396
query("packages") {
401397
resolver { offset: Int, limit: Int, query: String, sortBy: FileSortBy ->
398+
Permissions.checkAsync(MainApp.instance, setOf(Permission.QUERY_ALL_PACKAGES))
402399
PackageHelper.searchAsync(query, limit, offset, sortBy).map { it.toModel() }
403400
}
404401
}
405402
query("packageStatuses") {
406403
resolver { ids: List<ID> ->
404+
Permissions.checkAsync(MainApp.instance, setOf(Permission.QUERY_ALL_PACKAGES))
407405
PackageHelper.getPackageInfoMap(ids.map { it.value }).map {
408406
val pkg = it.value
409407
val updatedAt = if (pkg != null) Instant.fromEpochMilliseconds(pkg.lastUpdateTime) else null
@@ -413,7 +411,11 @@ class MainGraphQL(val schema: Schema) {
413411
}
414412
query("packageCount") {
415413
resolver { query: String ->
416-
PackageHelper.count(query)
414+
if (Permission.QUERY_ALL_PACKAGES.enabledAndCanAsync(MainApp.instance)) {
415+
PackageHelper.count(query)
416+
} else {
417+
0
418+
}
417419
}
418420
}
419421
query("storageStats") {
@@ -673,6 +675,7 @@ class MainGraphQL(val schema: Schema) {
673675
}
674676
mutation("uninstallPackages") {
675677
resolver { ids: List<ID> ->
678+
Permissions.checkAsync(MainApp.instance, setOf(Permission.QUERY_ALL_PACKAGES))
676679
ids.forEach {
677680
PackageHelper.uninstall(MainActivity.instance.get()!!, it.value)
678681
}
@@ -681,6 +684,7 @@ class MainGraphQL(val schema: Schema) {
681684
}
682685
mutation("installPackage") {
683686
resolver { path: String ->
687+
Permissions.checkAsync(MainApp.instance, setOf(Permission.QUERY_ALL_PACKAGES))
684688
val file = File(path)
685689
if (!file.exists()) {
686690
throw GraphQLError("File does not exist")

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@
263263
<string name="about_desc">ক্লায়েন্টের নাম, সংস্করণ, লগ, অনুদান</string>
264264
<string name="require_confirmation">নিশ্চিত প্রয়োজন</string>
265265
<string name="web_console">ওয়েব কনসোল পিসি উপর</string>
266+
<string name="web_service_required_for_chat">অন্যদের থেকে বার্তা পেতে, অনুগ্রহ করে পিসিতে ওয়েব পরিষেবা সক্রিয় করুন।</string>
267+
<string name="enable_web_service">ওয়েব পরিষেবা সক্রিয় করুন</string>
266268
<string name="backup_restore">ব্যাকআপ এবং পুনরুদ্ধার</string>
267269
<string name="backup">ব্যাকআপ</string>
268270
<string name="backup_desc">প্লেনঅ্যাপ ডেটা ব্যাকআপ বা পুনরুদ্ধার করুন</string>
@@ -411,6 +413,7 @@
411413
<string name="feature_WRITE_CONTACTS">যোগাযোগ পরিচালনা</string>
412414
<string name="feature_NOTIFICATION_LISTENER">বিজ্ঞপ্তি পরিচালক</string>
413415
<string name="feature_READ_PHONE_NUMBERS">ফোন নম্বর পড়ুন</string>
416+
<string name="feature_QUERY_ALL_PACKAGES">অ্যাপ্স পরিচালনা করুন</string>
414417
<string name="notification_filter_settings">বিজ্ঞপ্তি ফিল্টার সেটিংস</string>
415418
<string name="notification_filter_settings_desc">কিভাবে পিসি এ বিজ্ঞপ্তি প্রেরণ করবে তা নির্বাচন করুন</string>
416419
<string name="filter_mode">ফিল্টার মোড</string>

0 commit comments

Comments
 (0)