Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4cbf29d
Update Astronomy plugin to use dynamic named colors
dmpr0 Jun 25, 2026
c12fa80
Changed buttons
vitaliy-sova-ios Jul 8, 2026
33044d8
Added Inertial scrolling & zoom buttons for mac
vitaliy-sova-ios Jul 8, 2026
c792bb0
Remove camera button and unify AR/camera behavior
vitaliy-sova-ios Jul 8, 2026
48653f1
Refactor AR controls into dedicated component
vitaliy-sova-ios Jul 9, 2026
8892c6a
Fix SwiftLint warnings
vitaliy-sova-ios Jul 9, 2026
8099f44
Changed colors and alpha
vitaliy-sova-ios Jul 10, 2026
4250a13
Merge branch 'master' into astro_plugin_star_map
vitaliy-sova-ios Jul 10, 2026
e5426e3
Merge remote-tracking branch 'origin/feature/astronomy-colors' into a…
vitaliy-sova-ios Jul 10, 2026
90d5a26
Use color asset extensions in AstroUtils
vitaliy-sova-ios Jul 10, 2026
08ace4e
Fix buttons opacity
vitaliy-sova-ios Jul 14, 2026
9b2abf7
DayNight cache
vitaliy-sova-ios Jul 14, 2026
9a75cc1
Refactor Astronomy plugin UI and settings management
vitaliy-sova-ios Jul 15, 2026
abfdcc5
Refactor astronomy UI components
vitaliy-sova-ios Jul 15, 2026
bade85b
Persist astronomy settings and recent chips
vitaliy-sova-ios Jul 17, 2026
af03df6
Merge branch 'master' into astro_plugin_star_map
vitaliy-sova-ios Jul 17, 2026
b871e21
Code review fixes
vitaliy-sova-ios Jul 17, 2026
37a369e
Migrate Android legacy star_watcher_settings into astronomy_settings …
vitaliy-sova-ios Jul 17, 2026
c02d9e7
Code review fixes
vitaliy-sova-ios Jul 20, 2026
2f925d0
Code review fixes
vitaliy-sova-ios Jul 21, 2026
0fa2a7f
Remove unused icons and fix StarMap 2D/3D mode handling
vitaliy-sova-ios Jul 21, 2026
81d52a5
Restore view angle property in StarView
vitaliy-sova-ios Jul 21, 2026
a64f8d4
Merge branch 'master' into astro_plugin_star_map
vitaliy-sova-ios Jul 22, 2026
f4cbf71
Update StarMapViewController.swift
vitaliy-sova-ios Jul 22, 2026
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
40 changes: 24 additions & 16 deletions OsmAnd.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x4D",
"green" : "0x4D",
"red" : "0x4D"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x4D",
"green" : "0x4D",
"red" : "0x4D"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_navbar_close@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_navbar_close@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
5 changes: 0 additions & 5 deletions Sources/Constants/OAColors.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@
#define color_dialog_buttons_dark 0xff8800
#define color_on_map_icon_color 0x505050

#define color_on_map_icon_background_color_tap_light 0xE6E6E6
#define color_on_map_icon_background_color_tap_dark 0x595959

#define color_on_map_icon_border_color 0x4D4D4D

#define color_sky_day 0x8cbed6
#define color_sky_night 0x05142e

Expand Down
6 changes: 3 additions & 3 deletions Sources/Controllers/Map/OAHudButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ - (void)commonInit
{
self.unpressedColorDay = [UIColor colorNamed:ACColorNameMapButtonBgColorDefault].light;
self.unpressedColorNight = [UIColor colorNamed:ACColorNameMapButtonBgColorDefault].dark;
self.pressedColorDay = UIColorFromRGB(color_on_map_icon_background_color_tap_light);
self.pressedColorNight = UIColorFromRGB(color_on_map_icon_background_color_tap_dark);
self.pressedColorDay = [UIColor colorNamed:ACColorNameMapButtonBgColorTap].light;
self.pressedColorNight = [UIColor colorNamed:ACColorNameMapButtonBgColorTap].dark;
self.tintColorDay = [UIColor colorNamed:ACColorNameMapButtonIconColorDefault].light;
self.tintColorNight = [UIColor colorNamed:ACColorNameMapButtonIconColorDefault].dark;
self.borderColor = UIColorFromRGB(color_on_map_icon_border_color);
self.borderColor = [UIColor colorNamed:ACColorNameMapButtonBorderColor];
self.borderWidthDay = 0;
self.borderWidthNight = 2;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="onx-Gz-iEg">
<rect key="frame" x="0.0" y="0.0" width="64" height="42"/>
<color key="backgroundColor" white="0.0" alpha="0.80377358490566042" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" image="ic_navbar_close.png"/>
<state key="normal" image="ic_navbar_close"/>
<connections>
<action selector="closePressed:" destination="-1" eventType="touchUpInside" id="qhF-wP-sgx"/>
</connections>
Expand Down Expand Up @@ -556,7 +556,7 @@
<image name="ic_custom_routes" width="30" height="30"/>
<image name="ic_custom_straight_line.png" width="30" height="30"/>
<image name="ic_custom_undo.png" width="30" height="30"/>
<image name="ic_navbar_close.png" width="28" height="28"/>
<image name="ic_navbar_close" width="28" height="28"/>
<namedColor name="customSeparator">
<color red="0.79607843137254897" green="0.7803921568627451" blue="0.81960784313725488" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
<rect key="frame" x="0.0" y="16" width="44" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" image="ic_navbar_close.png"/>
<state key="normal" image="ic_navbar_close"/>
<connections>
<action selector="closePressed:" destination="-1" eventType="touchUpInside" id="gZd-S4-022"/>
</connections>
Expand All @@ -102,6 +102,6 @@
</objects>
<resources>
<image name="ic_action_wifi_off.png" width="30" height="30"/>
<image name="ic_navbar_close.png" width="28" height="28"/>
<image name="ic_navbar_close" width="28" height="28"/>
</resources>
</document>
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
<constraint firstAttribute="width" constant="28" id="NPl-hq-TuC"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal" image="ic_navbar_close.png"/>
<state key="normal" image="ic_navbar_close"/>
<connections>
<action selector="navBarCancelButtonPressed:" destination="-1" eventType="touchUpInside" id="p67-N5-hcJ"/>
</connections>
Expand Down Expand Up @@ -140,6 +140,6 @@
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
</objects>
<resources>
<image name="ic_navbar_close.png" width="28" height="28"/>
<image name="ic_navbar_close" width="28" height="28"/>
</resources>
</document>
14 changes: 13 additions & 1 deletion Sources/Helpers/MigrationManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ final class MigrationManager: NSObject {
case migrationHudButtonPositionsKey
case migrateRouteRecalculationValues
case migrateLocationIconSizeAndCourseIconSize
case migrateAstronomyPreferences
}

private struct HudMigrationScenario {
Expand Down Expand Up @@ -104,6 +105,10 @@ final class MigrationManager: NSObject {
migrateLocationIconSizeAndCourseIconSize()
defaults.set(true, forKey: MigrationKey.migrateLocationIconSizeAndCourseIconSize.rawValue)
}
if !defaults.bool(forKey: MigrationKey.migrateAstronomyPreferences.rawValue) {
migrateAstronomyPreferences()
defaults.set(true, forKey: MigrationKey.migrateAstronomyPreferences.rawValue)
}
}
}

Expand Down Expand Up @@ -600,6 +605,12 @@ final class MigrationManager: NSObject {
}
}

private func migrateAstronomyPreferences() {
if let plugin = OAPluginsHelper.getPlugin(AstronomyPlugin.self) as? AstronomyPlugin {
plugin.migrateLegacyStarWatcherSettingsIfNeeded()
}
}

// MARK: - Import old versions

func changeJsonMigrationToV2(_ json: [String: String]) -> [String: String] {
Expand All @@ -610,7 +621,8 @@ final class MigrationManager: NSObject {
"top_widget_panel_order": "widget_top_panel_order",
"bottom_widget_panel_order": "widget_bottom_panel_order",
"shared_string_automatic": "driving_region_automatic",
"external_input_device": "selected_external_input_device"
"external_input_device": "selected_external_input_device",
"star_watcher_settings": "astronomy_settings"
]

let changeWidgetIds = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ final class AstroConfigureViewBottomSheet: UIViewController, UISheetPresentation
}

private func configureNavigationBar() {
let imageClose = OAUtilities.resize(UIImage.templateImageNamed("ic_navbar_close"),
let imageClose = OAUtilities.resize(.icNavbarClose,
newSize: CGSize(width: 24, height: 24))?.withRenderingMode(.alwaysTemplate)
let closeButton = UIBarButtonItem(image: imageClose, style: .plain, target: self, action: #selector(closeAction))
closeButton.tintColor = .label
Expand Down
85 changes: 42 additions & 43 deletions Sources/Plugins/Astronomy/AstroUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,18 @@ private final class AstroRedFilterOverlayView: UIView {
super.init(coder: coder)
commonInit()
}

private func commonInit() {
isUserInteractionEnabled = false
backgroundColor = .red
layer.compositingFilter = "multiplyBlendMode"
}


override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = superview?.layer.cornerRadius ?? 0
layer.masksToBounds = layer.cornerRadius > 0
}

private func commonInit() {
isUserInteractionEnabled = false
backgroundColor = .mapNightFilter
layer.compositingFilter = "multiplyBlendMode"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approximately matches the astronomical red filter on Android. On Android, the effect is implemented using ColorMatrixColorFilter, which maps luminance to the red channel. UIKit does not provide a public equivalent of a color matrix filter for arbitrary UIView content, so on iOS we approximate the effect by applying a red overlay with the multiplyBlendMode compositing filter.

}
}

enum AstroRedFilter {
Expand Down Expand Up @@ -111,6 +111,17 @@ enum AstroRedFilter {
}

enum AstroUtils {
struct Twilight {
let sunrise: Date?
let sunset: Date?
let civilDawn: Date?
let civilDusk: Date?
let nauticalDawn: Date?
let nauticalDusk: Date?
let astroDawn: Date?
let astroDusk: Date?
}

private static let customStarLock = NSLock()

static let solarSystemWikidataIds: [String: Body] = [
Expand All @@ -126,17 +137,6 @@ enum AstroUtils {
"Q339": Body.pluto
]

struct Twilight {
let sunrise: Date?
let sunset: Date?
let civilDawn: Date?
let civilDusk: Date?
let nauticalDawn: Date?
let nauticalDusk: Date?
let astroDawn: Date?
let astroDusk: Date?
}

static func astronomyTime(from date: Date) -> Time {
Time.companion.fromMillisecondsSince1970(millis: Int64(date.timeIntervalSince1970 * 1000.0))
}
Expand Down Expand Up @@ -303,19 +303,6 @@ enum AstroUtils {
return formatter.string(from: date)
}

private static func filterRiseSetDate(_ date: Date?, windowStart: Date?, windowEnd: Date?) -> Date? {
guard let date else {
return nil
}
if let windowStart, date < windowStart {
return nil
}
if let windowEnd, date > windowEnd {
return nil
}
return date
}

static func bodyName(_ body: Body) -> String {
bodyDisplayName(body)
}
Expand Down Expand Up @@ -352,17 +339,17 @@ enum AstroUtils {

static func color(for body: Body) -> UIColor {
if body === Body.sun {
return UIColor(red: 1.0, green: 0.69, blue: 0.20, alpha: 1.0)
return .solarSun
} else if body === Body.moon {
return UIColor(white: 0.88, alpha: 1.0)
return .solarMoon
} else if body === Body.mars {
return UIColor(red: 0.95, green: 0.36, blue: 0.22, alpha: 1.0)
return .solarMars
} else if body === Body.jupiter {
return UIColor(red: 0.95, green: 0.73, blue: 0.48, alpha: 1.0)
return .solarJupiter
} else if body === Body.saturn {
return UIColor(red: 0.95, green: 0.82, blue: 0.52, alpha: 1.0)
return .solarSaturn
} else if body === Body.neptune || body === Body.uranus {
return UIColor(red: 0.42, green: 0.73, blue: 1.0, alpha: 1.0)
return .solarUranusNeptune
} else {
return UIColor(red: 0.87, green: 0.90, blue: 1.0, alpha: 1.0)
}
Expand All @@ -371,16 +358,15 @@ enum AstroUtils {
static func color(for type: SkyObjectType, magnitude: Double?) -> UIColor {
switch type {
case .STAR:
let brightness = max(0.45, min(1.0, 1.0 - ((magnitude ?? 2.0) / 8.0)))
return UIColor(red: brightness, green: brightness, blue: 1.0, alpha: 1.0)
return .starDot
case .GALAXY, .GALAXY_CLUSTER:
return UIColor(red: 0.52, green: 0.74, blue: 1.0, alpha: 1.0)
return .deepSkyGalaxyDot
case .NEBULA:
return UIColor(red: 0.85, green: 0.45, blue: 0.95, alpha: 1.0)
return .deepSkyNebulaDot
case .OPEN_CLUSTER, .GLOBULAR_CLUSTER:
return UIColor(red: 0.50, green: 0.95, blue: 0.78, alpha: 1.0)
return .deepSkyClusterDot
case .BLACK_HOLE:
return UIColor(red: 0.95, green: 0.45, blue: 0.35, alpha: 1.0)
return .deepSkyBlackHoleDot
case .CONSTELLATION:
return UIColor(red: 0.80, green: 0.86, blue: 1.0, alpha: 1.0)
case .SUN, .MOON, .PLANET:
Expand Down Expand Up @@ -478,4 +464,17 @@ enum AstroUtils {
formatter.timeStyle = .short
return formatter.string(from: date)
}

private static func filterRiseSetDate(_ date: Date?, windowStart: Date?, windowEnd: Date?) -> Date? {
guard let date else {
return nil
}
if let windowStart, date < windowStart {
return nil
}
if let windowEnd, date > windowEnd {
return nil
}
return date
}
}
45 changes: 41 additions & 4 deletions Sources/Plugins/Astronomy/AstronomyPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,50 @@

import UIKit

@objc(AstronomyPlugin)
final class AstronomyPlugin: OAPlugin {
let dataProvider: AstroDataDbProvider
@objc final class AstronomyPlugin: OAPlugin {
private enum PreferenceId {
static let settings = "astronomy_settings"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle Android legacy star_watcher_settings too. Android migrates it to astronomy_settings, and this key may exist in backup/cloud exports. Since this setting is now cross-platform, iOS should register star_watcher_settings as profile/shared and migrate its value to astronomy_settings when the new pref is empty.

static let legacySettings = "star_watcher_settings"
static let recent = "astronomy_recently_viewed"
}

let dataProvider = AstroDataDbProvider()

var astroSettings: AstronomyPluginSettings { astronomySettingsStorage }
var recentSearchChips: [StarMapRecentChip] = []

private let settingsPref: OACommonString = OAAppSettings.sharedManager()
.registerStringPreference(PreferenceId.settings, defValue: "")
.makeProfile()
.makeShared()

private let legacySettingsPref: OACommonString = OAAppSettings.sharedManager()
.registerStringPreference(PreferenceId.legacySettings, defValue: "")
.makeProfile()

private let recentPref: OACommonString = OAAppSettings.sharedManager()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this also configured as .makeGlobal().makeShared() on Android?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Android, they are stored only in RAM, for a single session. On iOS, they need to be saved across sessions and shared among all profiles.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the logic differ from Android?

.registerStringPreference(PreferenceId.recent, defValue: "")
.makeGlobal()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.makeGlobal() ?


private lazy var astronomySettingsStorage = AstronomyPluginSettings(settingsPref: settingsPref, recentPref: recentPref)

override init() {
dataProvider = AstroDataDbProvider()
super.init()
recentSearchChips = astronomySettingsStorage.recentChips()
}

func saveRecentSearchChips() {
astronomySettingsStorage.setRecentChips(recentSearchChips)
}

func migrateLegacyStarWatcherSettingsIfNeeded() {
for appMode in OAApplicationMode.allPossibleValues() {
guard legacySettingsPref.isSet(for: appMode), !settingsPref.isSet(for: appMode) else {
continue
}
settingsPref.set(legacySettingsPref.get(appMode), mode: appMode)
}
astronomySettingsStorage.reloadFromPreference()
}

override func getId() -> String? {
Expand Down
Loading