Atoll: distinguish charging-on-hold from fully charged on lockscreen widget

The lockscreen battery widget treated any plugged-in-but-not-charging
state as 'Fully charged'. macOS pauses charging for battery health
(e.g., optimized battery charging at 80%), so this misreported the
actual battery state.

Now 'Fully charged' shows only at 100% + plugged in; otherwise the
detail label reads '<level>% • On hold' (with a matching accessibility
string). Charging-in-progress and fully-charged states are unchanged.
This commit is contained in:
Jis G Jacob 2026-05-12 16:22:24 +05:30
commit d205923b02
2 changed files with 47 additions and 6 deletions

View file

@ -2314,6 +2314,7 @@
}, },
"±10 Seconds" : { "±10 Seconds" : {
"comment" : "Display name for the \"±10 Seconds\" music skip behavior option.", "comment" : "Display name for the \"±10 Seconds\" music skip behavior option.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -3149,6 +3150,7 @@
}, },
"Accent" : { "Accent" : {
"comment" : "Display name for the caps lock indicator tint mode.", "comment" : "Display name for the caps lock indicator tint mode.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -3706,6 +3708,7 @@
}, },
"Adaptive gradient" : { "Adaptive gradient" : {
"comment" : "Display name for the timer icon color mode: adaptive gradient.", "comment" : "Display name for the timer icon color mode: adaptive gradient.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -5632,10 +5635,6 @@
} }
} }
}, },
"Amazon Music" : {
"comment" : "Spotify music service.",
"isCommentAutoGenerated" : true
},
"Animation" : { "Animation" : {
"extractionState" : "stale", "extractionState" : "stale",
"localizations" : { "localizations" : {
@ -6029,6 +6028,7 @@
}, },
"Apple Music" : { "Apple Music" : {
"comment" : "Media controller type for Apple Music", "comment" : "Media controller type for Apple Music",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -6936,6 +6936,7 @@
}, },
"Bar" : { "Bar" : {
"comment" : "Name of the timer progress style that shows a horizontal bar.", "comment" : "Name of the timer progress style that shows a horizontal bar.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -7087,6 +7088,9 @@
} }
} }
}, },
"Battery at %d percent, charging on hold" : {
"comment" : "Plugged in but charging is paused by the system"
},
"Battery charging" : { "Battery charging" : {
"comment" : "Battery charging without estimate", "comment" : "Battery charging without estimate",
"localizations" : { "localizations" : {
@ -9048,6 +9052,9 @@
} }
} }
}, },
"Charging on hold" : {
"comment" : "Plugged in but charging is paused by the system"
},
"Charging on Hold: Desktop Mode" : { "Charging on Hold: Desktop Mode" : {
"localizations" : { "localizations" : {
"ar" : { "ar" : {
@ -14535,6 +14542,7 @@
}, },
"Digital" : { "Digital" : {
"comment" : "The display name for the \"Digital\" reminder presentation style.", "comment" : "The display name for the \"Digital\" reminder presentation style.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -20845,6 +20853,7 @@
}, },
"Green" : { "Green" : {
"comment" : "Display name for the green caps lock indicator tint mode.", "comment" : "Display name for the green caps lock indicator tint mode.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -29970,6 +29979,7 @@
}, },
"Now Playing" : { "Now Playing" : {
"comment" : "Name of the media controller type for the \"Now Playing\" option.", "comment" : "Name of the media controller type for the \"Now Playing\" option.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -30157,6 +30167,9 @@
} }
} }
}, },
"On hold" : {
"comment" : "Plugged in but charging is paused by the system"
},
"One or more files failed to load" : { "One or more files failed to load" : {
"localizations" : { "localizations" : {
"ar" : { "ar" : {
@ -30719,6 +30732,7 @@
}, },
"Panel" : { "Panel" : {
"comment" : "Display name for the clipboard display mode \"Panel\".", "comment" : "Display name for the clipboard display mode \"Panel\".",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -34275,6 +34289,7 @@
}, },
"Ring" : { "Ring" : {
"comment" : "The name of the timer progress style that shows a ring shape.", "comment" : "The name of the timer progress style that shows a ring shape.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -35796,6 +35811,7 @@
}, },
"Separate Tab" : { "Separate Tab" : {
"comment" : "Display name for the clipboard display mode option to open the clipboard in a separate tab.", "comment" : "Display name for the clipboard display mode option to open the clipboard in a separate tab.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -38231,6 +38247,7 @@
}, },
"Shows screen assistant as a dropdown attached to the AI button" : { "Shows screen assistant as a dropdown attached to the AI button" : {
"comment" : "Description of the screen assistant display mode option that shows the screen assistant as a dropdown attached to the AI button.", "comment" : "Description of the screen assistant display mode option that shows the screen assistant as a dropdown attached to the AI button.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -38255,6 +38272,7 @@
}, },
"Shows screen assistant in a floating panel near the notch" : { "Shows screen assistant in a floating panel near the notch" : {
"comment" : "Description of the screen assistant display mode option that shows the screen assistant in a floating panel near the notch.", "comment" : "Description of the screen assistant display mode option that shows the screen assistant in a floating panel near the notch.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -38482,6 +38500,7 @@
}, },
"Skip forward or backward by ten seconds" : { "Skip forward or backward by ten seconds" : {
"comment" : "Description of a music skip behavior option.", "comment" : "Description of a music skip behavior option.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -39209,6 +39228,7 @@
}, },
"Spotify" : { "Spotify" : {
"comment" : "Spotify media controller type.", "comment" : "Spotify media controller type.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -39449,6 +39469,7 @@
}, },
"Standard previous/next track controls" : { "Standard previous/next track controls" : {
"comment" : "Description of the music skip behavior option to use standard previous/next track controls.", "comment" : "Description of the music skip behavior option to use standard previous/next track controls.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -42276,6 +42297,7 @@
}, },
"Track Skip" : { "Track Skip" : {
"comment" : "Display name for the \"Track Skip\" music skip behavior.", "comment" : "Display name for the \"Track Skip\" music skip behavior.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {
@ -45651,6 +45673,7 @@
}, },
"Youtube Music" : { "Youtube Music" : {
"comment" : "Spotify music service.", "comment" : "Spotify music service.",
"extractionState" : "stale",
"isCommentAutoGenerated" : true, "isCommentAutoGenerated" : true,
"localizations" : { "localizations" : {
"ko" : { "ko" : {

View file

@ -1261,8 +1261,16 @@ struct LockScreenWeatherWidget: View {
private func chargingStatusFallback(for info: LockScreenWeatherSnapshot.ChargingInfo) -> String { private func chargingStatusFallback(for info: LockScreenWeatherSnapshot.ChargingInfo) -> String {
if info.isPluggedIn && !info.isCharging { if info.isPluggedIn && !info.isCharging {
let level = info.batteryLevel.map(clampedBatteryLevel)
if level == 100 {
return NSLocalizedString("Fully charged", comment: "Charging fallback label when already charged") return NSLocalizedString("Fully charged", comment: "Charging fallback label when already charged")
} }
if let level {
let onHold = NSLocalizedString("On hold", comment: "Plugged in but charging is paused by the system")
return "\(level)% • \(onHold)"
}
return NSLocalizedString("On hold", comment: "Plugged in but charging is paused by the system")
}
return NSLocalizedString("Charging", comment: "Charging fallback label when no estimate is available") return NSLocalizedString("Charging", comment: "Charging fallback label when no estimate is available")
} }
@ -1456,8 +1464,18 @@ struct LockScreenWeatherWidget: View {
} }
if charging.isPluggedIn && !charging.isCharging { if charging.isPluggedIn && !charging.isCharging {
let level = charging.batteryLevel.map(clampedBatteryLevel)
if level == 100 {
return NSLocalizedString("Battery fully charged", comment: "Battery is full") return NSLocalizedString("Battery fully charged", comment: "Battery is full")
} }
if let level {
return String(
format: NSLocalizedString("Battery at %d percent, charging on hold", comment: "Plugged in but charging is paused by the system"),
level
)
}
return NSLocalizedString("Charging on hold", comment: "Plugged in but charging is paused by the system")
}
if snapshot.showsChargingPercentage, let level = charging.batteryLevel { if snapshot.showsChargingPercentage, let level = charging.batteryLevel {
return String( return String(