* start upgrade to RN 74 * migrate react-native-fs to expo-file-system * exclude expo-asset module * fix database manager remove directory * fix: android network helper * include expo on android * temporarily disable android dep lock * replace react-native-create-thumbnail with expo-video-thumnails * update patches file version * fix android build on 74 * create local library to replace MattermostManaged, Notifications and SplitView modules with new arch support * migrate app to use new mattermost-rnutils library * remove unused flipper class for android unsigned * fix mattermost-rnutils android foldedObserver lifecycle * use mattermost-rnutils on Android * use mattermost-rnutils on iOS * path react-native-navigation to not crash when activity is not NavigationActivity * create local library for android share extension with new arch support * Replace ShareModule with @mattermost/rnshare library * remove ShareModule from android native code * update react-intl * update nodejs to 20.x.x npm to 10.x.x and dev deps * update @gorhom/bottom-sheet * use MattermostShare conditionally based on the platform * update @react-native-camera-roll/camera-roll * remove unused react-native-calendars * fix metro config * fix terminate session race condition * remove unused analytics * replace react-native-device-info with expo-application and expo-device * update @react-native-clipboard/clipboard * update @react-native-community/datetimepicker * update @react-native-community/netinfo * update @sentry/react-native * update react-native-document-picker * update react-native-gesture-handler * update react-native-share * update react-native-svg and react-native-svg-transformer * update react-native-vector-icons * update babel * update react-native-shadow-2 * update semver * remove react-native-svg-transformer and convert svg files to svg components * fix @mattermost/rnshare new-arch build on android * remove react-native-create-thumbnail resolution in build.gradle * create @mattermost/hardware-keyboard library to replace hw-keyboard-events * fix hardware-keyboard library * fix rnutils library * create @mattermost/keyboard-tracker library * replace react-native-keyboard-tracking-view with @mattermost/keyboard-tracker * fix: rnutils to not crash on lateinit context * fix: rnutils delete database * revert changes to session_manager * Removed react-native-webview and added expo-web-browser instead With expo-web-browser we no longer need the webview for SSO login the SSO login is now done by using "custom Chrome tabs" on Android and ASWebAuthenticationSession on iOS * remove patch for react-native-keyboard-tracking-view * replace react-native-linear-gradient with expo-linear-gradient * replace react-native-in-app-review with expo-store-review * fix: shared group database directory on ios * replace react-native-fast-image with expo-image * remove unusued type def for react-native-keyboard-tracking-view * replace react-native-elements and react-native-button with @rneui * node version * update sizzling methods * fix tests using jest-expo * replace jail-monkey with expo-device * update babel deps * update typescript eslint * update rn and expo * react-native-document-picker @react-native-camera-roll/camera-roll @react-native-community/datetimepicker react-native-reanimated react-native-safe-area-context * update patches * update @sentry/react-native * upgrade react-native-navigation * update expo & expo-image * upgrade to working version of @sentry/react-native * update node, cocoapods, bundler, fastlane versions * @testing-library/react-native and eslint-plugin-jest * fix: FloatingTextInput causing a crash with reanimated * update sentry, localize, @types/lodash and uuid * fix floating text input label * update react-native-video * fix: cannot calculate shadow efficiently on some components * fix: reduce motion warning for bottomSheet * fix: shadow on YouTube component * update react-native-webrtc expo and @typescript-eslint * audit fix * fix swizzling bad merge * temp use of github dependency for @mattermost libraries * feedback review * feedback review * npm audit fix * update bundle deps * update @mattermost/react-native-turbo-log * update deps
224 lines
7.8 KiB
Swift
224 lines
7.8 KiB
Swift
import Foundation
|
|
import React
|
|
|
|
@objc public class RNUtilsWrapper: NSObject {
|
|
@objc public weak var delegate: RNUtilsDelegate? = nil
|
|
|
|
deinit {
|
|
NotificationCenter.default.removeObserver(self,
|
|
name: NSNotification.Name.RCTUserInterfaceStyleDidChange,
|
|
object: nil)
|
|
}
|
|
|
|
func getSharedDirectory() -> URL? {
|
|
let fileManager = FileManager.default
|
|
return fileManager.containerURL(forSecurityApplicationGroupIdentifier: getAppGroupId())
|
|
}
|
|
|
|
func getDatabasePath() -> String {
|
|
guard let sharedDirectory = getSharedDirectory() else {
|
|
return ""
|
|
}
|
|
return sharedDirectory.appendingPathComponent("databases").path
|
|
}
|
|
|
|
func isRunningInFullScreen() -> Bool {
|
|
guard let w = UIApplication.shared.delegate?.window, let window = w else { return false }
|
|
let screenSize = window.screen.bounds.size.width
|
|
let frameSize = window.frame.size.width
|
|
let shouldBeConsideredFullScreen = frameSize >= (screenSize * 0.6)
|
|
return shouldBeConsideredFullScreen
|
|
}
|
|
|
|
@objc public func captureEvents() {
|
|
NotificationCenter.default.addObserver(self,
|
|
selector: #selector(isSplitView), name: NSNotification.Name.RCTUserInterfaceStyleDidChange,
|
|
object: nil)
|
|
}
|
|
|
|
@objc func isSplitView() {
|
|
if UIDevice.current.userInterfaceIdiom == .pad {
|
|
delegate?.sendEvent(name: "SplitViewChanged", result: [
|
|
"isSplitView": !isRunningInFullScreen(),
|
|
"isTablet": UIDevice.current.userInterfaceIdiom == .pad,
|
|
])
|
|
}
|
|
}
|
|
|
|
@objc public func getAppGroupId() -> String {
|
|
let bundle = Bundle.main
|
|
guard let appGroupId = bundle.object(forInfoDictionaryKey: "AppGroupIdentifier") as? String else {
|
|
return ""
|
|
}
|
|
|
|
return appGroupId
|
|
}
|
|
|
|
@objc public func appGroupSharedDirectory() -> Dictionary<String, Any> {
|
|
let fileManager = FileManager.default
|
|
let sharedDirectory = fileManager.containerURL(forSecurityApplicationGroupIdentifier: getAppGroupId())
|
|
let databasePath = sharedDirectory?.appendingPathComponent("databases")
|
|
var results = Dictionary<String, Any>()
|
|
|
|
guard let dbPath = databasePath,
|
|
let shared = sharedDirectory else {
|
|
results["sharedDirectory"] = ""
|
|
results["databasePath"] = ""
|
|
return results
|
|
}
|
|
|
|
try? fileManager.createDirectory(at: dbPath, withIntermediateDirectories: true, attributes: nil)
|
|
|
|
results["sharedDirectory"] = shared.path
|
|
results["databasePath"] = dbPath.path
|
|
return results
|
|
}
|
|
|
|
@objc public func deleteDatabaseDirectory(databaseName: String?, shouldRemoveDirectory: Bool) -> Dictionary<String, Any> {
|
|
let appGroupDatabaseDir = getDatabasePath()
|
|
guard !appGroupDatabaseDir.isEmpty else {
|
|
return [
|
|
"error": "No app group directory found",
|
|
"success": false
|
|
]
|
|
}
|
|
|
|
guard let name = databaseName, !name.isEmpty else {
|
|
return [
|
|
"error": "database name should not be null or empty",
|
|
"success": false
|
|
]
|
|
}
|
|
|
|
let databaseFile = "\(appGroupDatabaseDir)/\(name).db"
|
|
let databaseDirOrFile = shouldRemoveDirectory ? appGroupDatabaseDir : databaseFile
|
|
let fileManager = FileManager.default
|
|
|
|
let walFile = "\(databaseFile)-wal"
|
|
if !shouldRemoveDirectory && fileManager.fileExists(atPath: walFile) {
|
|
try? fileManager.removeItem(atPath: walFile)
|
|
}
|
|
|
|
let shmFile = "\(databaseFile)-shm"
|
|
if !shouldRemoveDirectory && fileManager.fileExists(atPath: shmFile) {
|
|
try? fileManager.removeItem(atPath: shmFile)
|
|
}
|
|
|
|
do {
|
|
try fileManager.removeItem(atPath: databaseDirOrFile)
|
|
return [
|
|
"error": "",
|
|
"success": true
|
|
]
|
|
} catch {
|
|
return [
|
|
"error": error.localizedDescription,
|
|
"success": false
|
|
]
|
|
}
|
|
}
|
|
|
|
@objc public func renameDatabase(databaseName: String?, newDatabaseName: String?) -> Dictionary<String, Any> {
|
|
guard let appGroupDir = getSharedDirectory() else {
|
|
return [
|
|
"error": "No app group directory found",
|
|
"success": false
|
|
]
|
|
}
|
|
|
|
guard let name = databaseName,
|
|
let newName = newDatabaseName,
|
|
!name.isEmpty, !newName.isEmpty else {
|
|
return [
|
|
"error": "database name and the new database name should not be null or empty",
|
|
"success": false
|
|
]
|
|
}
|
|
|
|
let fileManager = FileManager.default
|
|
let databaseDir = "\(appGroupDir.path)/\(name).db"
|
|
let walFile = "\(databaseDir)-wal"
|
|
let shmFile = "\(databaseDir)-shm"
|
|
if !fileManager.fileExists(atPath: databaseDir) {
|
|
return [
|
|
"error": "database file is not does not exists",
|
|
"success": false
|
|
]
|
|
}
|
|
|
|
let newDatabaseDir = "\(appGroupDir.path)/\(newName).db"
|
|
let destinationFileExists = fileManager.fileExists(atPath: newDatabaseDir)
|
|
let dstWal = "\(newDatabaseDir)-wal"
|
|
let dstShm = "\(newDatabaseDir)-shm"
|
|
|
|
if !destinationFileExists && fileManager.fileExists(atPath: walFile) {
|
|
try? fileManager.moveItem(atPath: walFile, toPath: dstWal)
|
|
}
|
|
|
|
if !destinationFileExists && fileManager.fileExists(atPath: shmFile) {
|
|
try? fileManager.moveItem(atPath: shmFile, toPath: dstShm)
|
|
}
|
|
|
|
do {
|
|
try fileManager.moveItem(atPath: databaseDir, toPath: newDatabaseDir)
|
|
return [
|
|
"error": "",
|
|
"success": true
|
|
]
|
|
} catch {
|
|
return [
|
|
"error": error.localizedDescription,
|
|
"success": false
|
|
]
|
|
}
|
|
}
|
|
|
|
@objc public func deleteEntitiesFile() -> NSNumber {
|
|
guard let appGroupDir = getSharedDirectory() else {
|
|
return NSNumber(false)
|
|
}
|
|
|
|
let file = "\(appGroupDir)/entities"
|
|
do {
|
|
try FileManager.default.removeItem(atPath: file)
|
|
return NSNumber(true)
|
|
} catch {
|
|
return NSNumber(false)
|
|
}
|
|
}
|
|
|
|
@objc public func isRunningInSplitView() -> Dictionary<String, Any> {
|
|
let queue = DispatchQueue.main
|
|
let group = DispatchGroup()
|
|
var shouldBeConsideredFullScreen = true
|
|
group.enter()
|
|
queue.async(group: group) { [weak self] in
|
|
shouldBeConsideredFullScreen = self?.isRunningInFullScreen() ?? true
|
|
group.leave()
|
|
}
|
|
group.wait()
|
|
return [
|
|
"isSplit": !shouldBeConsideredFullScreen,
|
|
"isTablet": UIDevice.current.userInterfaceIdiom == .pad,
|
|
]
|
|
}
|
|
|
|
@objc public func unlockOrientation() {
|
|
DispatchQueue.main.async {
|
|
OrientationManager.shared.unlockOrientation()
|
|
UIDevice.current.setValue(UIInterfaceOrientation.unknown.rawValue, forKey: "orientation")
|
|
UINavigationController.attemptRotationToDeviceOrientation()
|
|
}
|
|
}
|
|
|
|
@objc public func lockOrientation() {
|
|
DispatchQueue.main.async {
|
|
OrientationManager.shared.lockOrientation()
|
|
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
|
|
UINavigationController.attemptRotationToDeviceOrientation()
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|