mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-14 18:26:11 -04:00
Add popup via system alert window.
This commit is contained in:
@@ -28,6 +28,8 @@
|
||||
android:usesPermissionFlags="neverForLocation" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth_le"
|
||||
android:required="true" />
|
||||
|
||||
@@ -62,6 +62,15 @@ enum class Permission(
|
||||
val pwm = it.getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
pwm.isIgnoringBatteryOptimizations(BuildConfigWrap.APPLICATION_ID)
|
||||
},
|
||||
),
|
||||
SYSTEM_ALERT_WINDOW(
|
||||
minApiLevel = Build.VERSION_CODES.BASE,
|
||||
labelRes = R.string.permission_system_alert_window_label,
|
||||
descriptionRes = R.string.permission_system_alert_window_description,
|
||||
permissionId = "android.permission.SYSTEM_ALERT_WINDOW",
|
||||
isGranted = {
|
||||
android.provider.Settings.canDrawOverlays(it)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.permissions.Permission
|
||||
import eu.darken.capod.common.permissions.isRequired
|
||||
import eu.darken.capod.reaction.settings.ReactionSettings
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
@@ -18,6 +19,7 @@ import javax.inject.Singleton
|
||||
class PermissionTool @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val generalSettings: GeneralSettings,
|
||||
private val reactionSettings: ReactionSettings,
|
||||
) {
|
||||
private val permissionCheckTrigger = MutableStateFlow(UUID.randomUUID())
|
||||
|
||||
@@ -29,10 +31,12 @@ class PermissionTool @Inject constructor(
|
||||
val missingPermissions: Flow<Set<Permission>> = combine(
|
||||
permissionCheckTrigger,
|
||||
generalSettings.monitorMode.flow,
|
||||
) { _, monitorMode ->
|
||||
reactionSettings.showPopUpOnCaseOpen.flow
|
||||
) { _, monitorMode, showPopUp ->
|
||||
Permission.values()
|
||||
.filter { it != Permission.IGNORE_BATTERY_OPTIMIZATION || monitorMode == MonitorMode.ALWAYS }
|
||||
.filter { it != Permission.ACCESS_BACKGROUND_LOCATION || monitorMode == MonitorMode.ALWAYS }
|
||||
.filter { it != Permission.SYSTEM_ALERT_WINDOW || showPopUp }
|
||||
.filter { it.isRequired(context) }
|
||||
.toSet()
|
||||
}
|
||||
|
||||
@@ -33,11 +33,11 @@ class OverviewFragment : Fragment3(R.layout.main_fragment) {
|
||||
lateinit var adapter: OverviewAdapter
|
||||
|
||||
lateinit var permissionLauncher: ActivityResultLauncher<String>
|
||||
var awaitingIgnoreBatteryOptimization = false
|
||||
var awaitingPermission = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
awaitingIgnoreBatteryOptimization = savedInstanceState?.getBoolean("awaitingIgnoreBatteryOptimization") ?: false
|
||||
awaitingPermission = savedInstanceState?.getBoolean("awaitingPermission") ?: false
|
||||
|
||||
permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
|
||||
log { "Request for $id was granted=$granted" }
|
||||
@@ -77,16 +77,28 @@ class OverviewFragment : Fragment3(R.layout.main_fragment) {
|
||||
}
|
||||
|
||||
vm.requestPermissionEvent.observe2(ui) {
|
||||
if (it == Permission.IGNORE_BATTERY_OPTIMIZATION) {
|
||||
awaitingIgnoreBatteryOptimization = true
|
||||
startActivity(
|
||||
Intent(
|
||||
Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
|
||||
Uri.parse("package:${requireContext().packageName}")
|
||||
when (it) {
|
||||
Permission.IGNORE_BATTERY_OPTIMIZATION -> {
|
||||
awaitingPermission = true
|
||||
startActivity(
|
||||
Intent(
|
||||
Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
|
||||
Uri.parse("package:${requireContext().packageName}")
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
permissionLauncher.launch(it.permissionId)
|
||||
}
|
||||
Permission.SYSTEM_ALERT_WINDOW -> {
|
||||
awaitingPermission = true
|
||||
startActivity(
|
||||
Intent(
|
||||
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
||||
Uri.parse("package:${requireContext().packageName}")
|
||||
)
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
permissionLauncher.launch(it.permissionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,15 +147,15 @@ class OverviewFragment : Fragment3(R.layout.main_fragment) {
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putBoolean("awaitingIgnoreBatteryOptimization", awaitingIgnoreBatteryOptimization)
|
||||
outState.putBoolean("awaitingPermission", awaitingPermission)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (awaitingIgnoreBatteryOptimization) {
|
||||
awaitingIgnoreBatteryOptimization = false
|
||||
log { "awaitingIgnoreBatteryOptimization=true" }
|
||||
if (awaitingPermission) {
|
||||
awaitingPermission = false
|
||||
log { "awaitingPermission=true" }
|
||||
vm.onPermissionResult(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,8 @@ interface DualApplePods : ApplePods, HasDualPods, HasDualEarDetection, HasCase {
|
||||
|
||||
val caseLidState: LidState
|
||||
get() {
|
||||
return LidState.values().firstOrNull { it.rawRange.contains(rawCaseLidState.toInt()) } ?: LidState.UNKNOWN
|
||||
val rawstate = rawCaseLidState
|
||||
return LidState.values().firstOrNull { it.rawRange.contains(rawstate.toInt()) } ?: LidState.UNKNOWN
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.darken.capod.reaction.popup
|
||||
|
||||
import eu.darken.capod.common.coroutine.DispatcherProvider
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.INFO
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
@@ -9,9 +10,10 @@ import eu.darken.capod.common.flow.withPrevious
|
||||
import eu.darken.capod.monitor.core.PodMonitor
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.reaction.popup.ui.PopUpNotification
|
||||
import eu.darken.capod.reaction.popup.ui.PopUpWindow
|
||||
import eu.darken.capod.reaction.settings.ReactionSettings
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -19,7 +21,8 @@ import javax.inject.Singleton
|
||||
class PopUpReaction @Inject constructor(
|
||||
private val podMonitor: PodMonitor,
|
||||
private val reactionSettings: ReactionSettings,
|
||||
private val popUpNotification: PopUpNotification,
|
||||
private val popupWindow: PopUpWindow,
|
||||
private val dispatcherProvider: DispatcherProvider,
|
||||
) {
|
||||
|
||||
fun monitor(): Flow<Unit> = reactionSettings.showPopUpOnCaseOpen.flow
|
||||
@@ -51,10 +54,14 @@ class PopUpReaction @Inject constructor(
|
||||
|
||||
if (current.caseLidState == DualApplePods.LidState.OPEN && current.model != PodDevice.Model.UNKNOWN) {
|
||||
log(TAG, INFO) { "Show popup" }
|
||||
popUpNotification.showNotification(current)
|
||||
withContext(dispatcherProvider.Main) {
|
||||
popupWindow.show(current)
|
||||
}
|
||||
} else if (current.caseLidState != DualApplePods.LidState.OPEN) {
|
||||
log(TAG, INFO) { "Hide popup" }
|
||||
popUpNotification.hideNotification()
|
||||
withContext(dispatcherProvider.Main) {
|
||||
popupWindow.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package eu.darken.capod.reaction.popup.ui
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.app.NotificationCompat
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.BuildConfigWrap
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.common.notifications.PendingIntentCompat
|
||||
import eu.darken.capod.main.ui.MainActivity
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class PopUpNotification @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val notificationManager: NotificationManager,
|
||||
private val notificationViewFactory: PopUpNotificationViewFactory
|
||||
) {
|
||||
|
||||
private val builder: NotificationCompat.Builder
|
||||
|
||||
init {
|
||||
NotificationChannel(
|
||||
NOTIFICATION_CHANNEL_ID,
|
||||
context.getString(R.string.notification_channel_reaction_popup_label),
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
).run {
|
||||
vibrationPattern = LongArray(1) { 0 }
|
||||
enableVibration(true)
|
||||
enableLights(false)
|
||||
setSound(null, null)
|
||||
notificationManager.createNotificationChannel(this)
|
||||
}
|
||||
|
||||
val openIntent = Intent(context, MainActivity::class.java)
|
||||
val openPi = PendingIntent.getActivity(
|
||||
context,
|
||||
0,
|
||||
openIntent,
|
||||
PendingIntentCompat.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID).apply {
|
||||
setChannelId(NOTIFICATION_CHANNEL_ID)
|
||||
setContentIntent(openPi)
|
||||
priority = NotificationCompat.PRIORITY_LOW
|
||||
setSmallIcon(R.drawable.ic_device_generic_earbuds)
|
||||
setContentTitle(context.getString(R.string.app_name))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBuilder(device: PodDevice): NotificationCompat.Builder = builder.apply {
|
||||
setStyle(NotificationCompat.DecoratedCustomViewStyle())
|
||||
setCustomContentView(notificationViewFactory.createContentView(device))
|
||||
setSmallIcon(device.iconRes)
|
||||
setSubText(null)
|
||||
}
|
||||
|
||||
fun showNotification(device: PodDevice) {
|
||||
val notification = getBuilder(device).build()
|
||||
log(TAG) { "showNotification(): $device" }
|
||||
notificationManager.notify(NOTIFICATION_ID, notification)
|
||||
}
|
||||
|
||||
fun hideNotification() {
|
||||
log(TAG) { "hideNotification()" }
|
||||
notificationManager.cancel(NOTIFICATION_ID)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAG = logTag("Reaction", "PopUp", "Notifications")
|
||||
private val NOTIFICATION_CHANNEL_ID =
|
||||
"${BuildConfigWrap.APPLICATION_ID}.notification.channel.reaction.popup"
|
||||
internal const val NOTIFICATION_ID = 9000
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package eu.darken.capod.reaction.popup.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.RemoteViews
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.pods.core.*
|
||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class PopUpNotificationViewFactory @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
) {
|
||||
|
||||
fun createContentView(device: PodDevice): RemoteViews = when (device) {
|
||||
is DualApplePods -> createDualApplePods(device)
|
||||
is SingleApplePods -> createSingleApplePods(device)
|
||||
is BasicSingleApplePods -> createSingleBasicApplePods(device)
|
||||
else -> throw IllegalArgumentException("Unexpected device: $device")
|
||||
}
|
||||
|
||||
private fun createDualApplePods(device: DualApplePods): RemoteViews = RemoteViews(
|
||||
context.packageName,
|
||||
R.layout.popup_notification_dual_pods
|
||||
).apply {
|
||||
setTextViewText(R.id.pod_label, device.getLabel(context))
|
||||
|
||||
device.getBatteryLevelLeftPod(context)
|
||||
.let { if (device.isLeftPodCharging) "$it⚡" else it }
|
||||
.run { setTextViewText(R.id.pod_left, this) }
|
||||
|
||||
device.getBatteryLevelCase(context)
|
||||
.let { if (device.isCaseCharging) "$it⚡" else it }
|
||||
.run { setTextViewText(R.id.pod_case, this) }
|
||||
|
||||
device.getBatteryLevelRightPod(context)
|
||||
.let { if (device.isRightPodCharging) "$it⚡" else it }
|
||||
.run { setTextViewText(R.id.pod_right, this) }
|
||||
}
|
||||
|
||||
private fun createSingleApplePods(device: SingleApplePods): RemoteViews = RemoteViews(
|
||||
context.packageName,
|
||||
R.layout.popup_notification_single_pods
|
||||
).apply {
|
||||
setTextViewText(R.id.headphones_label, device.getLabel(context))
|
||||
|
||||
device.getBatteryLevelHeadset(context)
|
||||
.let { if (!device.isHeadsetBeingCharged) "$it⚡" else it }
|
||||
.run { setTextViewText(R.id.headphones, this) }
|
||||
}
|
||||
|
||||
private fun createSingleBasicApplePods(device: BasicSingleApplePods): RemoteViews = RemoteViews(
|
||||
context.packageName,
|
||||
R.layout.popup_notification_single_pods_basic
|
||||
).apply {
|
||||
setTextViewText(R.id.headphones_label, device.getLabel(context))
|
||||
|
||||
device.getBatteryLevelHeadset(context)
|
||||
.run { setTextViewText(R.id.headphones, this) }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package eu.darken.capod.reaction.popup.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.core.view.isInvisible
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.debug.autoreport.DebugSettings
|
||||
import eu.darken.capod.databinding.PopupNotificationDualPodsBinding
|
||||
import eu.darken.capod.databinding.PopupNotificationSinglePodsBasicBinding
|
||||
import eu.darken.capod.databinding.PopupNotificationSinglePodsBinding
|
||||
import eu.darken.capod.pods.core.*
|
||||
import eu.darken.capod.pods.core.apple.BasicSingleApplePods
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.SingleApplePods
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
class PopUpPodViewFactory @Inject constructor(
|
||||
@ApplicationContext private val appContext: Context,
|
||||
private val debugSettings: DebugSettings,
|
||||
) {
|
||||
|
||||
private val context = ContextThemeWrapper(appContext, R.style.AppTheme)
|
||||
private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||
|
||||
fun createContentView(parent: ViewGroup, device: PodDevice): View = when (device) {
|
||||
is DualApplePods -> createDualApplePods(parent, device)
|
||||
is SingleApplePods -> createSingleApplePods(parent, device) // Unused, has no case to trigger reaction?
|
||||
is BasicSingleApplePods -> createSingleBasicApplePods(
|
||||
parent,
|
||||
device
|
||||
) // Unused, has no case to trigger reaction?
|
||||
else -> throw IllegalArgumentException("Unexpected device: $device")
|
||||
}
|
||||
|
||||
private fun createDualApplePods(parent: ViewGroup, device: DualApplePods): View =
|
||||
PopupNotificationDualPodsBinding.inflate(layoutInflater, parent, false).apply {
|
||||
device.apply {
|
||||
podIcon.setImageResource(iconRes)
|
||||
podLabel.text = getLabel(context)
|
||||
signal.text = getSignalQuality(context)
|
||||
signal.isInvisible = debugSettings.isDebugModeEnabled.value
|
||||
|
||||
// Left
|
||||
podLeftBatteryIcon.setImageResource(getBatteryDrawable(batteryLeftPodPercent))
|
||||
podLeftBatteryLabel.text = getBatteryLevelLeftPod(context)
|
||||
|
||||
// Case
|
||||
podCaseBatteryIcon.setImageResource(getBatteryDrawable(batteryCasePercent))
|
||||
podCaseBatteryLabel.text = getBatteryLevelCase(context)
|
||||
|
||||
// Right
|
||||
podRightBatteryIcon.setImageResource(getBatteryDrawable(batteryRightPodPercent))
|
||||
podRightBatteryLabel.text = getBatteryLevelRightPod(context)
|
||||
}
|
||||
}.root
|
||||
|
||||
private fun createSingleApplePods(parent: ViewGroup, device: SingleApplePods): View =
|
||||
PopupNotificationSinglePodsBinding.inflate(layoutInflater, parent, false).apply {
|
||||
device.apply {
|
||||
headphonesIcon.setImageResource(iconRes)
|
||||
headphonesLabel.text = getLabel(context)
|
||||
signal.text = getSignalQuality(context)
|
||||
signal.isInvisible = debugSettings.isDebugModeEnabled.value
|
||||
|
||||
headphonesBatteryIcon.setImageResource(getBatteryDrawable(batteryHeadsetPercent))
|
||||
headphonesBatteryLabel.text = getBatteryLevelHeadset(context)
|
||||
}
|
||||
}.root
|
||||
|
||||
private fun createSingleBasicApplePods(parent: ViewGroup, device: BasicSingleApplePods): View =
|
||||
PopupNotificationSinglePodsBasicBinding.inflate(layoutInflater, parent, false).apply {
|
||||
device.apply {
|
||||
headphonesIcon.setImageResource(iconRes)
|
||||
headphonesLabel.text = getLabel(context)
|
||||
signal.text = getSignalQuality(context)
|
||||
signal.isInvisible = debugSettings.isDebugModeEnabled.value
|
||||
|
||||
headphonesBatteryIcon.setImageResource(getBatteryDrawable(batteryHeadsetPercent))
|
||||
headphonesBatteryLabel.text = getBatteryLevelHeadset(context)
|
||||
}
|
||||
}.root
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package eu.darken.capod.reaction.popup.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Context.WINDOW_SERVICE
|
||||
import android.graphics.PixelFormat
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.FrameLayout
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import eu.darken.capod.R
|
||||
import eu.darken.capod.common.debug.logging.Logging.Priority.ERROR
|
||||
import eu.darken.capod.common.debug.logging.asLog
|
||||
import eu.darken.capod.common.debug.logging.log
|
||||
import eu.darken.capod.common.debug.logging.logTag
|
||||
import eu.darken.capod.pods.core.PodDevice
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class PopUpWindow @Inject constructor(
|
||||
@ApplicationContext private val appContext: Context,
|
||||
private val podViewFactory: PopUpPodViewFactory
|
||||
) {
|
||||
|
||||
private val context = ContextThemeWrapper(appContext, R.style.AppTheme)
|
||||
private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
||||
private val windowManager: WindowManager = context.getSystemService(WINDOW_SERVICE) as WindowManager
|
||||
private val layoutParams = WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT, // Display it on top of other application windows
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // Don't let it grab the input focus
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, // Make the underlying application window visible
|
||||
|
||||
PixelFormat.TRANSLUCENT
|
||||
).apply {
|
||||
gravity = Gravity.BOTTOM
|
||||
}
|
||||
private val popUpView: View = layoutInflater.inflate(R.layout.popup_window_container_layout, null).apply {
|
||||
findViewById<View>(R.id.close_action).setOnClickListener { close() }
|
||||
}
|
||||
private val deviceContainer = popUpView.findViewById<FrameLayout>(R.id.popup_content)
|
||||
|
||||
fun show(device: PodDevice) = try {
|
||||
log(TAG) { "open()" }
|
||||
if (popUpView.windowToken == null && popUpView.parent == null) {
|
||||
val podView = podViewFactory.createContentView(deviceContainer, device)
|
||||
deviceContainer.addView(podView)
|
||||
windowManager.addView(popUpView, layoutParams)
|
||||
} else {
|
||||
log(TAG) { "View already added." }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log(TAG, ERROR) { "open() failed: ${e.asLog()}" }
|
||||
}
|
||||
|
||||
fun close() = try {
|
||||
log(TAG) { "close()" }
|
||||
if (popUpView.parent != null) {
|
||||
// (popUpView.parent as ViewGroup).removeAllViews()
|
||||
// popUpView.invalidate()
|
||||
windowManager.removeView(popUpView)
|
||||
} else {
|
||||
log(TAG) { "View was not added" }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log(TAG, ERROR) { "close() failed: ${e.asLog()}" }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = logTag("Reaction", "PopUp", "Window")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
|
||||
</vector>
|
||||
@@ -1,72 +1,182 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pod_label"
|
||||
style="@style/TextAppearance.Compat.Notification.Title"
|
||||
<ImageView
|
||||
android:id="@+id/pod_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_device_generic_earbuds"
|
||||
app:layout_constraintBottom_toBottomOf="@id/pod_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/pod_label"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/pod_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/pod_label"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/signal"
|
||||
app:layout_constraintStart_toEndOf="@id/pod_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="AirPods Pro" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/signal"
|
||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:orientation="horizontal">
|
||||
android:drawableEnd="@drawable/ic_baseline_signal_cellular_alt_24"
|
||||
android:gravity="center"
|
||||
android:minWidth="44dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/pod_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/pod_label"
|
||||
tools:text="-90%" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@id/pod_left_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/pod_case_container"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/pod_label">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pod_left"
|
||||
style="@style/TextAppearance.Compat.Notification.Title"
|
||||
<ImageView
|
||||
android:id="@+id/pod_left_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:drawableStart="@drawable/ic_airpod_left_24"
|
||||
android:src="@drawable/ic_airpod_left_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/pod_left_battery_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/pod_left_battery_icon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/pod_left_battery_label" />
|
||||
|
||||
<ImageView
|
||||
android:id="@id/pod_left_battery_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_baseline_battery_unknown_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/pod_left_battery_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/pod_left_battery_label"
|
||||
app:layout_constraintStart_toEndOf="@id/pod_left_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/pod_left_battery_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/pod_left_battery_label"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/pod_left_battery_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="100%" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pod_case"
|
||||
style="@style/TextAppearance.Compat.Notification.Title"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/pod_case_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/pod_right_container"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toEndOf="@id/pod_left_container"
|
||||
app:layout_constraintTop_toBottomOf="@id/pod_label">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pod_case_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:drawableStart="@drawable/ic_airpod_case_24"
|
||||
android:src="@drawable/ic_airpod_case_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/pod_case_battery_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/pod_case_battery_icon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/pod_case_battery_label" />
|
||||
|
||||
<ImageView
|
||||
android:id="@id/pod_case_battery_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_baseline_battery_unknown_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/pod_case_battery_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/pod_case_battery_label"
|
||||
app:layout_constraintStart_toEndOf="@id/pod_case_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/pod_case_battery_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/pod_case_battery_label"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/pod_case_battery_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="100%" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pod_right"
|
||||
style="@style/TextAppearance.Compat.Notification.Title"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@id/pod_right_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toEndOf="@id/pod_case_container"
|
||||
app:layout_constraintTop_toBottomOf="@id/pod_label">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pod_right_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:drawableStart="@drawable/ic_airpod_right_24"
|
||||
android:src="@drawable/ic_airpod_right_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/pod_right_battery_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/pod_right_battery_icon"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/pod_right_battery_label" />
|
||||
|
||||
<ImageView
|
||||
android:id="@id/pod_right_battery_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_baseline_battery_unknown_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/pod_right_battery_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/pod_right_battery_label"
|
||||
app:layout_constraintStart_toEndOf="@id/pod_right_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/pod_right_battery_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/pod_right_battery_label"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/pod_right_battery_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="100%" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,29 +1,81 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headphones_label"
|
||||
style="@style/TextAppearance.Compat.Notification.Title"
|
||||
<ImageView
|
||||
android:id="@+id/headphones_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_device_generic_earbuds"
|
||||
app:layout_constraintBottom_toBottomOf="@id/headphones_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/headphones_label"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/headphones_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/headphones_label"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:gravity="center"
|
||||
app:layout_constraintEnd_toStartOf="@id/signal"
|
||||
app:layout_constraintStart_toEndOf="@id/headphones_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="AirPods Max" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headphones"
|
||||
style="@style/TextAppearance.Compat.Notification.Title"
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/signal"
|
||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:drawableStart="@drawable/ic_device_generic_headphones"
|
||||
tools:text="100%" />
|
||||
android:drawableEnd="@drawable/ic_baseline_signal_cellular_alt_24"
|
||||
android:gravity="center"
|
||||
android:minWidth="44dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/headphones_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/headphones_label"
|
||||
tools:text="-90%" />
|
||||
|
||||
</LinearLayout>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/headphones_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/headphones_label">
|
||||
|
||||
<ImageView
|
||||
android:id="@id/headphones_battery_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_baseline_battery_unknown_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/headphones_battery_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/headphones_battery_label"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/headphones_battery_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/headphones_battery_label"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/headphones_battery_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="100%" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,38 +1,81 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
<ImageView
|
||||
android:id="@+id/headphones_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_device_generic_earbuds"
|
||||
app:layout_constraintBottom_toBottomOf="@id/headphones_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/headphones_label"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/headphones_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/headphones_label"
|
||||
style="@style/TextAppearance.Compat.Notification.Title"
|
||||
android:layout_width="wrap_content"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:gravity="center"
|
||||
tools:text="AirPods Max" />
|
||||
app:layout_constraintEnd_toStartOf="@id/signal"
|
||||
app:layout_constraintStart_toEndOf="@id/headphones_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Beats Solo 3" />
|
||||
|
||||
<LinearLayout
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/signal"
|
||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:drawableEnd="@drawable/ic_baseline_signal_cellular_alt_24"
|
||||
android:gravity="center"
|
||||
android:minWidth="44dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/headphones_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/headphones_label"
|
||||
tools:text="-90%" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headphones"
|
||||
style="@style/TextAppearance.Compat.Notification.Title"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/headphones_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/headphones_label">
|
||||
|
||||
<ImageView
|
||||
android:id="@id/headphones_battery_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:drawableStart="@drawable/ic_device_generic_headphones"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_baseline_battery_unknown_24"
|
||||
app:layout_constraintBottom_toBottomOf="@id/headphones_battery_label"
|
||||
app:layout_constraintEnd_toStartOf="@id/headphones_battery_label"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/headphones_battery_label" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/headphones_battery_label"
|
||||
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/headphones_battery_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="100%" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="320dp"
|
||||
android:minHeight="96dp"
|
||||
android:layout_margin="8dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/popup_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/close_action"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="1.0" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/close_action"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/general_close_action"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/popup_content" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@@ -15,6 +15,7 @@
|
||||
<string name="general_grant_permission_action">Grant permission</string>
|
||||
<string name="general_upgrade_action">Upgrade</string>
|
||||
<string name="general_check_action">Check</string>
|
||||
<string name="general_close_action">Close</string>
|
||||
|
||||
<string name="debug_debuglog_size_label">Size</string>
|
||||
<string name="debug_debuglog_size_compressed_label">Compressed size</string>
|
||||
@@ -134,4 +135,6 @@
|
||||
<string name="help_translate_description">Help translate this into your favorite language.</string>
|
||||
<string name="settings_onepod_mode_label">One pod mode</string>
|
||||
<string name="settings_onepod_mode_description">Wearing both pods is not required, wearing a single pod is sufficient to trigger reactions.</string>
|
||||
<string name="permission_system_alert_window_label">System Alert Window</string>
|
||||
<string name="permission_system_alert_window_description">Allow CAPod to draw over other apps to make the feature \"Show PopUp\" possible.</string>
|
||||
</resources>
|
||||
@@ -14,5 +14,6 @@
|
||||
|
||||
<style name="PodInfoItemText" parent="TextAppearance.MaterialComponents.Body2">
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
</style>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user