Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class SettingsRepository(
"Cycle sound modes" -> Action.CycleSoundModes
"Toggle media volume" -> Action.ToggleMediaVolume
"Like current song" -> Action.LikeCurrentSong
"Circle to Search" -> Action.CircleToSearch
"Circle to Search" -> Action.CircleToSearch()
else -> null
}
setRemapAction(key, action)
Expand Down Expand Up @@ -299,6 +299,7 @@ class SettingsRepository(
const val KEY_CIRCLE_TO_SEARCH_GESTURE_HEIGHT = "circle_to_search_gesture_height"
const val KEY_CIRCLE_TO_SEARCH_GESTURE_WIDTH = "circle_to_search_gesture_width"
const val KEY_CIRCLE_TO_SEARCH_PREVIEW_ENABLED = "circle_to_search_preview_enabled"
const val KEY_CIRCLE_TO_SEARCH_HIDE_ON_SHADE = "circle_to_search_hide_on_shade"
const val KEY_AUTO_UPDATE_ENABLED = "auto_update_enabled"
const val KEY_UPDATE_NOTIFICATION_ENABLED = "update_notification_enabled"
const val KEY_LAST_UPDATE_CHECK_TIME = "last_update_check_time"
Expand Down Expand Up @@ -564,7 +565,9 @@ class SettingsRepository(
const val KEY_ISLAND_SHOW_TIME_BATTERY = "island_show_time_battery"
const val KEY_ISLAND_TIME_SHOW_SECONDS = "island_time_show_seconds"
const val KEY_ISLAND_THEMED_TEXT = "island_themed_text"
const val KEY_ISLAND_THEMED_APP_ICONS = "island_themed_app_icons"
const val KEY_ISLAND_CHIPS = "island_chips"
const val KEY_ISLAND_TIME_CHIP = "island_time_chip"
const val KEY_ISLAND_ICON_COLOR_MODE = "island_icon_color_mode"
const val KEY_ISLAND_ICON_COLOR_CUSTOM = "island_icon_color_custom"
const val KEY_ISLAND_ICON_MATERIAL_YOU = "island_icon_material_you"
Expand All @@ -573,6 +576,7 @@ class SettingsRepository(
const val KEY_ISLAND_TIME_FORMAT = "island_time_format"
const val KEY_ISLAND_TIME_PERIOD = "island_time_period"
const val KEY_ISLAND_TIME_LEADING_ZERO = "island_time_leading_zero"
const val KEY_ISLAND_TIME_DAY_SUFFIX = "island_time_day_suffix"
const val ISLAND_TIME_FORMAT_SYSTEM = "system"
const val ISLAND_TIME_FORMAT_12H = "12h"
const val ISLAND_TIME_FORMAT_24H = "24h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,16 @@ sealed interface Action {
override val isConfigurable: Boolean = true
}

enum class CircleToSearchMethod { ACCESSIBILITY, SHIZUKU }

@Keep
data object CircleToSearch : Action {
override val title: Int = R.string.diy_action_circle_to_search
override val icon: Int = R.drawable.rounded_search_24
override val permissions: List<String> = listOf("shizuku", "root")
data class CircleToSearch(
@SerializedName("method") val method: CircleToSearchMethod = CircleToSearchMethod.ACCESSIBILITY,
) : Action {
override val title: Int get() = R.string.diy_action_circle_to_search
override val icon: Int get() = R.drawable.rounded_search_24
override val permissions: List<String> get() =
if (method == CircleToSearchMethod.SHIZUKU) listOf("shizuku", "root") else listOf("ACCESSIBILITY")
}

@Keep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ object ActionRegistry {
add(Action.CustomSettings())
add(Action.Wait())
add(Action.SendNotification())
add(Action.CircleToSearch)
add(Action.CircleToSearch())
add(Action.TurnOffBackGesture)
add(Action.TurnOnBackGesture)
// TakeScreenshot only available on screen-on context (null means no filter = include always)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.sameerasw.essentials.island

import android.content.Context
import android.text.format.DateFormat
import com.sameerasw.essentials.data.repository.SettingsRepository
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

object IslandTimeFormat {
fun is24Hour(context: Context, settings: SettingsRepository): Boolean =
when (settings.getString(SettingsRepository.KEY_ISLAND_TIME_FORMAT, null)) {
SettingsRepository.ISLAND_TIME_FORMAT_12H -> false
SettingsRepository.ISLAND_TIME_FORMAT_24H -> true
else -> DateFormat.is24HourFormat(context)
}

fun leadingZero(context: Context, settings: SettingsRepository): Boolean =
if (settings.contains(SettingsRepository.KEY_ISLAND_TIME_LEADING_ZERO)) {
settings.getBoolean(SettingsRepository.KEY_ISLAND_TIME_LEADING_ZERO, false)
} else {
is24Hour(context, settings)
}

fun pattern(context: Context, settings: SettingsRepository, seconds: Boolean = false, period: Boolean? = null): String {
val is24 = is24Hour(context, settings)
val hours = if (is24) {
if (leadingZero(context, settings)) "HH" else "H"
} else if (leadingZero(context, settings)) {
"hh"
} else {
"h"
}
val base = if (seconds) "$hours:mm:ss" else "$hours:mm"
val showPeriod = !is24 && (period ?: (settings.getString(SettingsRepository.KEY_ISLAND_TIME_PERIOD, null) == SettingsRepository.ISLAND_TIME_PERIOD_AM_PM))
return if (showPeriod) "$base a" else base
}

fun format(context: Context, settings: SettingsRepository, millis: Long, seconds: Boolean = false, period: Boolean? = null): String =
SimpleDateFormat(pattern(context, settings, seconds, period), Locale.getDefault()).format(Date(millis))
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ object SideBubblePriority {

object IslandChips {
val items = setOf(
"media", "calendar", "timer", "alarm", "caffeinate", "flashlight", "sound_mode", "devices", "travel", "navigation",
"media", "calendar", "timer", "alarm", "caffeinate", "flashlight", "sound_mode", "devices", "travel", "navigation", "call",
)
}

Expand Down Expand Up @@ -150,6 +150,8 @@ class IslandItem(
val stack: List<StackIcon> = emptyList(),
val queued: List<StackIcon>? = null,
val priorityGroup: String? = null,
// Rendered inside a colored chip when Island chips is enabled.
val chip: Boolean = key in IslandChips.items,
) {
var userPriority: Int? = null

Expand Down Expand Up @@ -178,6 +180,7 @@ class IslandItem(
stack = stack,
queued = queued,
priorityGroup = priorityGroup,
chip = chip,
).also { it.userPriority = userPriority }

val effectivePriority: Int get() = priorityOverride ?: userPriority ?: priority
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sameerasw.essentials.island.plugins.alarm

import com.sameerasw.essentials.island.IslandTimeFormat
import android.app.AlarmManager
import android.content.BroadcastReceiver
import android.content.Context
Expand Down Expand Up @@ -31,6 +32,9 @@ class AlarmPlugin : BaseIslandPlugin() {
SettingsRepository.KEY_ISLAND_SHOW_ALARM,
SettingsRepository.KEY_ISLAND_ALARM_WINDOW_HOURS,
SettingsRepository.KEY_ISLAND_ALARM_HIDE_TIME,
SettingsRepository.KEY_ISLAND_TIME_FORMAT,
SettingsRepository.KEY_ISLAND_TIME_LEADING_ZERO,
SettingsRepository.KEY_ISLAND_TIME_PERIOD,
)

private var registered = false
Expand Down Expand Up @@ -135,11 +139,6 @@ object NextAlarm {
}

fun format(context: Context, millis: Long, withPeriod: Boolean): String {
val pattern = when {
DateFormat.is24HourFormat(context) -> "HH:mm"
withPeriod -> "h:mm a"
else -> "h:mm"
}
return SimpleDateFormat(pattern, Locale.getDefault()).format(Date(millis))
return IslandTimeFormat.format(context, SettingsRepository(context), millis, period = withPeriod)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sameerasw.essentials.island.plugins.brief

import com.sameerasw.essentials.island.IslandTimeFormat
import com.sameerasw.essentials.island.ui.components.LocalIslandIconColor
import com.sameerasw.essentials.island.plugins.alarm.NextAlarm
import androidx.compose.foundation.layout.fillMaxSize
Expand Down Expand Up @@ -440,8 +441,8 @@ private fun BriefOverview(
}
}

val timePattern = if (DateFormat.is24HourFormat(context)) "HH:mm" else "h:mm"
val time = SimpleDateFormat(timePattern, Locale.getDefault()).format(Date(now))
val timeSettings = remember { SettingsRepository(context) }
val time = IslandTimeFormat.format(context, timeSettings, now)
val date = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "EEEMMMd"), Locale.getDefault()).format(Date(now))

val artwork = remember(media?.artwork) { media?.artwork?.asImageBitmap() }
Expand Down Expand Up @@ -686,15 +687,16 @@ private fun BriefPlayerButton(
}

private fun briefWhen(context: Context, event: UpcomingCalendarEvent, now: Long): String {
val timeFormat = DateFormat.getTimeFormat(context)
val timeSettings = SettingsRepository(context)
val timeText = { millis: Long -> IslandTimeFormat.format(context, timeSettings, millis) }
val start = event.startTimeMillis
val tomorrow = !isSameDay(start, now) && start > now
if (event.allDay) {
val all = context.getString(R.string.island_brief_all_day)
return if (tomorrow) context.getString(R.string.island_brief_tomorrow, all) else all
}
if (start <= now) {
return context.getString(R.string.island_brief_now_until, timeFormat.format(Date(event.endTimeMillis)))
return context.getString(R.string.island_brief_now_until, timeText(event.endTimeMillis))
}
val minutes = ((start - now + 59_999L) / 60_000L).toInt()
val hours = minutes / 60
Expand All @@ -707,8 +709,8 @@ private fun briefWhen(context: Context, event: UpcomingCalendarEvent, now: Long)
context.getString(R.string.island_brief_in_hours_minutes, hours, rest)
}
minutes < 12 * 60 -> context.getString(R.string.island_brief_in_hours, if (rest >= 30) hours + 1 else hours)
tomorrow -> context.getString(R.string.island_brief_tomorrow, timeFormat.format(Date(start)))
else -> context.getString(R.string.island_brief_today, timeFormat.format(Date(start)))
tomorrow -> context.getString(R.string.island_brief_tomorrow, timeText(start))
else -> context.getString(R.string.island_brief_today, timeText(start))
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.sameerasw.essentials.island.plugins.calendar

import com.sameerasw.essentials.data.repository.SettingsRepository
import com.sameerasw.essentials.island.IslandTimeFormat
import com.sameerasw.essentials.island.ui.squareFit
import androidx.compose.foundation.layout.fillMaxSize
import com.sameerasw.essentials.island.ui.SurfaceBackdrop
Expand Down Expand Up @@ -62,12 +64,13 @@ fun CalendarExpanded(
val context = LocalContext.current
val sidePadding = spec.expandedPadding + spec.expandedCorner * 0.35f
val calendarColor = event.calendarColor?.let { Color(soften(it)) } ?: MaterialTheme.colorScheme.primary
val timeFormat = DateFormat.getTimeFormat(context)
val timeSettings = remember { SettingsRepository(context) }
val timeText = { millis: Long -> IslandTimeFormat.format(context, timeSettings, millis) }
val timeRange = when {
event.allDay -> stringResource(R.string.island_calendar_all_day)
event.endTimeMillis > event.startTimeMillis ->
"${timeFormat.format(Date(event.startTimeMillis))} – ${timeFormat.format(Date(event.endTimeMillis))}"
else -> timeFormat.format(Date(event.startTimeMillis))
"${timeText(event.startTimeMillis)} – ${timeText(event.endTimeMillis)}"
else -> timeText(event.startTimeMillis)
}
val detailStyle = IslandTextStyles.body.copy(color = islandTextColor(), fontSize = 15.sp, lineHeight = 20.sp)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sameerasw.essentials.island.plugins.calendar

import com.sameerasw.essentials.island.IslandTimeFormat
import android.app.KeyguardManager
import android.content.ContentUris
import android.content.Context
Expand Down Expand Up @@ -36,6 +37,9 @@ class CalendarPlugin : BaseIslandPlugin() {
SettingsRepository.KEY_ISLAND_CALENDAR_PRIORITY_MINUTES,
SettingsRepository.KEY_ISLAND_CALENDAR_HIDE_LOCKED,
SettingsRepository.KEY_ISLAND_CALENDAR_COMPACT_TIME,
SettingsRepository.KEY_ISLAND_TIME_FORMAT,
SettingsRepository.KEY_ISLAND_TIME_LEADING_ZERO,
SettingsRepository.KEY_ISLAND_TIME_PERIOD,
)

private var event: UpcomingCalendarEvent? = null
Expand Down Expand Up @@ -86,8 +90,7 @@ class CalendarPlugin : BaseIslandPlugin() {
val now = System.currentTimeMillis()
val full = CalendarEventUtil.formatRelativeTime(context, e.startTimeMillis, now)
val short = if (settings.getBoolean(SettingsRepository.KEY_ISLAND_CALENDAR_COMPACT_TIME, false) && e.startTimeMillis - now >= 60 * 60_000L) {
val pattern = if (DateFormat.is24HourFormat(context)) "H:mm" else "h:mm"
SimpleDateFormat(pattern, Locale.getDefault()).format(Date(e.startTimeMillis))
IslandTimeFormat.format(context, settings, e.startTimeMillis, period = false)
} else {
CalendarEventUtil.formatRelativeTimeCompact(e.startTimeMillis, now)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sameerasw.essentials.island.plugins.consciousgate

import com.sameerasw.essentials.utils.AppIconUtil
import com.sameerasw.essentials.island.ui.components.MarqueeText
import android.content.Context
import android.os.PowerManager
Expand Down Expand Up @@ -68,7 +69,7 @@ class ConsciousGatePlugin : BaseIslandPlugin() {
if (cachedPkg != session.packageName || cachedIcon == null) {
cachedPkg = session.packageName
cachedIcon = try {
AppUtil.drawableToBitmap(context.packageManager.getApplicationIcon(session.packageName))
AppUtil.drawableToBitmap(AppIconUtil.islandAppIcon(context, session.packageName))
} catch (_: Exception) {
null
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sameerasw.essentials.island.plugins.media

import com.sameerasw.essentials.utils.AppIconUtil
import android.content.ComponentName
import android.content.Context
import android.graphics.Bitmap
Expand Down Expand Up @@ -150,7 +151,7 @@ class MediaSessionSource(
}

fun appIcon(context: Context, packageName: String): Bitmap? = try {
AppUtil.drawableToBitmap(context.packageManager.getApplicationIcon(packageName))
AppUtil.drawableToBitmap(AppIconUtil.islandAppIcon(context, packageName))
} catch (_: Exception) {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,17 @@ class NavigationPlugin : BaseIslandPlugin() {

override fun refresh() {
ctx ?: return
data = NotificationListener.getLatestNavigationNotification()
data = stabilized(NotificationListener.getLatestNavigationNotification())
render()
}

private fun update(next: NavigationNotificationData?) {
val c = ctx ?: return
val turned = next?.instruction != null && next.instruction != data?.instruction
data = next
val stable = stabilized(next)
val turned = stable?.instruction != null && stable.instruction != data?.instruction
data = stable
render()
if (next == null) {
if (stable == null) {
c.mainHandler.removeCallbacks(endExpand)
c.mainHandler.removeCallbacks(peekAfterCollapse)
c.mainHandler.removeCallbacks(endRoute)
Expand All @@ -94,9 +95,9 @@ class NavigationPlugin : BaseIslandPlugin() {
if (!enabled()) return
val focused = c.focusedKey()
val action = trigger.decide(
instruction = next.instruction.orEmpty(),
instruction = stable.instruction.orEmpty(),
turned = turned,
meters = NavigationParser.meters(next.distance),
meters = NavigationParser.meters(stable.distance),
threshold = settings.getIslandNavigationExpandDistance(),
onNew = settings.getIslandNavigationOnNew(),
canPeek = settings.isIslandLineStageEnabled(),
Expand All @@ -110,6 +111,12 @@ class NavigationPlugin : BaseIslandPlugin() {
}
}

private fun stabilized(next: NavigationNotificationData?): NavigationNotificationData? {
val previous = data?.maneuver ?: return next
val incoming = next?.maneuver ?: return next
return if (previous !== incoming && previous.sameAs(incoming)) next.copy(maneuver = previous) else next
}

private fun expand(c: IslandPluginContext) {
if (c.focusedKey() == ITEM_KEY && c.currentStage() == IslandStage.Expanded) return
c.mainHandler.removeCallbacks(peekAfterCollapse)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.sameerasw.essentials.island.plugins.network

import com.sameerasw.essentials.utils.NetworkUtil
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
Expand Down Expand Up @@ -66,9 +67,11 @@ class NetworkPlugin : BaseIslandPlugin() {
override fun onStart() {
val c = ctx ?: return
airplane = readAirplane()
wifiNetwork = connectivity.activeNetwork?.takeIf {
connectivity.getNetworkCapabilities(it)?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true
}
wifiNetwork = connectivity.allNetworks.firstOrNull { network ->
connectivity.getNetworkCapabilities(network)?.let {
it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && !it.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
} == true
}.takeIf { NetworkUtil.isWifiConnected(connectivity) }
ssid = wifiNetwork?.let { WifiUtil.getCurrentSsid(context) }
try {
val request = NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build()
Expand Down Expand Up @@ -102,7 +105,7 @@ class NetworkPlugin : BaseIslandPlugin() {
override fun refresh() = render()

private fun onWifi(network: Network, caps: NetworkCapabilities) {
if (ctx == null || !caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) return
if (ctx == null || !caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) return
if (network == wifiNetwork) {
if (ssid == null) ssidFrom(caps)?.let { ssid = it }
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ class NotificationsPlugin : BaseIslandPlugin() {
}
val stack = alerts.map { stackIconFor(it, current = it === alert) }
val waitingAlerts = waitingInOrder(alert).filter { !it.hubOnly && it.key !in seen }
val queued = if (hub() && alert.hubOnly) {
val queued = if (hub()) {
hubEntries().filter { entry -> entry.alerts.none { it === alert } }.map { hubIconFor(it) }
} else {
waitingAlerts.map { stackIconFor(it, current = false) }
Expand Down
Loading
Loading