android: workaround of system restricted background (#2873)
* android: workaround of system restricted background * strings * exclude lockscreen call from requirements to unrestrict * texts * added button and changed behaviour * texts 2 * button instead of alert * padding * bigger padding * refactor * don't jump on button hide * no exceptions for lockscreen * sometimes do not show off alert --------- Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
38dc14f041
commit
9543af4784
@@ -12,7 +12,9 @@ import android.os.PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.*
|
||||
import androidx.compose.desktop.ui.tooling.preview.Preview
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
@@ -33,11 +35,10 @@ import androidx.webkit.WebViewAssetLoader
|
||||
import androidx.webkit.WebViewClientCompat
|
||||
import chat.simplex.common.model.*
|
||||
import chat.simplex.common.ui.theme.*
|
||||
import chat.simplex.common.views.helpers.ProfileImage
|
||||
import chat.simplex.common.views.helpers.withApi
|
||||
import chat.simplex.common.model.ChatModel
|
||||
import chat.simplex.common.model.Contact
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.res.MR
|
||||
import com.google.accompanist.permissions.rememberMultiplePermissionsState
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
@@ -267,7 +268,9 @@ private fun ActiveCallOverlayLayout(
|
||||
when (call.peerMedia ?: call.localMedia) {
|
||||
CallMediaType.Video -> {
|
||||
CallInfoView(call, alignment = Alignment.Start)
|
||||
Spacer(Modifier.fillMaxHeight().weight(1f))
|
||||
Box(Modifier.fillMaxWidth().fillMaxHeight().weight(1f), contentAlignment = Alignment.BottomCenter) {
|
||||
DisabledBackgroundCallsButton()
|
||||
}
|
||||
Row(Modifier.fillMaxWidth().padding(horizontal = 6.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
|
||||
ToggleAudioButton(call, toggleAudio)
|
||||
Spacer(Modifier.size(40.dp))
|
||||
@@ -293,7 +296,9 @@ private fun ActiveCallOverlayLayout(
|
||||
ProfileImage(size = 192.dp, image = call.contact.profile.image)
|
||||
CallInfoView(call, alignment = Alignment.CenterHorizontally)
|
||||
}
|
||||
Spacer(Modifier.fillMaxHeight().weight(1f))
|
||||
Box(Modifier.fillMaxWidth().fillMaxHeight().weight(1f), contentAlignment = Alignment.BottomCenter) {
|
||||
DisabledBackgroundCallsButton()
|
||||
}
|
||||
Box(Modifier.fillMaxWidth().padding(bottom = DEFAULT_BOTTOM_PADDING), contentAlignment = Alignment.CenterStart) {
|
||||
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
|
||||
IconButton(onClick = dismiss) {
|
||||
@@ -358,6 +363,31 @@ fun CallInfoView(call: Call, alignment: Alignment.Horizontal) {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DisabledBackgroundCallsButton() {
|
||||
var show by remember { mutableStateOf(!platform.androidIsBackgroundCallAllowed()) }
|
||||
if (show) {
|
||||
Row(
|
||||
Modifier
|
||||
.padding(bottom = 24.dp)
|
||||
.clickable {
|
||||
withBGApi {
|
||||
show = !platform.androidAskToAllowBackgroundCalls()
|
||||
}
|
||||
}
|
||||
.background(WarningOrange.copy(0.3f), RoundedCornerShape(50))
|
||||
.padding(start = 14.dp, top = 4.dp, end = 8.dp, bottom = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(stringResource(MR.strings.system_restricted_background_in_call_title), color = WarningOrange)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
IconButton(onClick = { show = false }, Modifier.size(24.dp)) {
|
||||
Icon(painterResource(MR.images.ic_close), null, tint = WarningOrange)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//@Composable
|
||||
//fun CallViewDebug(close: () -> Unit) {
|
||||
// val callCommand = remember { mutableStateOf<WCallCommand?>(null)}
|
||||
|
||||
@@ -9,6 +9,8 @@ interface PlatformInterface {
|
||||
fun androidChatStartedAfterBeingOff() {}
|
||||
fun androidChatStopped() {}
|
||||
fun androidChatInitializedAndStarted() {}
|
||||
fun androidIsBackgroundCallAllowed(): Boolean = true
|
||||
suspend fun androidAskToAllowBackgroundCalls(): Boolean = true
|
||||
}
|
||||
/**
|
||||
* Multiplatform project has separate directories per platform + common directory that contains directories per platform + common for all of them.
|
||||
|
||||
@@ -3,6 +3,7 @@ package chat.simplex.common.views.call
|
||||
import chat.simplex.common.model.ChatModel
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.views.helpers.withApi
|
||||
import chat.simplex.common.views.helpers.withBGApi
|
||||
import chat.simplex.common.views.usersettings.showInDevelopingAlert
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
@@ -28,6 +29,7 @@ class CallManager(val chatModel: ChatModel) {
|
||||
if (appPlatform.isDesktop) {
|
||||
return showInDevelopingAlert()
|
||||
}
|
||||
|
||||
val call = chatModel.activeCall.value
|
||||
if (call == null) {
|
||||
justAcceptIncomingCall(invitation = invitation)
|
||||
@@ -50,7 +52,7 @@ class CallManager(val chatModel: ChatModel) {
|
||||
contact = invitation.contact,
|
||||
callState = CallState.InvitationAccepted,
|
||||
localMedia = invitation.callType.media,
|
||||
sharedKey = invitation.sharedKey
|
||||
sharedKey = invitation.sharedKey,
|
||||
)
|
||||
showCallView.value = true
|
||||
val useRelay = controller.appPrefs.webrtcPolicyRelay.get()
|
||||
|
||||
@@ -239,11 +239,13 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: () -> Unit) {
|
||||
if (appPlatform.isDesktop) {
|
||||
return@out showInDevelopingAlert()
|
||||
}
|
||||
val cInfo = chat.chatInfo
|
||||
if (cInfo is ChatInfo.Direct) {
|
||||
chatModel.activeCall.value = Call(contact = cInfo.contact, callState = CallState.WaitCapabilities, localMedia = media)
|
||||
chatModel.showCallView.value = true
|
||||
chatModel.callCommand.value = WCallCommand.Capabilities
|
||||
withBGApi {
|
||||
val cInfo = chat.chatInfo
|
||||
if (cInfo is ChatInfo.Direct) {
|
||||
chatModel.activeCall.value = Call(contact = cInfo.contact, callState = CallState.WaitCapabilities, localMedia = media)
|
||||
chatModel.showCallView.value = true
|
||||
chatModel.callCommand.value = WCallCommand.Capabilities
|
||||
}
|
||||
}
|
||||
},
|
||||
acceptCall = { contact ->
|
||||
|
||||
@@ -43,6 +43,7 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit, drawerSt
|
||||
profile = user.profile,
|
||||
stopped,
|
||||
chatModel.chatDbEncrypted.value == true,
|
||||
remember { chatModel.controller.appPrefs.notificationsMode.state },
|
||||
user.displayName,
|
||||
setPerformLA = setPerformLA,
|
||||
showModal = { modalView -> { ModalManager.start.showModal { modalView(chatModel) } } },
|
||||
@@ -114,6 +115,7 @@ fun SettingsLayout(
|
||||
profile: LocalProfile,
|
||||
stopped: Boolean,
|
||||
encrypted: Boolean,
|
||||
notificationsMode: State<NotificationsMode>,
|
||||
userDisplayName: String,
|
||||
setPerformLA: (Boolean) -> Unit,
|
||||
showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
|
||||
@@ -155,7 +157,7 @@ fun SettingsLayout(
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_settings)) {
|
||||
SettingsActionItem(painterResource(MR.images.ic_bolt), stringResource(MR.strings.notifications), showSettingsModal { NotificationsSettingsView(it) }, disabled = stopped, extraPadding = true)
|
||||
SettingsActionItem(painterResource(if (notificationsMode.value == NotificationsMode.OFF) MR.images.ic_bolt_off else MR.images.ic_bolt), stringResource(MR.strings.notifications), showSettingsModal { NotificationsSettingsView(it) }, disabled = stopped, extraPadding = true)
|
||||
SettingsActionItem(painterResource(MR.images.ic_wifi_tethering), stringResource(MR.strings.network_and_servers), showSettingsModal { NetworkAndServersView(it, showModal, showSettingsModal, showCustomModal) }, disabled = stopped, extraPadding = true)
|
||||
SettingsActionItem(painterResource(MR.images.ic_videocam), stringResource(MR.strings.settings_audio_video_calls), showSettingsModal { CallSettingsView(it, showModal) }, disabled = stopped, extraPadding = true)
|
||||
SettingsActionItem(painterResource(MR.images.ic_lock), stringResource(MR.strings.privacy_and_security), showSettingsModal { PrivacySettingsView(it, showSettingsModal, setPerformLA) }, disabled = stopped, extraPadding = true)
|
||||
@@ -464,6 +466,7 @@ fun PreviewSettingsLayout() {
|
||||
profile = LocalProfile.sampleData,
|
||||
stopped = false,
|
||||
encrypted = false,
|
||||
notificationsMode = remember { mutableStateOf(NotificationsMode.OFF) },
|
||||
userDisplayName = "Alice",
|
||||
setPerformLA = { _ -> },
|
||||
showModal = { {} },
|
||||
|
||||
@@ -132,11 +132,19 @@
|
||||
<string name="service_notifications_disabled">Instant notifications are disabled!</string>
|
||||
<string name="to_preserve_privacy_simplex_has_background_service_instead_of_push_notifications_it_uses_a_few_pc_battery"><![CDATA[To preserve your privacy, instead of push notifications the app has a <b>SimpleX background service</b> – it uses a few percent of the battery per day.]]></string>
|
||||
<string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>It can be disabled via settings</b> – notifications will still be shown while the app is running.]]></string>
|
||||
<string name="turn_off_battery_optimization"><![CDATA[In order to use it, please <b>disable battery optimization</b> for SimpleX in the next dialog. Otherwise, the notifications will be disabled.]]></string>
|
||||
<string name="turn_off_battery_optimization"><![CDATA[To use it, please <b>allow SimpleX to run in background</b> in the next dialog. Otherwise, the notifications will be disabled.]]></string>
|
||||
<string name="turning_off_service_and_periodic">Battery optimization is active, turning off background service and periodic requests for new messages. You can re-enable them via settings.</string>
|
||||
<string name="periodic_notifications">Periodic notifications</string>
|
||||
<string name="periodic_notifications_disabled">Periodic notifications are disabled!</string>
|
||||
<string name="periodic_notifications_desc">The app fetches new messages periodically — it uses a few percent of the battery per day. The app doesn\'t use push notifications — data from your device is not sent to the servers.</string>
|
||||
<string name="turn_off_battery_optimization_button">Allow</string>
|
||||
<string name="turn_off_system_restriction_button">Open app settings</string>
|
||||
<string name="disable_notifications_button">Disable notifications</string>
|
||||
<string name="system_restricted_background_desc"><![CDATA[SimpleX can\'t run in background. You will receive the notifications only when the app is running.]]></string>
|
||||
<string name="system_restricted_background_warn"><![CDATA[To enable notifications, please choose <b>App battery usage</b> / <b>Unrestricted</b> in the app settings.]]></string>
|
||||
<string name="system_restricted_background_in_call_title">No background calls</string>
|
||||
<string name="system_restricted_background_in_call_desc"><![CDATA[The app may be closed after 1 minute in background.]]></string>
|
||||
<string name="system_restricted_background_in_call_warn"><![CDATA[To make calls in background, please choose <b>App battery usage</b> / <b>Unrestricted</b> in the app settings]]>.</string>
|
||||
<string name="enter_passphrase_notification_title">Passphrase is needed</string>
|
||||
<string name="enter_passphrase_notification_desc">To receive notifications, please, enter the database passphrase</string>
|
||||
<string name="database_initialization_error_title">Can\'t initialize the database</string>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="24"
|
||||
viewBox="0 -960 960 960"
|
||||
width="24"
|
||||
version="1.1"
|
||||
id="svg864"
|
||||
sodipodi:docname="ic_bolt_off.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs868">
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath1042">
|
||||
<g
|
||||
id="g1046">
|
||||
<g
|
||||
inkscape:label="Clip"
|
||||
id="use1044"
|
||||
clip-path="url(#clipPath1042)">
|
||||
<g
|
||||
id="g1054" />
|
||||
</g>
|
||||
</g>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="namedview866"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
showgrid="false"
|
||||
inkscape:zoom="5.0911688"
|
||||
inkscape:cx="-25.239784"
|
||||
inkscape:cy="-0.49104638"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="856"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg864" />
|
||||
<path
|
||||
id="path1067"
|
||||
d="M 367.38281 -591.32812 L 326.67969 -632.65625 L 279.53125 -564.57031 L 166.67969 -401.5625 C 159.67969 -391.89551 158.77538 -382.00292 163.98438 -371.83594 C 169.19336 -361.66896 177.59871 -356.5625 189.17969 -356.5625 L 333.67188 -356.5625 L 314.6875 -222.8125 L 295.70312 -89.0625 C 294.37014 -80.895816 295.62013 -73.294223 299.45312 -66.210938 C 303.28612 -59.127653 308.83888 -53.987005 316.17188 -50.820312 C 323.50486 -47.320319 331.02496 -46.494079 338.71094 -48.359375 C 346.39692 -50.224071 353.04388 -54.490464 358.67188 -61.09375 L 482.53906 -209.72656 L 601.99219 -353.125 L 561.75781 -393.98438 L 552.69531 -383.08594 L 458.20312 -269.57031 L 363.67188 -156.09375 L 381.67969 -285.07812 L 399.6875 -414.0625 L 244.6875 -414.0625 L 330.50781 -538.08594 L 367.38281 -591.32812 z " />
|
||||
<path
|
||||
id="path1128"
|
||||
d="M 523.94531 -904.84375 C 516.11233 -902.34376 509.86231 -897.58593 505.19531 -890.58594 L 392.34375 -727.57812 L 371.91406 -698.04688 L 413.04688 -657.26562 L 416.36719 -662.07031 L 502.1875 -786.09375 L 483.94531 -641.32812 L 477.85156 -593.00781 L 575.15625 -496.5625 L 647.1875 -496.5625 L 614.60938 -457.46094 L 655.27344 -417.10938 L 730.19531 -507.07031 C 737.86229 -516.73729 739.14756 -526.97952 734.10156 -537.8125 C 729.05558 -548.64547 720.4441 -554.0625 708.20312 -554.0625 L 530.70312 -554.0625 L 550.42969 -709.84375 L 570.19531 -865.58594 C 571.19531 -873.35892 569.42186 -880.88407 564.92188 -888.16406 C 560.42188 -895.44405 554.52048 -900.7295 547.1875 -904.0625 C 539.52052 -907.06249 531.77829 -907.34375 523.94531 -904.84375 z " />
|
||||
<path
|
||||
d="m 98.757614,-815.50208 c -6,-5.6667 -9,-12.4944 -9,-20.483 0,-7.9894 3,-14.995 9,-21.017 5.666666,-5.6667 12.499996,-8.5 20.499996,-8.5 8,0 14.87033,2.8703 20.611,8.611 l 703.77795,703.77797 c 5.7407,5.74067 8.611,12.52767 8.611,20.361 0,7.83333 -2.8333,14.58333 -8.5,20.25 -5.6666,6 -12.58329,8.91667 -20.74999,8.75 -8.1666,-0.16666 -15.0646,-3.06466 -20.694,-8.694 C 515.62153,-363.72015 368.7575,-545.07432 98.757614,-815.50208 Z"
|
||||
id="path114"
|
||||
sodipodi:nodetypes="cscsssscscc" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
Reference in New Issue
Block a user