refactor oscprofilemanager to swift
This commit is contained in:
+2
-1
@@ -4,6 +4,7 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
Build
|
Build
|
||||||
DerivedData
|
DerivedData
|
||||||
|
build-home/
|
||||||
*.xccheckout
|
*.xccheckout
|
||||||
.github
|
.github
|
||||||
README.md
|
README.md
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
84351B0E2C29ACCB00A77989 /* LayoutOnScreenControls.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B072C29ACCA00A77989 /* LayoutOnScreenControls.m */; };
|
84351B0E2C29ACCB00A77989 /* LayoutOnScreenControls.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B072C29ACCA00A77989 /* LayoutOnScreenControls.m */; };
|
||||||
84351B0F2C29ACCB00A77989 /* OnScreenButtonState.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B092C29ACCA00A77989 /* OnScreenButtonState.m */; };
|
84351B0F2C29ACCB00A77989 /* OnScreenButtonState.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B092C29ACCA00A77989 /* OnScreenButtonState.m */; };
|
||||||
84351B102C29ACCB00A77989 /* OSCProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B0A2C29ACCA00A77989 /* OSCProfile.m */; };
|
84351B102C29ACCB00A77989 /* OSCProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B0A2C29ACCA00A77989 /* OSCProfile.m */; };
|
||||||
84351B112C29ACCB00A77989 /* OSCProfilesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B0B2C29ACCB00A77989 /* OSCProfilesManager.m */; };
|
84351B112C29ACCB00A77989 /* OSCProfilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1D4E0A22FBBBBCC00112233 /* OSCProfilesManager.swift */; };
|
||||||
84351B2D2C29AD6100A77989 /* ToolBarContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B292C29AD6000A77989 /* ToolBarContainerView.m */; };
|
84351B2D2C29AD6100A77989 /* ToolBarContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B292C29AD6000A77989 /* ToolBarContainerView.m */; };
|
||||||
84351B5D2C29ADBE00A77989 /* ProfileTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84351B5B2C29ADBE00A77989 /* ProfileTableViewCell.xib */; };
|
84351B5D2C29ADBE00A77989 /* ProfileTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84351B5B2C29ADBE00A77989 /* ProfileTableViewCell.xib */; };
|
||||||
843667F02D9D7173004A7D7F /* widgetTemplates.bin in Resources */ = {isa = PBXBuildFile; fileRef = 843667EF2D9D7173004A7D7F /* widgetTemplates.bin */; };
|
843667F02D9D7173004A7D7F /* widgetTemplates.bin in Resources */ = {isa = PBXBuildFile; fileRef = 843667EF2D9D7173004A7D7F /* widgetTemplates.bin */; };
|
||||||
@@ -216,10 +216,9 @@
|
|||||||
84203F222C5F24C00032EEED /* OnScreenWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnScreenWidgetView.swift; sourceTree = "<group>"; };
|
84203F222C5F24C00032EEED /* OnScreenWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnScreenWidgetView.swift; sourceTree = "<group>"; };
|
||||||
84351B062C29ACCA00A77989 /* OnScreenButtonState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnScreenButtonState.h; sourceTree = "<group>"; };
|
84351B062C29ACCA00A77989 /* OnScreenButtonState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnScreenButtonState.h; sourceTree = "<group>"; };
|
||||||
84351B072C29ACCA00A77989 /* LayoutOnScreenControls.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LayoutOnScreenControls.m; sourceTree = "<group>"; };
|
84351B072C29ACCA00A77989 /* LayoutOnScreenControls.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LayoutOnScreenControls.m; sourceTree = "<group>"; };
|
||||||
84351B082C29ACCA00A77989 /* OSCProfilesManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSCProfilesManager.h; sourceTree = "<group>"; };
|
|
||||||
84351B092C29ACCA00A77989 /* OnScreenButtonState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OnScreenButtonState.m; sourceTree = "<group>"; };
|
84351B092C29ACCA00A77989 /* OnScreenButtonState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OnScreenButtonState.m; sourceTree = "<group>"; };
|
||||||
84351B0A2C29ACCA00A77989 /* OSCProfile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OSCProfile.m; sourceTree = "<group>"; };
|
84351B0A2C29ACCA00A77989 /* OSCProfile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OSCProfile.m; sourceTree = "<group>"; };
|
||||||
84351B0B2C29ACCB00A77989 /* OSCProfilesManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OSCProfilesManager.m; sourceTree = "<group>"; };
|
A1D4E0A22FBBBBCC00112233 /* OSCProfilesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSCProfilesManager.swift; sourceTree = "<group>"; };
|
||||||
84351B0C2C29ACCB00A77989 /* LayoutOnScreenControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutOnScreenControls.h; sourceTree = "<group>"; };
|
84351B0C2C29ACCB00A77989 /* LayoutOnScreenControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutOnScreenControls.h; sourceTree = "<group>"; };
|
||||||
84351B0D2C29ACCB00A77989 /* OSCProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSCProfile.h; sourceTree = "<group>"; };
|
84351B0D2C29ACCB00A77989 /* OSCProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSCProfile.h; sourceTree = "<group>"; };
|
||||||
84351B292C29AD6000A77989 /* ToolBarContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ToolBarContainerView.m; sourceTree = "<group>"; };
|
84351B292C29AD6000A77989 /* ToolBarContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ToolBarContainerView.m; sourceTree = "<group>"; };
|
||||||
@@ -492,8 +491,7 @@
|
|||||||
84351B092C29ACCA00A77989 /* OnScreenButtonState.m */,
|
84351B092C29ACCA00A77989 /* OnScreenButtonState.m */,
|
||||||
84351B0D2C29ACCB00A77989 /* OSCProfile.h */,
|
84351B0D2C29ACCB00A77989 /* OSCProfile.h */,
|
||||||
84351B0A2C29ACCA00A77989 /* OSCProfile.m */,
|
84351B0A2C29ACCA00A77989 /* OSCProfile.m */,
|
||||||
84351B082C29ACCA00A77989 /* OSCProfilesManager.h */,
|
A1D4E0A22FBBBBCC00112233 /* OSCProfilesManager.swift */,
|
||||||
84351B0B2C29ACCB00A77989 /* OSCProfilesManager.m */,
|
|
||||||
);
|
);
|
||||||
path = CustomOSC;
|
path = CustomOSC;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1159,7 +1157,7 @@
|
|||||||
FB53E1431BE5DC4400CD6ECE /* IdManager.m in Sources */,
|
FB53E1431BE5DC4400CD6ECE /* IdManager.m in Sources */,
|
||||||
189AD29A2DE7446000E24B88 /* HostCollectionViewController.m in Sources */,
|
189AD29A2DE7446000E24B88 /* HostCollectionViewController.m in Sources */,
|
||||||
9897B6A1221260EF00966419 /* VoidController.m in Sources */,
|
9897B6A1221260EF00966419 /* VoidController.m in Sources */,
|
||||||
84351B112C29ACCB00A77989 /* OSCProfilesManager.m in Sources */,
|
84351B112C29ACCB00A77989 /* OSCProfilesManager.swift in Sources */,
|
||||||
FB89462919F646E200339C8A /* mkcert.c in Sources */,
|
FB89462919F646E200339C8A /* mkcert.c in Sources */,
|
||||||
FB9AFD281A7C84ED00872C98 /* HttpResponse.m in Sources */,
|
FB9AFD281A7C84ED00872C98 /* HttpResponse.m in Sources */,
|
||||||
FB89463019F646E200339C8A /* StreamConfiguration.m in Sources */,
|
FB89463019F646E200339C8A /* StreamConfiguration.m in Sources */,
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#import "LayoutOnScreenControls.h"
|
#import "LayoutOnScreenControls.h"
|
||||||
#import "OnScreenButtonState.h"
|
#import "OnScreenButtonState.h"
|
||||||
#import "OSCProfilesManager.h"
|
|
||||||
#import "VoidLink-Swift.h"
|
#import "VoidLink-Swift.h"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ static CGRect layoutViewBounds;
|
|||||||
if(profile && targetProfiles.count > 1) [targetProfiles removeObject:profile];
|
if(profile && targetProfiles.count > 1) [targetProfiles removeObject:profile];
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
|
NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
|
||||||
bool importPencilProProfile = ([bundleId isEqualToString:@"com.voidlink.iOS"]
|
bool importPencilProProfile = ([bundleId isEqualToString:@"com.voidlink.iOS"]
|
||||||
|| [bundleId isEqualToString:@"com.voidlinkextreme.iOS"]
|
|| [bundleId isEqualToString:@"com.voidlinkextreme.iOS"]
|
||||||
@@ -179,7 +180,8 @@ static CGRect layoutViewBounds;
|
|||||||
if(!importPencilProProfile && [GenericUtils isIPad]){
|
if(!importPencilProProfile && [GenericUtils isIPad]){
|
||||||
[profilesEncoded removeObjectAtIndex:1];
|
[profilesEncoded removeObjectAtIndex:1];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if(targetProfiles.count > 0) [targetProfiles removeObjectAtIndex:0];
|
if(targetProfiles.count > 0) [targetProfiles removeObjectAtIndex:0];
|
||||||
NSMutableArray* localEncodedPofiles = [self encodedProfilesFromArray:targetProfiles];
|
NSMutableArray* localEncodedPofiles = [self encodedProfilesFromArray:targetProfiles];
|
||||||
[profilesEncoded addObjectsFromArray:localEncodedPofiles];
|
[profilesEncoded addObjectsFromArray:localEncodedPofiles];
|
||||||
@@ -281,6 +283,18 @@ static CGRect layoutViewBounds;
|
|||||||
return profilesDecoded;
|
return profilesDecoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSMutableArray *) decodeProfilesFrom:(NSMutableArray* )profilesEncoded {
|
||||||
|
NSSet *classes = [NSSet setWithObjects:[NSString class], [NSMutableData class], [NSMutableArray class], [OSCProfile class], [OnScreenButtonState class], nil];
|
||||||
|
NSMutableArray *profilesDecoded = [[NSMutableArray alloc] init];
|
||||||
|
OSCProfile *profileDecoded;
|
||||||
|
for (NSData *profileEncoded in profilesEncoded) {
|
||||||
|
|
||||||
|
profileDecoded = [NSKeyedUnarchiver unarchivedObjectOfClasses: classes fromData:profileEncoded error: nil];
|
||||||
|
[profilesDecoded addObject: profileDecoded];
|
||||||
|
}
|
||||||
|
return profilesDecoded;
|
||||||
|
}
|
||||||
|
|
||||||
- (OSCProfile *) getSelectedProfile {
|
- (OSCProfile *) getSelectedProfile {
|
||||||
// NSLog(@"getAllProfiles test %f", CACurrentMediaTime());
|
// NSLog(@"getAllProfiles test %f", CACurrentMediaTime());
|
||||||
NSMutableArray *profiles = [self getAllProfiles];
|
NSMutableArray *profiles = [self getAllProfiles];
|
||||||
|
|||||||
@@ -0,0 +1,543 @@
|
|||||||
|
//
|
||||||
|
// OSCProfilesManager.m -> OSCProfilesManager.swift
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Long Le on 1/1/23.
|
||||||
|
// Copyright © 2023 Moonlight Game Streaming Project. All rights reserved.
|
||||||
|
//
|
||||||
|
// Modified by True砖家 since 2024.6.24
|
||||||
|
// Copyright © 2024 True砖家 @ Bilibili. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@objcMembers
|
||||||
|
class OSCProfilesManager: NSObject {
|
||||||
|
private static let profilesDefaultsKey = "OSCProfiles"
|
||||||
|
private static let widgetProfileUpdatedKey = "widgetProfileUpdated-20260605"
|
||||||
|
|
||||||
|
private static var sharedInstance: OSCProfilesManager?
|
||||||
|
private static var onScreenWidgetViews: NSMutableSet?
|
||||||
|
private static var layoutViewBounds: CGRect = .zero
|
||||||
|
|
||||||
|
var currentProfiles: NSMutableArray = []
|
||||||
|
var widgetSizeTransition: WidgetSizeTransition = .keepWidgetSize
|
||||||
|
|
||||||
|
@objc(sharedManager:)
|
||||||
|
class func sharedManager(_ viewBounds: CGRect) -> OSCProfilesManager {
|
||||||
|
if viewBounds != .zero {
|
||||||
|
layoutViewBounds = viewBounds
|
||||||
|
}
|
||||||
|
if let sharedInstance {
|
||||||
|
return sharedInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
let manager = OSCProfilesManager()
|
||||||
|
sharedInstance = manager
|
||||||
|
return manager
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc(setOnScreenWidgetViewsSet:)
|
||||||
|
class func setOnScreenWidgetViewsSet(_ set: NSMutableSet) {
|
||||||
|
onScreenWidgetViews = set
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc(setLayoutViewBounds:)
|
||||||
|
class func setLayoutViewBounds(_ bounds: CGRect) {
|
||||||
|
layoutViewBounds = bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
private static let profileCodingClasses: [AnyClass] = [
|
||||||
|
NSString.self,
|
||||||
|
NSMutableData.self,
|
||||||
|
NSMutableArray.self,
|
||||||
|
OSCProfile.self,
|
||||||
|
OnScreenButtonState.self,
|
||||||
|
]
|
||||||
|
|
||||||
|
private static let buttonStateCodingClasses: [AnyClass] = [
|
||||||
|
NSString.self,
|
||||||
|
OnScreenButtonState.self,
|
||||||
|
NSSet.self,
|
||||||
|
NSNumber.self,
|
||||||
|
]
|
||||||
|
|
||||||
|
private func oscProfile(withName name: String) -> OSCProfile? {
|
||||||
|
let profiles = getAllProfiles()
|
||||||
|
for case let profile as OSCProfile in profiles where profile.name == name {
|
||||||
|
return profile
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
private func encodedProfiles(from profiles: NSMutableArray) -> NSMutableArray {
|
||||||
|
let profilesEncoded = NSMutableArray()
|
||||||
|
for case let profile as OSCProfile in profiles {
|
||||||
|
if let profileEncoded = try? NSKeyedArchiver.archivedData(withRootObject: profile, requiringSecureCoding: true) {
|
||||||
|
profilesEncoded.add(profileEncoded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return profilesEncoded
|
||||||
|
}
|
||||||
|
|
||||||
|
private func persistProfiles(_ profiles: NSMutableArray) {
|
||||||
|
let profilesEncoded = encodedProfiles(from: profiles)
|
||||||
|
persistEncodedProfiles(profilesEncoded)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func persistEncodedProfiles(_ profilesEncoded: NSMutableArray) {
|
||||||
|
guard let data = try? NSKeyedArchiver.archivedData(withRootObject: profilesEncoded, requiringSecureCoding: true) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let defaults = UserDefaults.standard
|
||||||
|
defaults.set(data, forKey: Self.profilesDefaultsKey)
|
||||||
|
defaults.synchronize()
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteCurrentSelectedProfile() {
|
||||||
|
let profiles = getAllProfiles()
|
||||||
|
var selectedIndex = getIndexOfSelectedProfile()
|
||||||
|
|
||||||
|
if selectedIndex != 0 {
|
||||||
|
profiles.removeObject(at: selectedIndex)
|
||||||
|
} else {
|
||||||
|
NSLog("Default profile!")
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedIndex -= 1
|
||||||
|
if selectedIndex < 0 {
|
||||||
|
selectedIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if let newSelectedProfile = profiles[safe: selectedIndex] as? OSCProfile {
|
||||||
|
newSelectedProfile.isSelected = true
|
||||||
|
}
|
||||||
|
|
||||||
|
persistProfiles(profiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func replaceSelectedProfile(with newProfile: OSCProfile, overwriteDefault: Bool) {
|
||||||
|
let profiles = getAllProfiles()
|
||||||
|
var index = 0
|
||||||
|
|
||||||
|
for case let profile as OSCProfile in profiles where profile.isSelected {
|
||||||
|
index = profiles.index(of: profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
if index > 0 || overwriteDefault {
|
||||||
|
profiles.replaceObject(at: index, with: newProfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
persistProfiles(profiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc(replaceProfile:withProfile:)
|
||||||
|
func replaceProfile(_ oldProfile: OSCProfile, withProfile newProfile: OSCProfile) {
|
||||||
|
let profiles = getAllProfiles()
|
||||||
|
|
||||||
|
for case let profile as OSCProfile in profiles {
|
||||||
|
profile.isSelected = false
|
||||||
|
}
|
||||||
|
|
||||||
|
newProfile.isSelected = true
|
||||||
|
|
||||||
|
var index = 0
|
||||||
|
for i in 0 ..< profiles.count {
|
||||||
|
guard let profile = profiles[i] as? OSCProfile else { continue }
|
||||||
|
if profile.name == oldProfile.name {
|
||||||
|
index = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
profiles.removeObject(at: index)
|
||||||
|
profiles.insert(newProfile, at: index)
|
||||||
|
persistProfiles(profiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func replace(_ oldProfile: OSCProfile, with newProfile: OSCProfile) {
|
||||||
|
replaceProfile(oldProfile, withProfile: newProfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEncodedProfiles() -> NSMutableArray {
|
||||||
|
guard
|
||||||
|
let profilesArrayEncoded = UserDefaults.standard.object(forKey: Self.profilesDefaultsKey) as? Data,
|
||||||
|
let profilesEncoded = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: Self.profileCodingClasses, from: profilesArrayEncoded) as? NSMutableArray
|
||||||
|
else {
|
||||||
|
return NSMutableArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
return profilesEncoded
|
||||||
|
}
|
||||||
|
|
||||||
|
func importEncodedProfiles(_ profilesEncoded: NSMutableArray) {
|
||||||
|
let localProfiles = currentProfiles.mutableCopy() as? NSMutableArray ?? NSMutableArray()
|
||||||
|
|
||||||
|
if localProfiles.count > 0 {
|
||||||
|
localProfiles.removeObject(at: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
let profilesDecoded = decodeProfiles(from: profilesEncoded)
|
||||||
|
|
||||||
|
let localProfileNames = Set(
|
||||||
|
localProfiles.compactMap { ($0 as? OSCProfile)?.name }
|
||||||
|
)
|
||||||
|
|
||||||
|
for case let profile as OSCProfile in profilesDecoded {
|
||||||
|
if localProfileNames.contains(profile.name) {
|
||||||
|
profile.name = "\(profile.name)-\(LocalizationHelper.localizedString(forKey:"Restored"))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let importedProfileNames = Set(
|
||||||
|
profilesDecoded.compactMap { ($0 as? OSCProfile)?.name }
|
||||||
|
)
|
||||||
|
|
||||||
|
var localProfilesToRemove: [OSCProfile] = []
|
||||||
|
for case let profile as OSCProfile in localProfiles {
|
||||||
|
if importedProfileNames.contains(profile.name) {localProfilesToRemove.append(profile)}
|
||||||
|
}
|
||||||
|
|
||||||
|
for case let profile as Any in localProfilesToRemove {
|
||||||
|
localProfiles.remove(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
for profile in localProfiles {
|
||||||
|
profilesDecoded.add(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
persistEncodedProfiles(encodedProfiles(from: profilesDecoded))
|
||||||
|
}
|
||||||
|
|
||||||
|
private func isIPhone() -> Bool {
|
||||||
|
UIDevice.current.userInterfaceIdiom == .phone
|
||||||
|
}
|
||||||
|
|
||||||
|
func importDefaultTemplates() {
|
||||||
|
guard let filePath = Bundle.main.path(forResource: isIPhone() ? "widgetTemplatesIPhone" : "widgetTemplates", ofType: "bin") else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let fileData = try Data(contentsOf: URL(fileURLWithPath: filePath), options: .mappedIfSafe)
|
||||||
|
if let profilesEncoded = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSMutableData.self, NSMutableArray.self], from: fileData) as? NSMutableArray {
|
||||||
|
importEncodedProfiles(profilesEncoded)
|
||||||
|
setProfileToSelected(0)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateDefaultTemplates() {
|
||||||
|
guard let filePath = Bundle.main.path(forResource: isIPhone() ? "widgetTemplatesIPhone" : "widgetTemplates", ofType: "bin") else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let fileData = try Data(contentsOf: URL(fileURLWithPath: filePath), options: .mappedIfSafe)
|
||||||
|
guard let defaultProfilesEncoded = try NSKeyedUnarchiver.unarchivedObject(ofClasses: Self.profileCodingClasses, from: fileData) as? NSMutableArray else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetProfilesDecoded = getAllProfiles()
|
||||||
|
var newPencilProProfile: OSCProfile?
|
||||||
|
var pencilProProfileExisted = false
|
||||||
|
|
||||||
|
for case let profileEncoded as Data in defaultProfilesEncoded {
|
||||||
|
guard let defaultProfileDecoded = try NSKeyedUnarchiver.unarchivedObject(ofClasses: Self.profileCodingClasses, from: profileEncoded) as? OSCProfile else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetProfile = findProfile(byName: defaultProfileDecoded.name, inProfileArray: targetProfilesDecoded)
|
||||||
|
if defaultProfileDecoded.name == "Pencil Pro" {
|
||||||
|
newPencilProProfile = defaultProfileDecoded.mutableCopy() as? OSCProfile
|
||||||
|
}
|
||||||
|
|
||||||
|
if let targetProfile {
|
||||||
|
if targetProfile.name == "Pencil Pro" {
|
||||||
|
pencilProProfileExisted = true
|
||||||
|
}
|
||||||
|
let targetIndex = targetProfilesDecoded.index(of: targetProfile)
|
||||||
|
targetProfilesDecoded.replaceObject(at: targetIndex, with: defaultProfileDecoded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let newPencilProProfile, !pencilProProfileExisted {
|
||||||
|
targetProfilesDecoded.insert(newPencilProProfile, at: 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
persistProfiles(targetProfilesDecoded)
|
||||||
|
setProfileToSelected(0)
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllProfiles() -> NSMutableArray {
|
||||||
|
guard
|
||||||
|
let profilesArrayEncoded = UserDefaults.standard.object(forKey: Self.profilesDefaultsKey) as? Data,
|
||||||
|
let profilesEncoded = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: Self.profileCodingClasses, from: profilesArrayEncoded) as? NSMutableArray
|
||||||
|
else {
|
||||||
|
currentProfiles = NSMutableArray()
|
||||||
|
return currentProfiles
|
||||||
|
}
|
||||||
|
|
||||||
|
let profilesDecoded = decodeProfiles(from: profilesEncoded)
|
||||||
|
currentProfiles = profilesDecoded
|
||||||
|
return profilesDecoded
|
||||||
|
}
|
||||||
|
|
||||||
|
private func decodeProfiles(from profilesEncoded: NSMutableArray) -> NSMutableArray {
|
||||||
|
let profilesDecoded = NSMutableArray()
|
||||||
|
for case let profileEncoded as Data in profilesEncoded {
|
||||||
|
guard let profileDecoded = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: Self.profileCodingClasses, from: profileEncoded) as? OSCProfile else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
profilesDecoded.add(profileDecoded)
|
||||||
|
}
|
||||||
|
return profilesDecoded
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSelectedProfile() -> OSCProfile {
|
||||||
|
var profiles = getAllProfiles()
|
||||||
|
let defaults = UserDefaults.standard
|
||||||
|
let needImportDefaultTemplates = defaults.object(forKey: Self.widgetProfileUpdatedKey) == nil
|
||||||
|
|
||||||
|
if profiles.count == 0 || needImportDefaultTemplates {
|
||||||
|
if profiles.count == 0 {
|
||||||
|
importDefaultTemplates()
|
||||||
|
} else {
|
||||||
|
updateDefaultTemplates()
|
||||||
|
}
|
||||||
|
defaults.set(true, forKey: Self.widgetProfileUpdatedKey)
|
||||||
|
defaults.synchronize()
|
||||||
|
profiles = getAllProfiles()
|
||||||
|
}
|
||||||
|
|
||||||
|
for case let profile as OSCProfile in profiles where profile.isSelected {
|
||||||
|
return profile
|
||||||
|
}
|
||||||
|
|
||||||
|
return (profiles.firstObject as? OSCProfile) ?? OSCProfile(name: "", buttonStates: NSMutableArray(), isSelected: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIndexOfSelectedProfile() -> Int {
|
||||||
|
let profiles = getAllProfiles()
|
||||||
|
for case let profile as OSCProfile in profiles where profile.isSelected {
|
||||||
|
return profiles.index(of: profile)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIndexOfLastProfile() -> UInt32 {
|
||||||
|
let profiles = getAllProfiles()
|
||||||
|
return profiles.count > 0 ? UInt32(profiles.count - 1) : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func setProfileToSelected(_ tableIndex: UInt32) {
|
||||||
|
let profiles = getAllProfiles()
|
||||||
|
|
||||||
|
for (idx, element) in profiles.enumerated() {
|
||||||
|
guard let profile = element as? OSCProfile else { continue }
|
||||||
|
profile.isSelected = idx == Int(tableIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
persistProfiles(profiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateSelectedProfile(_ oscButtonLayers: NSMutableSet) -> Bool {
|
||||||
|
let buttonStatesEncoded = convertOnScreenControllerAndWidgetsToButtonStates(oscButtonLayers)
|
||||||
|
if getIndexOfSelectedProfile() == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let selectedProfile = getSelectedProfile()
|
||||||
|
selectedProfile.buttonStatesEncoded = buttonStatesEncoded
|
||||||
|
selectedProfile.unfoldedExclusiveFolderSequence = OnScreenWidgetView.unfoldedExclusiveFolderSequence
|
||||||
|
selectedProfile.postExclusiveUnfoldedSequences = Set(OnScreenWidgetView.postExclusiveUnfoldedSequences.map { NSNumber(value: $0) })
|
||||||
|
replaceSelectedProfile(with: selectedProfile, overwriteDefault: false)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func duplicateSelectedProfile(withName name: String) {
|
||||||
|
if profileNameAlreadyExist(name) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let profiles = getAllProfiles()
|
||||||
|
var newProfile: OSCProfile?
|
||||||
|
|
||||||
|
for case let profile as OSCProfile in profiles where profile.isSelected {
|
||||||
|
profile.isSelected = false
|
||||||
|
newProfile = profile.mutableCopy() as? OSCProfile
|
||||||
|
newProfile?.isSelected = true
|
||||||
|
newProfile?.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let newProfile, let newProfileEncoded = try? NSKeyedArchiver.archivedData(withRootObject: newProfile, requiringSecureCoding: true) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let profilesEncoded = encodedProfiles(from: profiles)
|
||||||
|
profilesEncoded.add(newProfileEncoded)
|
||||||
|
persistEncodedProfiles(profilesEncoded)
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizeWidgetPosition(_ position: CGPoint) -> CGPoint {
|
||||||
|
var normalizedPosition = position
|
||||||
|
let originalPosition = position
|
||||||
|
if position.x > 1.0, position.y > 1.0 {
|
||||||
|
normalizedPosition.x = position.x / Self.layoutViewBounds.size.width
|
||||||
|
normalizedPosition.y = position.y / Self.layoutViewBounds.size.height
|
||||||
|
}
|
||||||
|
NSLog("layoutToolView bounds: %f, %f", Self.layoutViewBounds.size.width, Self.layoutViewBounds.size.height)
|
||||||
|
NSLog("position: %f, %f, denormalized position: %f, %f", normalizedPosition.x, normalizedPosition.y, originalPosition.x, originalPosition.y)
|
||||||
|
return normalizedPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
private func denormalizeWidgetPosition(_ position: CGPoint) -> CGPoint {
|
||||||
|
var denormalizedPosition = position
|
||||||
|
if position.x < 1.0, position.y < 1.0 {
|
||||||
|
denormalizedPosition.x = position.x * Self.layoutViewBounds.size.width
|
||||||
|
denormalizedPosition.y = position.y * Self.layoutViewBounds.size.height
|
||||||
|
}
|
||||||
|
return denormalizedPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
private func convertOnScreenControllerAndWidgetsToButtonStates(_ oscButtonLayers: NSMutableSet) -> NSMutableArray {
|
||||||
|
let buttonStatesEncoded = NSMutableArray()
|
||||||
|
|
||||||
|
for case let oscButtonLayer as CALayer in oscButtonLayers {
|
||||||
|
if oscButtonLayer.isHidden {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
let normalizedPosition = normalizeWidgetPosition(oscButtonLayer.position)
|
||||||
|
let layerName = oscButtonLayer.name ?? ""
|
||||||
|
let buttonState = OnScreenButtonState(buttonName: layerName, buttonType: 0, andPosition: normalizedPosition)
|
||||||
|
buttonState.isHidden = oscButtonLayer.isHidden
|
||||||
|
buttonState.oscLayerSizeFactor = OnScreenControls.getControllerLayerSizeFactor(oscButtonLayer)
|
||||||
|
buttonState.backgroundAlpha = CGFloat(oscButtonLayer.opacity)
|
||||||
|
|
||||||
|
if let style = OnScreenControls.layerVibrationStyleDic()?.object(forKey: layerName) as? NSNumber {
|
||||||
|
buttonState.vibrationStyle = style.uint8Value
|
||||||
|
} else {
|
||||||
|
buttonState.vibrationStyle = UInt8(UIImpactFeedbackGenerator.FeedbackStyle.light.rawValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let buttonStateEncoded = try? NSKeyedArchiver.archivedData(withRootObject: buttonState, requiringSecureCoding: true) {
|
||||||
|
buttonStatesEncoded.add(buttonStateEncoded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
widgetSizeTransition = .keepWidgetSize
|
||||||
|
for widgetView in OnScreenWidgetView.mapping.values {
|
||||||
|
let normalizedPosition = normalizeWidgetPosition(widgetView.storedCenter)
|
||||||
|
let buttonState = OnScreenButtonState(buttonName: widgetView.cmdString, buttonType: 1, andPosition: normalizedPosition)
|
||||||
|
buttonState.alias = widgetView.widgetLabel
|
||||||
|
buttonState.sequence = widgetView.sequence
|
||||||
|
buttonState.sequenceSet = Set(widgetView.sequenceSet.map { NSNumber(value: $0) })
|
||||||
|
buttonState.parentSequence = widgetView.parentSequence
|
||||||
|
buttonState.autoDockTimer = Int16(widgetView.autoDockIdleDuration)
|
||||||
|
buttonState.dockedAlpha = widgetView.autoDockSettledAlpha
|
||||||
|
buttonState.folded = widgetView.folded
|
||||||
|
buttonState.revealMode = UInt8(widgetView.revealMode.rawValue)
|
||||||
|
buttonState.bulkMoveEnabled = widgetView.bulkMoveEnabled
|
||||||
|
buttonState.widthFactor = normalizeSizeWidthFactor(with: widgetView)
|
||||||
|
buttonState.heightFactor = normalizeSizeHeightFactor(with: widgetView)
|
||||||
|
buttonState.backgroundAlpha = widgetView.originalBackgroundAlpha
|
||||||
|
buttonState.labelAlpha = widgetView.originalLabelAlpha
|
||||||
|
buttonState.borderAlpha = widgetView.borderAlpha
|
||||||
|
buttonState.highlightAlpha = widgetView.highlightAlpha
|
||||||
|
buttonState.borderWidth = widgetView.borderWidth
|
||||||
|
buttonState.highlightSizeFactor = widgetView.highlightSizeFactor
|
||||||
|
buttonState.autoTapInterval = UInt16(widgetView.autoTapInterval)
|
||||||
|
buttonState.autoTapRepeats = widgetView.autoTapRepeats
|
||||||
|
buttonState.vibrationStyle = UInt8(widgetView.vibrationStyle)
|
||||||
|
buttonState.mouseButtonAction = UInt8(widgetView.mouseButtonAction.rawValue)
|
||||||
|
buttonState.animatesTransition = widgetView.animatesTransition
|
||||||
|
buttonState.sensitivityFactorY = widgetView.sensitivityFactorY
|
||||||
|
buttonState.slideThreshold = widgetView.slideThreshold
|
||||||
|
buttonState.yawFactor = widgetView.yawFactor
|
||||||
|
buttonState.pitchFactor = widgetView.pitchFactor
|
||||||
|
buttonState.rollFactor = widgetView.rollFactor
|
||||||
|
buttonState.decelerationRateX = widgetView.decelerationRateX
|
||||||
|
buttonState.decelerationRateY = widgetView.decelerationRateY
|
||||||
|
buttonState.widgetShape = widgetView.shape
|
||||||
|
buttonState.walkModeThreshold = widgetView.dWheelWalkModeThreshold
|
||||||
|
buttonState.minStickOffset = widgetView.minStickOffset
|
||||||
|
buttonState.buttonMode = UInt8(widgetView.buttonMode.rawValue)
|
||||||
|
buttonState.sprintKeyActionType = widgetView.sprintKeyActionType.rawValue
|
||||||
|
buttonState.sprintKeyThreshold = widgetView.sprintKeyThreshold
|
||||||
|
buttonState.walkKeyActionType = widgetView.walkKeyActionType.rawValue
|
||||||
|
buttonState.walkKeyThreshold = widgetView.walkKeyThreshold
|
||||||
|
buttonState.sensitivityFactorX = widgetView.sensitivityFactorX
|
||||||
|
buttonState.componentSizeFactor = normalizeComponentSizeFactor(with: widgetView)
|
||||||
|
buttonState.touchPointAnchored = widgetView.touchPointAnchored
|
||||||
|
buttonState.stickIndicatorOffset = widgetView.stickIndicatorOffset
|
||||||
|
|
||||||
|
if let buttonStateEncoded = try? NSKeyedArchiver.archivedData(withRootObject: buttonState, requiringSecureCoding: true) {
|
||||||
|
buttonStatesEncoded.add(buttonStateEncoded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buttonStatesEncoded
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getReferenceLen() -> CGFloat {
|
||||||
|
let screenBounds = UIScreen.main.bounds
|
||||||
|
let screenWidthInPoints = screenBounds.width
|
||||||
|
let screenHeightInPoints = screenBounds.height
|
||||||
|
let longSideLen = max(screenWidthInPoints, screenHeightInPoints)
|
||||||
|
|
||||||
|
if widgetSizeTransition == .transitionWithOrientation {
|
||||||
|
return screenWidthInPoints
|
||||||
|
}
|
||||||
|
return longSideLen
|
||||||
|
}
|
||||||
|
|
||||||
|
private func normalizeSizeWidthFactor(with widget: OnScreenWidgetView) -> CGFloat {
|
||||||
|
widget.bounds.size.width / getReferenceLen() * 10000
|
||||||
|
}
|
||||||
|
|
||||||
|
private func normalizeSizeHeightFactor(with widget: OnScreenWidgetView) -> CGFloat {
|
||||||
|
widget.bounds.size.height / getReferenceLen() * 10000
|
||||||
|
}
|
||||||
|
|
||||||
|
private func normalizeComponentSizeFactor(with widget: OnScreenWidgetView) -> CGFloat {
|
||||||
|
if widget.isStickWheel || widget.isDisplacementBasedStickPad {
|
||||||
|
return widget.denormalizedComponentSizeFactor * widget.baselineDiameter / getReferenceLen() * 10000
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func profileNameAlreadyExist(_ name: String) -> Bool {
|
||||||
|
let profiles = getAllProfiles()
|
||||||
|
for case let profile as OSCProfile in profiles where profile.name == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc(findProfileByName:inProfileArray:)
|
||||||
|
func findProfile(byName name: String, inProfileArray profiles: NSMutableArray) -> OSCProfile? {
|
||||||
|
for case let profile as OSCProfile in profiles where profile.name == name {
|
||||||
|
return profile
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unarchiveButtonStateEncoded(_ data: Data) -> OnScreenButtonState {
|
||||||
|
if let buttonState = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: Self.buttonStateCodingClasses, from: data) as? OnScreenButtonState {
|
||||||
|
return buttonState
|
||||||
|
}
|
||||||
|
return OnScreenButtonState(buttonName: "", buttonType: 0, andPosition: .zero)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension NSMutableArray {
|
||||||
|
subscript(safe index: Int) -> Any? {
|
||||||
|
guard index >= 0, index < count else { return nil }
|
||||||
|
return self[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
#import <CoreMotion/CoreMotion.h>
|
#import <CoreMotion/CoreMotion.h>
|
||||||
#endif
|
#endif
|
||||||
#import "OnScreenButtonState.h"
|
#import "OnScreenButtonState.h"
|
||||||
#import "OSCProfilesManager.h"
|
#import "VoidLink-Swift.h"
|
||||||
#import "DataManager.h"
|
#import "DataManager.h"
|
||||||
|
|
||||||
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#import "ControllerSupport.h"
|
#import "ControllerSupport.h"
|
||||||
#import "KeyboardSupport.h"
|
#import "KeyboardSupport.h"
|
||||||
#import "VoidLink-Swift.h"
|
#import "VoidLink-Swift.h"
|
||||||
#import "OSCProfilesManager.h"
|
|
||||||
#import "NativeTouchPointer.h"
|
#import "NativeTouchPointer.h"
|
||||||
#import "NativeTouchHandler.h"
|
#import "NativeTouchHandler.h"
|
||||||
#import "PureNativeTouchHandler.h"
|
#import "PureNativeTouchHandler.h"
|
||||||
|
|||||||
@@ -13199,6 +13199,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Restored" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "已恢复"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "已恢復"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "已恢復"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Resume App" : {
|
"Resume App" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ import StoreKit
|
|||||||
case (.PencilProPack, "com.voidlink.tf.debug10.iOS"):
|
case (.PencilProPack, "com.voidlink.tf.debug10.iOS"):
|
||||||
return "com.pencilpro.voidlink.debug.iOS"
|
return "com.pencilpro.voidlink.debug.iOS"
|
||||||
case (.PencilProPack, "com.voidlink.tf.iOS"):
|
case (.PencilProPack, "com.voidlink.tf.iOS"):
|
||||||
return "com.pencilpro.voidlink.tf.iOS"
|
return ""
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -371,6 +371,9 @@ import StoreKit
|
|||||||
|
|
||||||
@objc static public func inAppPurchaseAction(viewController: UIViewController, product: AddOnProduct){
|
@objc static public func inAppPurchaseAction(viewController: UIViewController, product: AddOnProduct){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let alert = UIAlertController(title: product.productName(),
|
let alert = UIAlertController(title: product.productName(),
|
||||||
message: LocalizationHelper.localizedString(forKey: "No purchase found", product.productName()),
|
message: LocalizationHelper.localizedString(forKey: "No purchase found", product.productName()),
|
||||||
preferredStyle: .alert)
|
preferredStyle: .alert)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#import "LayoutOnScreenControlsViewController.h"
|
#import "LayoutOnScreenControlsViewController.h"
|
||||||
#import "OnScreenButtonState.h"
|
#import "OnScreenButtonState.h"
|
||||||
#import "OnScreenControls.h"
|
#import "OnScreenControls.h"
|
||||||
#import "OSCProfilesManager.h"
|
|
||||||
#import "LocalizationHelper.h"
|
#import "LocalizationHelper.h"
|
||||||
#import "VoidLink-Swift.h"
|
#import "VoidLink-Swift.h"
|
||||||
// #import "ThemeManager.h"
|
// #import "ThemeManager.h"
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#import "VoidLink-Swift.h"
|
#import "VoidLink-Swift.h"
|
||||||
#import "Connection.h"
|
#import "Connection.h"
|
||||||
#import "Plot.h"
|
#import "Plot.h"
|
||||||
#import "OSCProfilesManager.h"
|
|
||||||
|
|
||||||
#import <UIKit/UIGestureRecognizerSubclass.h>
|
#import <UIKit/UIGestureRecognizerSubclass.h>
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,6 @@
|
|||||||
#import "CustomTapGestureRecognizer.h"
|
#import "CustomTapGestureRecognizer.h"
|
||||||
#import "LocalizationHelper.h"
|
#import "LocalizationHelper.h"
|
||||||
#import "VoidLink-Swift.h"
|
#import "VoidLink-Swift.h"
|
||||||
#import "OSCProfilesManager.h"
|
|
||||||
#import "VoidLink-Swift.h"
|
|
||||||
#import "NativeTouchPointer.h"
|
#import "NativeTouchPointer.h"
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#import "DataManager.h"
|
#import "DataManager.h"
|
||||||
#import "LocalizationHelper.h"
|
#import "LocalizationHelper.h"
|
||||||
#import "OSCProfile.h"
|
#import "OSCProfile.h"
|
||||||
#import "OSCProfilesManager.h"
|
|
||||||
#import "LayoutOnScreenControls.h"
|
#import "LayoutOnScreenControls.h"
|
||||||
#import "ToolBarContainerView.h"
|
#import "ToolBarContainerView.h"
|
||||||
#import "opus.h"
|
#import "opus.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user