Skip to content

Commit

Permalink
Merge pull request #4289 from osmandapp/fix_cloud_4.9
Browse files Browse the repository at this point in the history
Fix cloud 4.9
  • Loading branch information
vshcherb authored Jan 14, 2025
2 parents 0a625c1 + da3da7a commit 009eb36
Show file tree
Hide file tree
Showing 74 changed files with 1,099 additions and 852 deletions.
16 changes: 10 additions & 6 deletions OsmAnd.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@
46D38A9F29C39B0F000AAE0C /* OAProfilesGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 46D38A9E29C39AE8000AAE0C /* OAProfilesGroup.m */; };
46D38AA229C39D7C000AAE0C /* OARoutingFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 46D38AA129C39D42000AAE0C /* OARoutingFile.m */; };
46D439142AA89C1F001D85FF /* DestinationsListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D439132AA89C1F001D85FF /* DestinationsListViewController.swift */; };
46D5E41A2D31A3F000428227 /* BackupUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46D5E4192D31A3EC00428227 /* BackupUtils.swift */; };
46D6CF4C28452F5D007A43F9 /* OATitleDescriptionBigIconCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 46D6CF4B28452F5D007A43F9 /* OATitleDescriptionBigIconCell.xib */; };
46DB0A632C5CEA8F001356D5 /* ConcurrentArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46DB0A622C5CEA8F001356D5 /* ConcurrentArray.swift */; };
46DB0A7E2C5D1602001356D5 /* GradientUiHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46DB0A7D2C5D1602001356D5 /* GradientUiHelper.swift */; };
Expand Down Expand Up @@ -2989,7 +2990,7 @@
DAEC06042296CA7C00045298 /* ic_navbar_close@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAEC06012296CA7B00045298 /* ic_navbar_close@2x.png */; };
DAEC06062296CA7C00045298 /* ic_navbar_close@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAEC06022296CA7C00045298 /* ic_navbar_close@3x.png */; };
DAECA4FA26CFE62600241B0B /* OABaseWidgetView.m in Sources */ = {isa = PBXBuildFile; fileRef = DAECA4F926CFE62600241B0B /* OABaseWidgetView.m */; };
DAEDAAA12865A0F100CE54D0 /* OABackupInfoGenerationTask.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEDAAA02865A0F100CE54D0 /* OABackupInfoGenerationTask.m */; };
DAEDAAA12865A0F100CE54D0 /* OAGenerateBackupInfoTask.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEDAAA02865A0F100CE54D0 /* OAGenerateBackupInfoTask.m */; };
DAF2F804254825BA00967935 /* map_plan_route_point_movable@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAF2F7FB254825B600967935 /* map_plan_route_point_movable@3x.png */; };
DAF2F808254825BA00967935 /* map_plan_route_point_normal@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAF2F7FD254825B700967935 /* map_plan_route_point_normal@3x.png */; };
DAF2F80C254825BA00967935 /* map_plan_route_point_selected@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAF2F7FF254825B800967935 /* map_plan_route_point_selected@2x.png */; };
Expand Down Expand Up @@ -4193,6 +4194,7 @@
46D38AA029C39D36000AAE0C /* OARoutingFile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OARoutingFile.h; sourceTree = "<group>"; };
46D38AA129C39D42000AAE0C /* OARoutingFile.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OARoutingFile.m; sourceTree = "<group>"; };
46D439132AA89C1F001D85FF /* DestinationsListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DestinationsListViewController.swift; sourceTree = "<group>"; };
46D5E4192D31A3EC00428227 /* BackupUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupUtils.swift; sourceTree = "<group>"; };
46D6CF4B28452F5D007A43F9 /* OATitleDescriptionBigIconCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = OATitleDescriptionBigIconCell.xib; sourceTree = "<group>"; };
46DB0A622C5CEA8F001356D5 /* ConcurrentArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConcurrentArray.swift; sourceTree = "<group>"; };
46DB0A7D2C5D1602001356D5 /* GradientUiHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientUiHelper.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -7494,8 +7496,8 @@
DAEC06022296CA7C00045298 /* ic_navbar_close@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "ic_navbar_close@3x.png"; path = "Resources/Icons/ic_navbar_close@3x.png"; sourceTree = "<group>"; };
DAECA4F826CFE62600241B0B /* OABaseWidgetView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OABaseWidgetView.h; sourceTree = "<group>"; };
DAECA4F926CFE62600241B0B /* OABaseWidgetView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OABaseWidgetView.m; sourceTree = "<group>"; };
DAEDAA9F2865A0F100CE54D0 /* OABackupInfoGenerationTask.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OABackupInfoGenerationTask.h; sourceTree = "<group>"; };
DAEDAAA02865A0F100CE54D0 /* OABackupInfoGenerationTask.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OABackupInfoGenerationTask.m; sourceTree = "<group>"; };
DAEDAA9F2865A0F100CE54D0 /* OAGenerateBackupInfoTask.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OAGenerateBackupInfoTask.h; sourceTree = "<group>"; };
DAEDAAA02865A0F100CE54D0 /* OAGenerateBackupInfoTask.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OAGenerateBackupInfoTask.m; sourceTree = "<group>"; };
DAF2F7FB254825B600967935 /* map_plan_route_point_movable@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "map_plan_route_point_movable@3x.png"; path = "Resources/Icons/map_plan_route_point_movable@3x.png"; sourceTree = "<group>"; };
DAF2F7FD254825B700967935 /* map_plan_route_point_normal@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "map_plan_route_point_normal@3x.png"; path = "Resources/Icons/map_plan_route_point_normal@3x.png"; sourceTree = "<group>"; };
DAF2F7FF254825B800967935 /* map_plan_route_point_selected@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "map_plan_route_point_selected@2x.png"; path = "Resources/Icons/map_plan_route_point_selected@2x.png"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -13446,6 +13448,7 @@
DACF784127E343FF00A8A218 /* Backup */ = {
isa = PBXGroup;
children = (
46D5E4192D31A3EC00428227 /* BackupUtils.swift */,
DAA9F44B27EC9E99002BB1A8 /* Commands */,
DA4ABED22876D98D00B996EF /* LocalBackup */,
4657490F2B68129B0006046B /* BackupUiUtils.swift */,
Expand All @@ -13461,8 +13464,8 @@
DAAC0EC22801885800867D35 /* OABackupImporter.m */,
DA775B8B27E618070081B9C1 /* OABackupInfo.h */,
DA775B8C27E618070081B9C1 /* OABackupInfo.mm */,
DAEDAA9F2865A0F100CE54D0 /* OABackupInfoGenerationTask.h */,
DAEDAAA02865A0F100CE54D0 /* OABackupInfoGenerationTask.m */,
DAEDAA9F2865A0F100CE54D0 /* OAGenerateBackupInfoTask.h */,
DAEDAAA02865A0F100CE54D0 /* OAGenerateBackupInfoTask.m */,
DAA9F45227ECADF8002BB1A8 /* OABackupListeners.h */,
DAA9F45327ECADF8002BB1A8 /* OABackupListeners.m */,
DA5F77B428742E85000A2BFF /* OABackupStatus.h */,
Expand Down Expand Up @@ -16225,7 +16228,7 @@
46A5A3872CA5DCDA00A206C2 /* ActionAddTerrainColorSchemeViewController.swift in Sources */,
46220B702AD6D6F2006C3248 /* OABaseEditorViewController.mm in Sources */,
DA5A855B26C563A900F274C7 /* OAWorldRegion.mm in Sources */,
DAEDAAA12865A0F100CE54D0 /* OABackupInfoGenerationTask.m in Sources */,
DAEDAAA12865A0F100CE54D0 /* OAGenerateBackupInfoTask.m in Sources */,
32839A372AF0F911007B5057 /* WikiImageCacheHelper.swift in Sources */,
4663AB412951CB6200D9781E /* OAInputTableViewCell.m in Sources */,
DA5A83DD26C563A800F274C7 /* OAFavoriteListViewController.mm in Sources */,
Expand Down Expand Up @@ -16978,6 +16981,7 @@
DA5A815F26C563A700F274C7 /* OALiveMonitoringHelper.m in Sources */,
DA5A84B426C563A900F274C7 /* OAInstallMapillaryBottomSheetViewController.mm in Sources */,
46964F762C345448007F3938 /* ColorPaletteHelper.swift in Sources */,
46D5E41A2D31A3F000428227 /* BackupUtils.swift in Sources */,
DA5A839A26C563A800F274C7 /* OALocalResourceInfoCell.m in Sources */,
DA5A823926C563A700F274C7 /* OAOsmAccountSettingsViewController.m in Sources */,
DA5A815C26C563A700F274C7 /* OAPlugin.mm in Sources */,
Expand Down
1 change: 1 addition & 0 deletions Resources/Localizations/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,7 @@
"res_world_map" = "World map";
"shared_string_world" = "World";
"download_tab_updates" = "Updates";
"download_tab_conflicts" = "Unresolved";
"res_worldwide" = "Worldwide";
"res_region_map" = "Region map";
"res_updates_avail" = "Updates available";
Expand Down
5 changes: 5 additions & 0 deletions Sources/AppHost/OsmAndAppImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,11 @@ - (void) loadRoutingFiles
});
}

- (void)rescanUnmanagedStoragePaths
{
_resourcesManager->rescanUnmanagedStoragePaths();
}

- (MAP_STR_STR) getDefaultAttributes
{
MAP_STR_STR defaultAttributes;
Expand Down
1 change: 1 addition & 0 deletions Sources/AppHost/OsmAndAppProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
- (void) checkAndDownloadWeatherForecastsUpdates;

- (void) loadRoutingFiles;
- (void) rescanUnmanagedStoragePaths;

- (NSString *) favoritesStorageFilename:(NSString *)groupName;
- (NSString *) getGroupFileName:(NSString *)groupName;
Expand Down
2 changes: 1 addition & 1 deletion Sources/AppHost/SceneDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ - (BOOL)handleIncomingOsmAndCloudURL:(NSURL *)url

if ([vc isKindOfClass:OACloudAccountVerificationViewController.class])
{
if ([OABackupHelper isTokenValid:tokenParam])
if ([BackupUtils isTokenValid:tokenParam])
{
[OABackupHelper.sharedInstance registerDevice:tokenParam];
}
Expand Down
267 changes: 267 additions & 0 deletions Sources/Backup/BackupUtils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
//
// BackupUtils.swift
// OsmAnd
//
// Created by Skalii on 10.01.2025.
// Copyright © 2025 OsmAnd. All rights reserved.
//

import Foundation

@objcMembers
final class BackupUtils: NSObject {

static let backupTypePrefix = "backup_type_"
static let versionHistoryPrefix = "save_version_history_"

static func setLastModifiedTime(_ name: String) {
setLastModifiedTime(name, lastModifiedTime: Int(NSDate().timeIntervalSince1970))
}

static func setLastModifiedTime(_ name: String, lastModifiedTime: Int) {
OABackupDbHelper.sharedDatabase().setLastModifiedTime(name, lastModifiedTime: Int(lastModifiedTime))
}

static func getLastModifiedTime(_ name: String) -> Int {
OABackupDbHelper.sharedDatabase().getLastModifiedTime(name)
}

static func isTokenValid(_ token: String) -> Bool {
token.range(of: "^[0-9]+$", options: .regularExpression) != nil
}

static func getItemsForRestore(_ info: OABackupInfo?,
settingsItems: [OASettingsItem]) -> [OASettingsItem] {
guard let info, let filtered = info.filteredFilesToDownload as? [OARemoteFile] else { return [] }

var items = [OASettingsItem]()
let restoreItems = getRemoteFilesSettingsItems(settingsItems,
remoteFiles: filtered,
infoFiles: false)
for restoreItem in restoreItems.values {
if let settingsItem = restoreItem as? OACollectionSettingsItem<AnyObject> {
settingsItem.processDuplicateItems()
settingsItem.shouldReplace = true
}
items.append(restoreItem)
}
items.sort { $0.lastModifiedTime > $1.lastModifiedTime }
return items
}

static func getItemsMapForRestore(_ info: OABackupInfo?,
settingsItems: [OASettingsItem]) -> [OARemoteFile: OASettingsItem] {
guard let info, let filtered = info.filteredFilesToDownload as? [OARemoteFile] else { return [OARemoteFile: OASettingsItem]() }

return getRemoteFilesSettingsItems(settingsItems,
remoteFiles: filtered,
infoFiles: false)
}

static func getRemoteFilesSettingsItems(_ items: [OASettingsItem],
remoteFiles: [OARemoteFile],
infoFiles: Bool) -> [OARemoteFile: OASettingsItem] {
var res = [OARemoteFile: OASettingsItem]()
var files = remoteFiles
for item in items {
var processedFiles = [OARemoteFile]()
for file in files {
var name = file.name as NSString
if infoFiles && name.pathExtension == OABackupHelper.info_EXT() {
name = name.deletingPathExtension as NSString
}

if applyItem(item, type: file.type, name: name) {
if file.item == nil {
file.item = item
}
res[file] = item
processedFiles.append(file)
}
}
files.removeAll { processedFiles.contains($0) }
}
return res
}

static func getBackupTypePref(_ type: OAExportSettingsType) -> OACommonBoolean {
OACommonBoolean.withKey("\(backupTypePrefix)\(type.name)", defValue: true).makeGlobal()
}

static func getVersionHistoryTypePref(_ type: OAExportSettingsType) -> OACommonBoolean {
OACommonBoolean.withKey("\(versionHistoryPrefix)\(type.name)", defValue: true).makeGlobal().makeShared()
}

static func applyItem(_ item: OASettingsItem, type: String, name: NSString) -> Bool {
let itemFileName = getItemFileName(item)
let itemTypeName = OASettingsItemType.typeName(item.type)
if itemTypeName == type {
if name.isEqual(to: itemFileName) {
return true
} else if let fileItem = item as? OAFileSettingsItem {
let subtypeFolder = OAFileSettingsItemFileSubtype.getFolderName(fileItem.subtype)
if name.hasPrefix(subtypeFolder) || subtypeFolder.isEmpty {
var isDir: ObjCBool = false
FileManager.default.fileExists(atPath: fileItem.filePath, isDirectory: &isDir)
if isDir.boolValue, !itemFileName.hasSuffix("/") {
return name.hasPrefix("\(itemFileName)/")
} else {
return name.hasPrefix(itemFileName)
}
}
}
}
return false
}

static func getItemFileName(_ item: OASettingsItem) -> String {
var fileName: String
if let fileItem = item as? OAFileSettingsItem {
fileName = getFileItemName(fileItem)
} else {
fileName = item.fileName
if fileName.isEmpty {
fileName = item.defaultFileName
}
}
if !fileName.isEmpty, fileName.first == "/" {
fileName.removeFirst()
}
return fileName
}

static func getFileItemName(_ fileSettingsItem: OAFileSettingsItem) -> String {
getFileItemName(nil, fileSettingsItem: fileSettingsItem)
}

static func getFileItemName(_ filePath: String?,
fileSettingsItem: OAFileSettingsItem) -> String {
let subtypeFolder = OAFileSettingsItemFileSubtype.getFolder(fileSettingsItem.subtype)
var fileName: String
let filePath = filePath ?? fileSettingsItem.filePath

if subtypeFolder.isEmpty {
fileName = filePath.lastPathComponent()
} else if fileSettingsItem.subtype == .subtypeGpx {
fileName = filePath.replacingOccurrences(of: "\(subtypeFolder)/", with: "")
} else if OAFileSettingsItemFileSubtype.isMap(fileSettingsItem.subtype) {
fileName = filePath.lastPathComponent()
} else {
let index = filePath.index(of: subtypeFolder.lastPathComponent())
if index >= 0 {
fileName = filePath.substring(from: Int(index))
} else {
fileName = filePath.lastPathComponent()
}
}

if !fileName.isEmpty, fileName.first == "/" {
fileName.removeFirst()
}

return fileName
}

static func isLimitedFilesCollectionItem(_ item: OAFileSettingsItem) -> Bool {
item.subtype == .subtypeVoice
}

static func isDefaultObfMap(_ settingsItem: OAFileSettingsItem,
fileName: String) -> Bool {
if (OAFileSettingsItemFileSubtype.isMap(settingsItem.subtype)) {
return isObfMapExistsOnServer(fileName)
}
return false
}

static func isObfMapExistsOnServer(_ name: String) -> Bool {
var exists = false
let params = [
"name": name,
"type": "file"
]

let operationLog = OAOperationLog(operationName: "isObfMapExistsOnServer", debug: true)
operationLog?.startOperation(name)

OANetworkUtilities.sendRequest(withUrl: "https://osmand.net/userdata/check-file-on-server",
params: params,
post: false,
async: false) { data, response, _ in
var status: Int32
var message: String

guard let data, let httpResponse = response as? HTTPURLResponse else {
status = STATUS_SERVER_ERROR
message = "Check obf map on server error: invalid response"
operationLog?.finishOperation("(\(status)): \(message)")
return
}

let result = String(data: data, encoding: .utf8) ?? ""
var backupError: OABackupError?
if httpResponse.statusCode != 200 {
backupError = OABackupError(error: result)
message = "Check obf map on server error: \(String(describing: backupError?.toString()))"
status = STATUS_SERVER_ERROR
} else if !result.isEmpty {
do {
if let resultJson = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any],
let fileStatus = resultJson["status"] as? String {
exists = fileStatus == "present"
status = STATUS_SUCCESS
message = "\(name) exist: \(exists)"
} else {
message = "Send code error: unknown"
status = STATUS_SERVER_ERROR
}
} catch {
message = "Check obf map on server error: json parsing"
status = STATUS_PARSE_JSON_ERROR
}
} else {
message = "Check obf map on server error: empty response"
status = STATUS_EMPTY_RESPONSE_ERROR
}
operationLog?.finishOperation("(\(status)): \(message)")
}

return exists
}

static func updateCacheForItems(_ items: [OASettingsItem]) {
var updateIndexes = false
var updateRouting = false
var updateRenderers = false
var updatePoiFilters = false
var updateColorPalette = false

for item in items {
if let fileItem = item as? OAFileSettingsItem {
updateIndexes = updateIndexes || OAFileSettingsItemFileSubtype.isMap(fileItem.subtype)
updateRouting = updateRouting || .subtypeRoutingConfig == fileItem.subtype
updateRenderers = updateRenderers || .subtypeRenderingStyle == fileItem.subtype
updateColorPalette = updateColorPalette || .subtypeColorPalette == fileItem.subtype
} else if item is OAPoiUiFilterSettingsItem || item is OAProfileSettingsItem {
updatePoiFilters = true
}
}
let app = OsmAndApp.swiftInstance()
if updateColorPalette {
app?.updateGpxTracksOnMapObservable.notifyEvent()
}
if updateIndexes {
app?.rescanUnmanagedStoragePaths()
app?.localResourcesChangedObservable.notifyEvent()
}
if updateRouting {
app?.loadRoutingFiles()
}
if updateRenderers {
OARendererRegistry.getExternalRenderers()
}
if updatePoiFilters {
OAPOIFiltersHelper.sharedInstance().loadSelectedPoiFilters()
}
}
}
Loading

0 comments on commit 009eb36

Please sign in to comment.