Signed-off-by: Nextcloud bot <bot@nextcloud.com>
Signed-off-by: Marino Faggiana <marino@marinofaggiana.com>
Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
Signed-off-by: rakekniven <2069590+rakekniven@users.noreply.github.com>
This commit is contained in:
Marino Faggiana 2024-10-24 13:55:27 +02:00 коммит произвёл GitHub
Родитель 64ab8f4891
Коммит 574ab7e3a2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
420 изменённых файлов: 17300 добавлений и 9046 удалений

Просмотреть файл

@ -26,4 +26,4 @@ import Foundation
// Database Realm
//
let databaseName = "nextcloud.realm"
let databaseSchemaVersion: UInt64 = 354
let databaseSchemaVersion: UInt64 = 365

Просмотреть файл

@ -31,6 +31,8 @@
<string>group.it.twsweb.Crypto-Cloud</string>
<key>NSExtensionFileProviderSupportsEnumeration</key>
<true/>
<key>NSExtensionFileProviderSupportsPickingFolders</key>
<true/>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.fileprovider-nonui</string>
<key>NSExtensionPrincipalClass</key>

Просмотреть файл

@ -26,7 +26,6 @@
import UIKit
class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
@IBOutlet weak var buttonLogin: UIButton!
@IBOutlet weak var buttonSignUp: UIButton!
@IBOutlet weak var buttonHost: UIButton!
@ -99,18 +98,23 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol
view.backgroundColor = NCBrandColor.shared.customer
timerAutoScroll = Timer.scheduledTimer(timeInterval: 5, target: self, selector: (#selector(NCIntroViewController.autoScroll)), userInfo: nil, repeats: true)
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeUser), object: nil, queue: nil) { _ in
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeUser), object: nil, queue: nil) { notification in
if let userInfo = notification.userInfo,
let account = userInfo["account"] as? String {
let window = UIApplication.shared.firstWindow
if window?.rootViewController is NCMainTabBarController {
if let controller = window?.rootViewController as? NCMainTabBarController {
controller.account = account
self.dismiss(animated: true)
} else {
if let mainTabBarController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController {
mainTabBarController.modalPresentationStyle = .fullScreen
mainTabBarController.view.alpha = 0
window?.rootViewController = mainTabBarController
if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController {
controller.account = account
controller.modalPresentationStyle = .fullScreen
controller.view.alpha = 0
window?.rootViewController = controller
window?.makeKeyAndVisible()
UIView.animate(withDuration: 0.5) {
mainTabBarController.view.alpha = 1
controller.view.alpha = 1
}
}
}
}
@ -179,11 +183,11 @@ class NCIntroViewController: UIViewController, UICollectionViewDataSource, UICol
}
@IBAction func login(_ sender: Any) {
appDelegate.openLogin(selector: NCGlobal.shared.introLogin, openLoginWeb: false)
appDelegate.openLogin(selector: NCGlobal.shared.introLogin)
}
@IBAction func signup(_ sender: Any) {
appDelegate.openLogin(selector: NCGlobal.shared.introSignup, openLoginWeb: false)
appDelegate.openLogin(selector: NCGlobal.shared.introSignup)
}
@IBAction func host(_ sender: Any) {

Просмотреть файл

@ -58,7 +58,7 @@ let userAgent: String = {
// BRAND ONLY
@objc public var use_AppConfig: Bool = false // Don't touch me !!
// Options
// Use server theming color
@objc public var use_themingColor: Bool = true
var disable_intro: Bool = false
@ -71,6 +71,10 @@ let userAgent: String = {
var disable_mobileconfig: Bool = false
var disable_show_more_nextcloud_apps_in_settings: Bool = false
var doNotAskPasscodeAtStartup: Bool = false
var disable_source_code_in_settings: Bool = false
// (name: "Name 1", url: "https://cloud.nextcloud.com"),(name: "Name 2", url: "https://cloud.nextcloud.com")
var enforce_servers: [(name: String, url: String)] = []
// Internal option behaviour
var cleanUpDay: Int = 0 // Set default "Delete, in the cache, all files older than" possible days value are: 0, 1, 7, 30, 90, 180, 365
@ -127,26 +131,22 @@ class NCBrandColor: NSObject {
return instance
}()
// Color
/// This is rewrited from customet theme, default is Nextcloud color
///
let customer: UIColor = UIColor(red: 0.0 / 255.0, green: 130.0 / 255.0, blue: 201.0 / 255.0, alpha: 1.0) // BLU NC : #0082c9
var customerText: UIColor = .white
var brand: UIColor // don't touch me
var brandElement: UIColor // don't touch me
var brandText: UIColor // don't touch me
let nextcloud: UIColor = UIColor(red: 0.0 / 255.0, green: 130.0 / 255.0, blue: 201.0 / 255.0, alpha: 1.0)
let yellowFavorite: UIColor = UIColor(red: 248.0 / 255.0, green: 205.0 / 255.0, blue: 70.0 / 255.0, alpha: 1.0)
// INTERNAL DEFINE COLORS
private var themingColor = ThreadSafeDictionary<String, UIColor>()
private var themingColorElement = ThreadSafeDictionary<String, UIColor>()
private var themingColorText = ThreadSafeDictionary<String, UIColor>()
var userColors: [CGColor] = []
var themingColor: String = ""
var themingColorElement: String = ""
var themingColorText: String = ""
let nextcloud: UIColor = UIColor(red: 0.0 / 255.0, green: 130.0 / 255.0, blue: 201.0 / 255.0, alpha: 1.0)
let yellowFavorite: UIColor = UIColor(red: 248.0 / 255.0, green: 205.0 / 255.0, blue: 70.0 / 255.0, alpha: 1.0)
let iconImageColor: UIColor = .label
let iconImageColor2: UIColor = .secondaryLabel
let iconImageMultiColors: [UIColor] = [.secondaryLabel, .label]
let textColor: UIColor = .label
let textColor2: UIColor = .secondaryLabel
@ -174,88 +174,17 @@ class NCBrandColor: NSObject {
}
}
override init() {
brand = customer
brandElement = customer
brandText = customerText
}
override init() { }
/**
Generate colors from the official nextcloud color.
You can provide how many colors you want (multiplied by 3).
if `step` = 6,
3 colors \* 6 will result in 18 generated colors
*/
func createUserColors() {
userColors = generateColors()
}
func settingThemingColor(account: String) {
let darker: CGFloat = 30 // %
let lighter: CGFloat = 30 // %
if NCBrandOptions.shared.use_themingColor {
self.themingColor = NCGlobal.shared.capabilityThemingColor
self.themingColorElement = NCGlobal.shared.capabilityThemingColorElement
self.themingColorText = NCGlobal.shared.capabilityThemingColorText
// COLOR
if themingColor.first == "#" {
if let color = UIColor(hex: themingColor) {
brand = color
} else {
brand = customer
}
} else {
brand = customer
}
// COLOR TEXT
if themingColorText.first == "#" {
if let color = UIColor(hex: themingColorText) {
brandText = color
} else {
brandText = customerText
}
} else {
brandText = customerText
}
// COLOR ELEMENT
if themingColorElement.first == "#" {
if let color = UIColor(hex: themingColorElement) {
brandElement = color
} else {
brandElement = brand
}
} else {
brandElement = brand
}
if brandElement.isTooLight() {
if let color = brandElement.darker(by: darker) {
brandElement = color
}
} else if brandElement.isTooDark() {
if let color = brandElement.lighter(by: lighter) {
brandElement = color
}
}
} else {
if self.customer.isTooLight() {
if let color = customer.darker(by: darker) {
brandElement = color
}
} else if customer.isTooDark() {
if let color = customer.lighter(by: lighter) {
brandElement = color
}
} else {
brandElement = customer
}
brand = customer
brandText = customerText
}
}
private func stepCalc(steps: Int, color1: CGColor, color2: CGColor) -> [CGFloat] {
func generateColors(steps: Int = 6) -> [CGColor] {
func stepCalc(steps: Int, color1: CGColor, color2: CGColor) -> [CGFloat] {
var step = [CGFloat](repeating: 0, count: 3)
step[0] = (color2.components![0] - color1.components![0]) / CGFloat(steps)
@ -264,7 +193,7 @@ class NCBrandColor: NSObject {
return step
}
private func mixPalette(steps: Int, color1: CGColor, color2: CGColor) -> [CGColor] {
func mixPalette(steps: Int, color1: CGColor, color2: CGColor) -> [CGColor] {
var palette = [color1]
let step = stepCalc(steps: steps, color1: color1, color2: color2)
let c1Components = color1.components!
@ -279,13 +208,6 @@ class NCBrandColor: NSObject {
return palette
}
/**
Generate colors from the official nextcloud color.
You can provide how many colors you want (multiplied by 3).
if `step` = 6,
3 colors \* 6 will result in 18 generated colors
*/
func generateColors(steps: Int = 6) -> [CGColor] {
let red = UIColor(red: 182 / 255, green: 70 / 255, blue: 157 / 255, alpha: 1).cgColor
let yellow = UIColor(red: 221 / 255, green: 203 / 255, blue: 85 / 255, alpha: 1).cgColor
let blue = UIColor(red: 0 / 255, green: 130 / 255, blue: 201 / 255, alpha: 1).cgColor
@ -296,4 +218,118 @@ class NCBrandColor: NSObject {
return palette1 + palette2 + palette3
}
userColors = generateColors()
}
@discardableResult
func settingThemingColor(account: String) -> Bool {
let darker: CGFloat = 30 // %
let lighter: CGFloat = 30 // %
var colorThemingColor: UIColor?
var colorThemingColorElement: UIColor?
var colorThemingColorText: UIColor?
if NCBrandOptions.shared.use_themingColor {
let themingColor = NCCapabilities.shared.getCapabilities(account: account).capabilityThemingColor
let themingColorElement = NCCapabilities.shared.getCapabilities(account: account).capabilityThemingColorElement
let themingColorText = NCCapabilities.shared.getCapabilities(account: account).capabilityThemingColorText
// THEMING COLOR
if themingColor.first == "#" {
if let color = UIColor(hex: themingColor) {
colorThemingColor = color
} else {
colorThemingColor = customer
}
} else {
colorThemingColor = customer
}
// THEMING COLOR ELEMENT (control isTooLight / isTooDark)
if themingColorElement.first == "#" {
if let color = UIColor(hex: themingColorElement) {
if color.isTooLight() {
if let color = color.darker(by: darker) {
colorThemingColorElement = color
}
} else if color.isTooDark() {
if let color = color.lighter(by: lighter) {
colorThemingColorElement = color
}
} else {
colorThemingColorElement = color
}
} else {
colorThemingColorElement = customer
}
} else {
colorThemingColorElement = customer
}
// THEMING COLOR TEXT
if themingColorText.first == "#" {
if let color = UIColor(hex: themingColorText) {
colorThemingColorText = color
} else {
colorThemingColorText = .white
}
} else {
colorThemingColorText = .white
}
} else {
// THEMING COLOR
colorThemingColor = customer
// THEMING COLOR ELEMENT (control isTooLight / isTooDark)
if self.customer.isTooLight() {
if let color = customer.darker(by: darker) {
colorThemingColorElement = color
}
} else if customer.isTooDark() {
if let color = customer.lighter(by: lighter) {
colorThemingColorElement = color
}
} else {
colorThemingColorElement = customer
}
// THEMING COLOR TEXT
colorThemingColorText = customerText
}
if self.themingColor[account] != colorThemingColor || self.themingColorElement[account] != colorThemingColorElement || self.themingColorText[account] != colorThemingColorText {
self.themingColor[account] = colorThemingColor
self.themingColorElement[account] = colorThemingColorElement
self.themingColorText[account] = colorThemingColorText
return true
}
return false
}
public func getTheming(account: String?) -> UIColor {
if let account, let color = self.themingColor[account] {
return color
}
return customer
}
public func getElement(account: String?) -> UIColor {
if let account, let color = self.themingColorElement[account] {
return color
}
return customer
}
public func getText(account: String?) -> UIColor {
if let account, let color = self.themingColorText[account] {
return color
}
return .white
}
}

Просмотреть файл

@ -9,6 +9,8 @@
</array>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>12.3</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>

Просмотреть файл

@ -1,2 +0,0 @@
github "https://github.com/marinofaggiana/TOPasscodeViewController" "master"
binary "https://code.videolan.org/videolan/VLCKit/raw/master/Packaging/MobileVLCKit.json" ~> 3.5.1

Просмотреть файл

@ -1,2 +0,0 @@
binary "https://code.videolan.org/videolan/VLCKit/raw/master/Packaging/MobileVLCKit.json" "3.6.0"
github "marinofaggiana/TOPasscodeViewController" "ed795637acd2b1ef154e011a04ebab4686d0523c"

Просмотреть файл

@ -53,7 +53,7 @@ class NCApplicationHandle: NSObject {
// class: NCCollectionViewCommon (+Menu)
// func: toggleMenu(metadata: tableMetadata, imageIcon: UIImage?)
func addCollectionViewCommonMenu(metadata: tableMetadata, imageIcon: UIImage?, actions: inout [NCMenuAction]) {
func addCollectionViewCommonMenu(metadata: tableMetadata, image: UIImage?, actions: inout [NCMenuAction]) {
}
// class: NCMore

Просмотреть файл

@ -32,9 +32,9 @@ class DocumentActionViewController: FPUIActionExtensionViewController {
override func loadView() {
super.loadView()
view.backgroundColor = NCBrandColor.shared.brandElement
titleError.textColor = NCBrandColor.shared.brandText
cancelButton.setTitleColor(NCBrandColor.shared.brandText, for: .normal)
view.backgroundColor = NCBrandColor.shared.customer
titleError.textColor = NCBrandColor.shared.customerText
cancelButton.setTitleColor(NCBrandColor.shared.customerText, for: .normal)
titleError.text = ""
}

Просмотреть файл

@ -33,19 +33,24 @@ class fileProviderData: NSObject {
var domain: NSFileProviderDomain?
var fileProviderManager: NSFileProviderManager = NSFileProviderManager.default
let utilityFileSystem = NCUtilityFileSystem()
var account = ""
var user = ""
var userId = ""
var accountUrlBase = ""
var homeServerUrl = ""
let database = NCManageDatabase.shared
var listFavoriteIdentifierRank: [String: NSNumber] = [:]
var fileProviderSignalDeleteContainerItemIdentifier: [NSFileProviderItemIdentifier: NSFileProviderItemIdentifier] = [:]
var fileProviderSignalUpdateContainerItem: [NSFileProviderItemIdentifier: FileProviderItem] = [:]
var fileProviderSignalDeleteWorkingSetItemIdentifier: [NSFileProviderItemIdentifier: NSFileProviderItemIdentifier] = [:]
var fileProviderSignalUpdateWorkingSetItem: [NSFileProviderItemIdentifier: FileProviderItem] = [:]
private var account: String = ""
var session: NCSession.Session {
if !account.isEmpty,
let tableAccount = self.database.getTableAccount(account: account) {
return NCSession.Session(account: tableAccount.account, urlBase: tableAccount.urlBase, user: tableAccount.user, userId: tableAccount.userId)
} else if let activeTableAccount = self.database.getActiveTableAccount() {
self.account = activeTableAccount.account
return NCSession.Session(account: activeTableAccount.account, urlBase: activeTableAccount.urlBase, user: activeTableAccount.user, userId: activeTableAccount.userId)
} else {
return NCSession.Session(account: "", urlBase: "", user: "", userId: "")
}
}
enum FileProviderError: Error {
case downloadError
@ -81,54 +86,45 @@ class fileProviderData: NSObject {
let version = NSString(format: NCBrandOptions.shared.textCopyrightNextcloudiOS as NSString, NCUtility().getVersionApp()) as String
NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Start File Provider session with level \(levelLog) " + version + " (File Provider Extension)")
// NO DOMAIN -> Set default account
if domain == nil {
guard let activeAccount = NCManageDatabase.shared.getActiveAccount() else { return nil }
account = activeAccount.account
user = activeAccount.user
userId = activeAccount.userId
accountUrlBase = activeAccount.urlBase
homeServerUrl = utilityFileSystem.getHomeServer(urlBase: activeAccount.urlBase, userId: activeAccount.userId)
var tblAccount = self.database.getActiveTableAccount()
if let domain {
for tableAccount in self.database.getAllTableAccount() {
guard let urlBase = NSURL(string: tableAccount.urlBase) else { continue }
guard let host = urlBase.host else { continue }
let accountDomain = tableAccount.userId + " (" + host + ")"
if accountDomain == domain.identifier.rawValue {
let account = "\(tableAccount.user) \(tableAccount.urlBase)"
tblAccount = self.database.getTableAccount(account: account)
break
}
}
}
guard let tblAccount else { return nil }
NCManageDatabase.shared.setCapabilities(account: account)
NextcloudKit.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: NCKeychain().getPassword(account: activeAccount.account), urlBase: activeAccount.urlBase, userAgent: userAgent, nextcloudVersion: NCGlobal.shared.capabilityServerVersionMajor, delegate: NCNetworking.shared)
self.account = tblAccount.account
/// NextcloudKit Session
NextcloudKit.shared.setup(delegate: NCNetworking.shared)
NextcloudKit.shared.appendSession(account: tblAccount.account,
urlBase: tblAccount.urlBase,
user: tblAccount.user,
userId: tblAccount.userId,
password: NCKeychain().getPassword(account: tblAccount.account),
userAgent: userAgent,
nextcloudVersion: NCCapabilities.shared.getCapabilities(account: tblAccount.account).capabilityServerVersionMajor,
groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
NCNetworking.shared.delegate = providerExtension as? NCNetworkingDelegate
return tableAccount.init(value: activeAccount)
}
// DOMAIN
let accounts = NCManageDatabase.shared.getAllAccount()
if accounts.isEmpty { return nil }
for activeAccount in accounts {
guard let url = NSURL(string: activeAccount.urlBase) else { continue }
guard let host = url.host else { continue }
let accountDomain = activeAccount.userId + " (" + host + ")"
if accountDomain == domain!.identifier.rawValue {
account = activeAccount.account
user = activeAccount.user
userId = activeAccount.userId
accountUrlBase = activeAccount.urlBase
homeServerUrl = utilityFileSystem.getHomeServer(urlBase: activeAccount.urlBase, userId: activeAccount.userId)
NCManageDatabase.shared.setCapabilities(account: account)
NextcloudKit.shared.setup(account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId, password: NCKeychain().getPassword(account: activeAccount.account), urlBase: activeAccount.urlBase, userAgent: userAgent, nextcloudVersion: NCGlobal.shared.capabilityServerVersionMajor, delegate: NCNetworking.shared)
NCNetworking.shared.delegate = providerExtension as? NCNetworkingDelegate
return tableAccount.init(value: activeAccount)
}
}
return nil
return tableAccount(value: tblAccount)
}
// MARK: -
@discardableResult
func signalEnumerator(ocId: String, type: TypeSignal) -> FileProviderItem? {
guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId),
let parentItemIdentifier = fileProviderUtility().getParentItemIdentifier(metadata: metadata) else { return nil }
guard let metadata = self.database.getMetadataFromOcId(ocId),
let parentItemIdentifier = fileProviderUtility().getParentItemIdentifier(metadata: metadata) else {
return nil
}
let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
if type == .delete {

Просмотреть файл

@ -28,7 +28,7 @@ class FileProviderDomain: NSObject {
NSFileProviderManager.getDomainsWithCompletionHandler { fileProviderDomain, error in
var domains: [String] = []
let pathRelativeToDocumentStorage = NSFileProviderManager.default.documentStorageURL.absoluteString
let accounts = NCManageDatabase.shared.getAllAccount()
let tableAccounts = NCManageDatabase.shared.getAllTableAccount()
for domain in fileProviderDomain {
domains.append(domain.identifier.rawValue)
@ -37,10 +37,10 @@ class FileProviderDomain: NSObject {
// Delete
for domain in domains {
var domainFound = false
for account in accounts {
guard let urlBase = NSURL(string: account.urlBase) else { continue }
for tableAccount in tableAccounts {
guard let urlBase = NSURL(string: tableAccount.urlBase) else { continue }
guard let host = urlBase.host else { continue }
let accountDomain = account.userId + " (" + host + ")"
let accountDomain = tableAccount.userId + " (" + host + ")"
if domain == accountDomain {
domainFound = true
break
@ -57,11 +57,11 @@ class FileProviderDomain: NSObject {
}
// Add
for account in accounts {
for tableAccount in tableAccounts {
var domainFound = false
guard let urlBase = NSURL(string: account.urlBase) else { continue }
guard let urlBase = NSURL(string: tableAccount.urlBase) else { continue }
guard let host = urlBase.host else { continue }
let accountDomain = account.userId + " (" + host + ")"
let accountDomain = tableAccount.userId + " (" + host + ")"
for domain in domains {
if domain == accountDomain {
domainFound = true

Просмотреть файл

@ -30,16 +30,17 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
var enumeratedItemIdentifier: NSFileProviderItemIdentifier
var serverUrl: String?
let providerUtility = fileProviderUtility()
let database = NCManageDatabase.shared
var recordsPerPage: Int = 20
var anchor: UInt64 = 0
init(enumeratedItemIdentifier: NSFileProviderItemIdentifier) {
self.enumeratedItemIdentifier = enumeratedItemIdentifier
if enumeratedItemIdentifier == .rootContainer {
serverUrl = fileProviderData.shared.homeServerUrl
serverUrl = NCUtilityFileSystem().getHomeServer(session: fileProviderData.shared.session)
} else {
if let metadata = providerUtility.getTableMetadataFromItemIdentifier(enumeratedItemIdentifier),
let directorySource = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) {
let directorySource = self.database.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) {
serverUrl = directorySource.serverUrl + "/" + metadata.fileName
}
@ -55,15 +56,15 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
if enumeratedItemIdentifier == .workingSet {
var itemIdentifierMetadata: [NSFileProviderItemIdentifier: tableMetadata] = [:]
/// Tags
let tags = NCManageDatabase.shared.getTags(predicate: NSPredicate(format: "account == %@", fileProviderData.shared.account))
let tags = self.database.getTags(predicate: NSPredicate(format: "account == %@", fileProviderData.shared.session.account))
for tag in tags {
guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(tag.ocId) else { continue }
guard let metadata = self.database.getMetadataFromOcId(tag.ocId) else { continue }
itemIdentifierMetadata[providerUtility.getItemIdentifier(metadata: metadata)] = metadata
}
/// Favorite
fileProviderData.shared.listFavoriteIdentifierRank = NCManageDatabase.shared.getTableMetadatasDirectoryFavoriteIdentifierRank(account: fileProviderData.shared.account)
fileProviderData.shared.listFavoriteIdentifierRank = self.database.getTableMetadatasDirectoryFavoriteIdentifierRank(account: fileProviderData.shared.session.account)
for (identifier, _) in fileProviderData.shared.listFavoriteIdentifierRank {
guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(identifier) else { continue }
guard let metadata = self.database.getMetadataFromOcId(identifier) else { continue }
itemIdentifierMetadata[providerUtility.getItemIdentifier(metadata: metadata)] = metadata
}
/// Create items
@ -90,7 +91,7 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
self.fetchItemsForPage(serverUrl: serverUrl, pageNumber: pageNumber) { metadatas in
if let metadatas {
for metadata in metadatas {
if metadata.e2eEncrypted || (!metadata.session.isEmpty && metadata.session != NCNetworking.shared.sessionUploadBackgroundExtension) {
if metadata.e2eEncrypted || (!metadata.session.isEmpty && metadata.session != NCNetworking.shared.sessionUploadBackgroundExt) {
continue
}
if let parentItemIdentifier = self.providerUtility.getParentItemIdentifier(metadata: metadata) {
@ -157,25 +158,25 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
}
func fetchItemsForPage(serverUrl: String, pageNumber: Int, completionHandler: @escaping (_ metadatas: Results<tableMetadata>?) -> Void) {
let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.shared.account, serverUrl)
let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@", fileProviderData.shared.session.account, serverUrl)
if pageNumber == 1 {
NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: NCKeychain().showHiddenFiles, account: fileProviderData.shared.account) { _, files, _, error in
if error == .success {
NCManageDatabase.shared.convertFilesToMetadatas(files, useFirstAsMetadataFolder: true) { metadataFolder, metadatas in
NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrl, depth: "1", showHiddenFiles: NCKeychain().showHiddenFiles, account: fileProviderData.shared.session.account) { _, files, _, error in
if error == .success, let files {
self.database.convertFilesToMetadatas(files, useFirstAsMetadataFolder: true) { metadataFolder, metadatas in
/// FOLDER
NCManageDatabase.shared.addMetadata(metadataFolder)
NCManageDatabase.shared.addDirectory(e2eEncrypted: metadataFolder.e2eEncrypted, favorite: metadataFolder.favorite, ocId: metadataFolder.ocId, fileId: metadataFolder.fileId, etag: metadataFolder.etag, permissions: metadataFolder.permissions, richWorkspace: metadataFolder.richWorkspace, serverUrl: serverUrl, account: metadataFolder.account)
self.database.addMetadata(metadataFolder)
self.database.addDirectory(e2eEncrypted: metadataFolder.e2eEncrypted, favorite: metadataFolder.favorite, ocId: metadataFolder.ocId, fileId: metadataFolder.fileId, etag: metadataFolder.etag, permissions: metadataFolder.permissions, richWorkspace: metadataFolder.richWorkspace, serverUrl: serverUrl, account: metadataFolder.account)
/// FILES
NCManageDatabase.shared.deleteMetadata(predicate: predicate)
NCManageDatabase.shared.addMetadatas(metadatas)
self.database.deleteMetadata(predicate: predicate)
self.database.addMetadatas(metadatas)
}
}
let resultsMetadata = NCManageDatabase.shared.fetchPagedResults(ofType: tableMetadata.self, primaryKey: "ocId", recordsPerPage: self.recordsPerPage, pageNumber: pageNumber, filter: predicate, sortedByKeyPath: "fileName")
let resultsMetadata = self.database.fetchPagedResults(ofType: tableMetadata.self, primaryKey: "ocId", recordsPerPage: self.recordsPerPage, pageNumber: pageNumber, filter: predicate, sortedByKeyPath: "fileName")
completionHandler(resultsMetadata)
}
} else {
let resultsMetadata = NCManageDatabase.shared.fetchPagedResults(ofType: tableMetadata.self, primaryKey: "ocId", recordsPerPage: recordsPerPage, pageNumber: pageNumber, filter: predicate, sortedByKeyPath: "fileName")
let resultsMetadata = self.database.fetchPagedResults(ofType: tableMetadata.self, primaryKey: "ocId", recordsPerPage: recordsPerPage, pageNumber: pageNumber, filter: predicate, sortedByKeyPath: "fileName")
completionHandler(resultsMetadata)
}
}

Просмотреть файл

@ -27,23 +27,23 @@ import NextcloudKit
extension FileProviderExtension {
override func createDirectory(withName directoryName: String, inParentItemIdentifier parentItemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) {
guard let tableDirectory = providerUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.account, homeServerUrl: fileProviderData.shared.homeServerUrl) else {
guard let tableDirectory = providerUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.session.account, homeServerUrl: utilityFileSystem.getHomeServer(session: fileProviderData.shared.session)) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
let directoryName = utilityFileSystem.createFileName(directoryName, serverUrl: tableDirectory.serverUrl, account: fileProviderData.shared.account)
let directoryName = utilityFileSystem.createFileName(directoryName, serverUrl: tableDirectory.serverUrl, account: fileProviderData.shared.session.account)
let serverUrlFileName = tableDirectory.serverUrl + "/" + directoryName
NextcloudKit.shared.createFolder(serverUrlFileName: serverUrlFileName, account: fileProviderData.shared.account) { _, ocId, _, error in
NextcloudKit.shared.createFolder(serverUrlFileName: serverUrlFileName, account: fileProviderData.shared.session.account) { _, ocId, _, _, error in
if error == .success {
NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: NCKeychain().showHiddenFiles, account: fileProviderData.shared.account) { _, files, _, error in
if error == .success, let file = files.first {
NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: NCKeychain().showHiddenFiles, account: fileProviderData.shared.session.account) { _, files, _, error in
if error == .success, let file = files?.first {
let isDirectoryEncrypted = self.utilityFileSystem.isDirectoryE2EE(file: file)
let metadata = NCManageDatabase.shared.convertFileToMetadata(file, isDirectoryE2EE: isDirectoryEncrypted)
let metadata = self.database.convertFileToMetadata(file, isDirectoryE2EE: isDirectoryEncrypted)
NCManageDatabase.shared.addDirectory(e2eEncrypted: false, favorite: false, ocId: ocId!, fileId: metadata.fileId, etag: metadata.etag, permissions: metadata.permissions, serverUrl: serverUrlFileName, account: metadata.account)
NCManageDatabase.shared.addMetadata(metadata)
self.database.addDirectory(e2eEncrypted: false, favorite: false, ocId: ocId!, fileId: metadata.fileId, etag: metadata.etag, permissions: metadata.permissions, serverUrl: serverUrlFileName, account: metadata.account)
self.database.addMetadata(metadata)
guard let metadataInsert = NCManageDatabase.shared.getMetadataFromOcId(ocId!),
guard let metadataInsert = self.database.getMetadataFromOcId(ocId!),
let parentItemIdentifier = self.providerUtility.getParentItemIdentifier(metadata: metadataInsert) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
@ -69,7 +69,7 @@ extension FileProviderExtension {
let serverUrl = metadata.serverUrl
let fileName = metadata.fileName
NextcloudKit.shared.deleteFileOrFolder(serverUrlFileName: serverUrlFileName, account: metadata.account) { account, error in
NextcloudKit.shared.deleteFileOrFolder(serverUrlFileName: serverUrlFileName, account: metadata.account) { account, _, error in
if error == .success {
let fileNamePath = self.utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue)
@ -81,11 +81,11 @@ extension FileProviderExtension {
if isDirectory {
let dirForDelete = self.utilityFileSystem.stringAppendServerUrl(serverUrl, addFileName: fileName)
NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: dirForDelete, account: account)
self.database.deleteDirectoryAndSubDirectory(serverUrl: dirForDelete, account: account)
}
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", ocId))
NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", ocId))
self.database.deleteMetadataOcId(ocId)
self.database.deleteLocalFileOcId(ocId)
completionHandler(nil)
} else {
completionHandler(NSFileProviderError(.serverUnreachable))
@ -101,38 +101,41 @@ extension FileProviderExtension {
let ocIdFrom = metadataFrom.ocId
let serverUrlFrom = metadataFrom.serverUrl
let fileNameFrom = serverUrlFrom + "/" + itemFrom.filename
guard let tableDirectoryTo = providerUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.account, homeServerUrl: fileProviderData.shared.homeServerUrl) else {
guard let tableDirectoryTo = providerUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.session.account, homeServerUrl: utilityFileSystem.getHomeServer(session: fileProviderData.shared.session)) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
let serverUrlTo = tableDirectoryTo.serverUrl
let fileNameTo = serverUrlTo + "/" + itemFrom.filename
var fileNameTo = serverUrlTo + "/" + itemFrom.filename
if let newName {
fileNameTo = serverUrlTo + "/" + newName
}
NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: fileNameFrom, serverUrlFileNameDestination: fileNameTo, overwrite: false, account: metadataFrom.account) { account, error in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: fileNameFrom, serverUrlFileNameDestination: fileNameTo, overwrite: true, account: metadataFrom.account) { account, _, error in
if error == .success {
if metadataFrom.directory {
NCManageDatabase.shared.deleteDirectoryAndSubDirectory(serverUrl: serverUrlFrom, account: account)
NCManageDatabase.shared.renameDirectory(ocId: ocIdFrom, serverUrl: serverUrlTo)
self.database.deleteDirectoryAndSubDirectory(serverUrl: serverUrlFrom, account: account)
self.database.renameDirectory(ocId: ocIdFrom, serverUrl: serverUrlTo)
}
NCManageDatabase.shared.moveMetadata(ocId: ocIdFrom, serverUrlTo: serverUrlTo)
self.database.moveMetadata(ocId: ocIdFrom, serverUrlTo: serverUrlTo)
guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocIdFrom) else {
guard let metadata = self.database.getMetadataFromOcId(ocIdFrom) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
let item = FileProviderItem(metadata: metadata, parentItemIdentifier: parentItemIdentifier)
completionHandler(item, nil)
} else if error.errorCode == NCGlobal.shared.errorBadRequest {
completionHandler(nil, NSFileProviderError(.noSuchItem, userInfo: [NSLocalizedDescriptionKey: error.errorDescription, NSLocalizedFailureReasonErrorKey: ""]))
} else {
completionHandler(nil, NSFileProviderError(.serverUnreachable))
completionHandler(nil, NSFileProviderError(.noSuchItem, userInfo: [NSLocalizedDescriptionKey: error.errorDescription, NSLocalizedFailureReasonErrorKey: ""]))
}
}
}
}
override func renameItem(withIdentifier itemIdentifier: NSFileProviderItemIdentifier, toName itemName: String, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) {
guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier),
let directoryTable = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) else {
guard let metadata = providerUtility.getTableMetadataFromItemIdentifier(itemIdentifier) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
let fileNameFrom = metadata.fileNameView
@ -140,23 +143,15 @@ extension FileProviderExtension {
let fileNamePathTo = metadata.serverUrl + "/" + itemName
let ocId = metadata.ocId
NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: fileNamePathFrom, serverUrlFileNameDestination: fileNamePathTo, overwrite: false, account: metadata.account) { account, error in
NextcloudKit.shared.moveFileOrFolder(serverUrlFileNameSource: fileNamePathFrom, serverUrlFileNameDestination: fileNamePathTo, overwrite: false, account: metadata.account) { _, _, error in
if error == .success {
// Rename metadata
NCManageDatabase.shared.renameMetadata(fileNameTo: itemName, ocId: ocId)
guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else {
self.database.renameMetadata(fileNameNew: itemName, ocId: ocId)
self.database.setMetadataServeUrlFileNameStatusNormal(ocId: ocId)
guard let metadata = self.database.getMetadataFromOcId(ocId) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
if metadata.directory {
NCManageDatabase.shared.setDirectory(serverUrl: fileNamePathFrom, serverUrlTo: fileNamePathTo, encrypted: directoryTable.e2eEncrypted, account: account)
} else {
let itemIdentifier = self.providerUtility.getItemIdentifier(metadata: metadata)
self.providerUtility.moveFile(self.utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue, fileNameView: fileNameFrom), toPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(itemIdentifier.rawValue, fileNameView: itemName))
self.providerUtility.moveFile(self.utilityFileSystem.getDirectoryProviderStoragePreviewOcId(itemIdentifier.rawValue, etag: metadata.etag), toPath: self.utilityFileSystem.getDirectoryProviderStoragePreviewOcId(itemIdentifier.rawValue, etag: metadata.etag))
self.providerUtility.moveFile(self.utilityFileSystem.getDirectoryProviderStorageIconOcId(itemIdentifier.rawValue, etag: metadata.etag), toPath: self.utilityFileSystem.getDirectoryProviderStorageIconOcId(itemIdentifier.rawValue, etag: metadata.etag))
NCManageDatabase.shared.setLocalFile(ocId: ocId, fileName: itemName)
}
guard let parentItemIdentifier = self.providerUtility.getParentItemIdentifier(metadata: metadata) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
@ -188,20 +183,20 @@ extension FileProviderExtension {
}
if (favorite == true && metadata.favorite == false) || (favorite == false && metadata.favorite == true) {
let fileNamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId)
NextcloudKit.shared.setFavorite(fileName: fileNamePath, favorite: favorite, account: metadata.account) { _, error in
let fileNamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, session: fileProviderData.shared.session)
NextcloudKit.shared.setFavorite(fileName: fileNamePath, favorite: favorite, account: metadata.account) { _, _, error in
if error == .success {
guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else {
guard let metadata = self.database.getMetadataFromOcId(ocId) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
// Change DB
metadata.favorite = favorite
NCManageDatabase.shared.addMetadata(metadata)
self.database.addMetadata(metadata)
/// SIGNAL
let item = fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, type: .workingSet)
completionHandler(item, nil)
} else {
guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else {
guard let metadata = self.database.getMetadataFromOcId(ocId) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
// Errore, remove from listFavoriteIdentifierRank
@ -221,7 +216,7 @@ extension FileProviderExtension {
let ocId = metadataForTag.ocId
let account = metadataForTag.account
NCManageDatabase.shared.addTag(ocId, tagIOS: tagData, account: account)
self.database.addTag(ocId, tagIOS: tagData, account: account)
/// SIGNAL WORKINGSET
let item = fileProviderData.shared.signalEnumerator(ocId: ocId, type: .workingSet)
completionHandler(item, nil)

Просмотреть файл

@ -37,10 +37,19 @@ extension FileProviderExtension: NCNetworkingDelegate {
guard let url = task.currentRequest?.url,
let metadata = NCManageDatabase.shared.getMetadata(from: url, sessionTaskIdentifier: task.taskIdentifier) else { return }
DispatchQueue.global(qos: .userInteractive).async {
if let ocId, !metadata.ocIdTransfer.isEmpty {
let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocIdTransfer)
let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(ocId)
self.utilityFileSystem.copyFile(atPath: atPath, toPath: toPath)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if error == .success, let ocId {
/// SIGNAL
fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTemp, type: .delete)
fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTransfer, type: .delete)
if !metadata.ocIdTransfer.isEmpty, ocId != metadata.ocIdTransfer {
NCManageDatabase.shared.deleteMetadataOcId(metadata.ocIdTransfer)
}
metadata.fileName = fileName
metadata.serverUrl = serverUrl
metadata.uploadDate = (date as? NSDate) ?? NSDate()
@ -61,19 +70,13 @@ extension FileProviderExtension: NCNetworkingDelegate {
NCManageDatabase.shared.addMetadata(metadata)
NCManageDatabase.shared.addLocalFile(metadata: metadata)
/// NEW File
if !metadata.ocIdTemp.isEmpty, ocId != metadata.ocIdTemp {
let atPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocIdTemp)
let toPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(ocId)
self.utilityFileSystem.copyFile(atPath: atPath, toPath: toPath)
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocIdTemp))
}
/// SIGNAL
fileProviderData.shared.signalEnumerator(ocId: metadata.ocId, type: .update)
} else {
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocIdTemp))
NCManageDatabase.shared.deleteMetadataOcId(metadata.ocIdTransfer)
/// SIGNAL
fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTemp, type: .delete)
fileProviderData.shared.signalEnumerator(ocId: metadata.ocIdTransfer, type: .delete)
}
}
}

Просмотреть файл

@ -24,6 +24,7 @@
import UIKit
import FileProvider
import NextcloudKit
import Alamofire
extension FileProviderExtension {
override func fetchThumbnails(for itemIdentifiers: [NSFileProviderItemIdentifier], requestedSize size: CGSize, perThumbnailCompletionHandler: @escaping (NSFileProviderItemIdentifier, Data?, Error?) -> Void, completionHandler: @escaping (Error?) -> Void) -> Progress {
@ -36,14 +37,14 @@ extension FileProviderExtension {
if counterProgress == progress.totalUnitCount { completionHandler(nil) }
continue
}
let fileNameIconLocalPath = utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)
NextcloudKit.shared.downloadPreview(fileId: metadata.fileId, widthPreview: Int(size.width), heightPreview: Int(size.height), etag: metadata.etag, account: metadata.account) { _ in
} completion: { _, data, error in
if error == .success, let data {
do {
try data.write(to: URL(fileURLWithPath: fileNameIconLocalPath), options: .atomic)
} catch { }
NextcloudKit.shared.downloadPreview(fileId: metadata.fileId,
width: Int(size.width),
height: Int(size.height),
etag: metadata.etag,
account: metadata.account) { _ in
} completion: { _, _, _, _, responseData, error in
if error == .success, let data = responseData?.data {
perThumbnailCompletionHandler(itemIdentifier, data, nil)
} else {
perThumbnailCompletionHandler(itemIdentifier, nil, NSFileProviderError(.serverUnreachable))

Просмотреть файл

@ -55,16 +55,13 @@ import Alamofire
class FileProviderExtension: NSFileProviderExtension {
let providerUtility = fileProviderUtility()
let utilityFileSystem = NCUtilityFileSystem()
let database = NCManageDatabase.shared
override init() {
super.init()
// Create directory File Provider Storage
_ = utilityFileSystem.directoryProviderStorage
// Configure URLSession
_ = NCNetworking.shared.sessionManagerUploadBackgroundExtension
// Domains
// FileProviderDomain().registerDomains()
_ = fileProviderData.shared.setupAccount(domain: domain, providerExtension: self)
}
deinit {
@ -114,12 +111,12 @@ class FileProviderExtension: NSFileProviderExtension {
override func item(for identifier: NSFileProviderItemIdentifier) throws -> NSFileProviderItem {
if identifier == .rootContainer {
let metadata = tableMetadata()
metadata.account = fileProviderData.shared.account
metadata.account = fileProviderData.shared.session.account
metadata.directory = true
metadata.ocId = NSFileProviderItemIdentifier.rootContainer.rawValue
metadata.fileName = "root"
metadata.fileNameView = "root"
metadata.serverUrl = fileProviderData.shared.homeServerUrl
metadata.serverUrl = utilityFileSystem.getHomeServer(session: fileProviderData.shared.session)
metadata.classFile = NKCommon.TypeClassFile.directory.rawValue
return FileProviderItem(metadata: metadata, parentItemIdentifier: NSFileProviderItemIdentifier(NSFileProviderItemIdentifier.rootContainer.rawValue))
} else {
@ -170,24 +167,25 @@ class FileProviderExtension: NSFileProviderExtension {
if let result = fileProviderData.shared.getUploadMetadata(id: itemIdentifier.rawValue) {
metadata = result.metadata
} else {
metadata = NCManageDatabase.shared.getMetadataFromOcIdAndOcIdTemp(itemIdentifier.rawValue)
metadata = self.database.getMetadataFromOcIdAndocIdTransfer(itemIdentifier.rawValue)
}
guard let metadata else {
return completionHandler(NSFileProviderError(.noSuchItem))
}
if metadata.session == NCNetworking.shared.sessionUploadBackgroundExtension {
if metadata.session == NCNetworking.shared.sessionUploadBackgroundExt {
return completionHandler(nil)
}
let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName
let fileNameLocalPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileName)
// Exists ? return
if let tableLocalFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)),
if let tableLocalFile = self.database.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)),
utilityFileSystem.fileProviderStorageExists(metadata),
tableLocalFile.etag == metadata.etag {
return completionHandler(nil)
} else {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId,
session: NextcloudKit.shared.nkCommonInstance.sessionIdentifierDownload,
self.database.setMetadataSession(ocId: metadata.ocId,
session: NCNetworking.shared.sessionDownload,
sessionTaskIdentifier: 0,
sessionError: "",
selector: "",
status: NCGlobal.shared.metadataStatusDownloading)
@ -197,8 +195,8 @@ class FileProviderExtension: NSFileProviderExtension {
NextcloudKit.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, account: metadata.account, requestHandler: { _ in
}, taskHandler: { task in
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId,
taskIdentifier: task.taskIdentifier)
self.database.setMetadataSession(ocId: metadata.ocId,
sessionTaskIdentifier: task.taskIdentifier)
fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(itemIdentifier.rawValue)) { _ in }
}, progressHandler: { _ in
}) { _, etag, date, _, _, _, error in
@ -215,16 +213,16 @@ class FileProviderExtension: NSFileProviderExtension {
metadata.status = NCGlobal.shared.metadataStatusNormal
metadata.date = (date as? NSDate) ?? NSDate()
metadata.etag = etag ?? ""
NCManageDatabase.shared.addLocalFile(metadata: metadata)
NCManageDatabase.shared.addMetadata(metadata)
self.database.addLocalFile(metadata: metadata)
self.database.addMetadata(metadata)
completionHandler(nil)
} else if error.errorCode == 200 {
NCManageDatabase.shared.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusNormal)
self.database.setMetadataStatus(ocId: metadata.ocId, status: NCGlobal.shared.metadataStatusNormal)
completionHandler(nil)
} else {
metadata.status = NCGlobal.shared.metadataStatusDownloadError
metadata.sessionError = error.errorDescription
NCManageDatabase.shared.addMetadata(metadata)
self.database.addMetadata(metadata)
completionHandler(NSFileProviderError(.noSuchItem))
}
/// SIGNAL
@ -242,33 +240,44 @@ class FileProviderExtension: NSFileProviderExtension {
if let result = fileProviderData.shared.getUploadMetadata(id: itemIdentifier.rawValue) {
metadata = result.metadata
} else {
metadata = NCManageDatabase.shared.getMetadataFromOcIdAndOcIdTemp(itemIdentifier.rawValue)
metadata = self.database.getMetadataFromOcIdAndocIdTransfer(itemIdentifier.rawValue)
}
guard let metadata else {
return
}
let serverUrlFileName = metadata.serverUrl + "/" + fileName
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId,
session: NCNetworking.shared.sessionUploadBackgroundExtension,
self.database.setMetadataSession(ocId: metadata.ocId,
session: NCNetworking.shared.sessionUploadBackgroundExt,
sessionTaskIdentifier: 0,
sessionError: "",
selector: "",
status: NCGlobal.shared.metadataStatusUploading)
if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: url.path, dateCreationFile: nil, dateModificationFile: nil, account: metadata.account, session: NCNetworking.shared.sessionManagerUploadBackgroundExtension) {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId,
status: NCGlobal.shared.metadataStatusUploading,
taskIdentifier: task.taskIdentifier)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName,
fileNameLocalPath: url.path,
dateCreationFile: nil,
dateModificationFile: nil,
overwrite: true,
account: metadata.account,
sessionIdentifier: metadata.session) {
self.database.setMetadataSession(ocId: metadata.ocId,
sessionTaskIdentifier: task.taskIdentifier,
status: NCGlobal.shared.metadataStatusUploading)
fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(metadata.fileId)) { _ in }
}
}
}
override func stopProvidingItem(at url: URL) {
let pathComponents = url.pathComponents
assert(pathComponents.count > 2)
let itemIdentifier = NSFileProviderItemIdentifier(pathComponents[pathComponents.count - 2])
guard let metadata = NCManageDatabase.shared.getMetadataFromOcIdAndOcIdTemp(itemIdentifier.rawValue) else { return }
if metadata.session == NextcloudKit.shared.nkCommonInstance.sessionIdentifierDownload {
NextcloudKit.shared.sessionManager.session.getTasksWithCompletionHandler { _, _, downloadTasks in
guard let metadata = self.database.getMetadataFromOcIdAndocIdTransfer(itemIdentifier.rawValue) else { return }
if metadata.session == NCNetworking.shared.sessionDownload {
let session = NextcloudKit.shared.nkCommonInstance.getSession(account: metadata.session)?.sessionData.session
session?.getTasksWithCompletionHandler { _, _, downloadTasks in
downloadTasks.forEach { task in
if metadata.sessionTaskIdentifier == task.taskIdentifier {
task.cancel()
@ -281,7 +290,7 @@ class FileProviderExtension: NSFileProviderExtension {
override func importDocument(at fileURL: URL, toParentItemIdentifier parentItemIdentifier: NSFileProviderItemIdentifier, completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void) {
DispatchQueue.main.async {
autoreleasepool {
guard let tableDirectory = self.providerUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.account, homeServerUrl: fileProviderData.shared.homeServerUrl) else {
guard let tableDirectory = self.providerUtility.getTableDirectoryFromParentItemIdentifier(parentItemIdentifier, account: fileProviderData.shared.session.account, homeServerUrl: self.utilityFileSystem.getHomeServer(session: fileProviderData.shared.session)) else {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
var size = 0 as Int64
@ -299,34 +308,48 @@ class FileProviderExtension: NSFileProviderExtension {
return completionHandler(nil, NSFileProviderError(.noSuchItem))
}
let fileName = self.utilityFileSystem.createFileName(fileURL.lastPathComponent, serverUrl: tableDirectory.serverUrl, account: fileProviderData.shared.account)
let ocIdTemp = NSUUID().uuidString.lowercased()
let fileName = self.utilityFileSystem.createFileName(fileURL.lastPathComponent, serverUrl: tableDirectory.serverUrl, account: fileProviderData.shared.session.account)
let ocIdTransfer = NSUUID().uuidString.lowercased()
NSFileCoordinator().coordinate(readingItemAt: fileURL, options: .withoutChanges, error: &error) { url in
self.providerUtility.copyFile(url.path, toPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTemp, fileNameView: fileName))
self.providerUtility.copyFile(url.path, toPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTransfer, fileNameView: fileName))
}
fileURL.stopAccessingSecurityScopedResource()
let metadata = NCManageDatabase.shared.createMetadata(account: fileProviderData.shared.account, user: fileProviderData.shared.user, userId: fileProviderData.shared.userId, fileName: fileName, fileNameView: fileName, ocId: ocIdTemp, serverUrl: tableDirectory.serverUrl, urlBase: fileProviderData.shared.accountUrlBase, url: "", contentType: "")
metadata.session = NCNetworking.shared.sessionUploadBackgroundExtension
metadata.size = size
metadata.status = NCGlobal.shared.metadataStatusUploading
let metadataForUpload = self.database.createMetadata(fileName: fileName,
fileNameView: fileName,
ocId: ocIdTransfer,
serverUrl: tableDirectory.serverUrl,
url: "",
contentType: "",
session: fileProviderData.shared.session,
sceneIdentifier: nil)
NCManageDatabase.shared.addMetadata(metadata)
metadataForUpload.session = NCNetworking.shared.sessionUploadBackgroundExt
metadataForUpload.size = size
metadataForUpload.status = NCGlobal.shared.metadataStatusUploading
self.database.addMetadata(metadataForUpload)
let serverUrlFileName = tableDirectory.serverUrl + "/" + fileName
let fileNameLocalPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTemp, fileNameView: fileName)
let fileNameLocalPath = self.utilityFileSystem.getDirectoryProviderStorageOcId(ocIdTransfer, fileNameView: fileName)
if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, dateCreationFile: nil, dateModificationFile: nil, account: metadata.account, session: NCNetworking.shared.sessionManagerUploadBackgroundExtension) {
NCManageDatabase.shared.setMetadataSession(ocId: metadata.ocId,
status: NCGlobal.shared.metadataStatusUploading,
taskIdentifier: task.taskIdentifier)
fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(ocIdTemp)) { _ in }
fileProviderData.shared.appendUploadMetadata(id: ocIdTemp, metadata: metadata, task: task)
if let task = NKBackground(nkCommonInstance: NextcloudKit.shared.nkCommonInstance).upload(serverUrlFileName: serverUrlFileName,
fileNameLocalPath: fileNameLocalPath,
dateCreationFile: nil,
dateModificationFile: nil,
overwrite: true,
account: metadataForUpload.account,
sessionIdentifier: metadataForUpload.session) {
self.database.setMetadataSession(ocId: metadataForUpload.ocId,
sessionTaskIdentifier: task.taskIdentifier,
status: NCGlobal.shared.metadataStatusUploading)
fileProviderData.shared.fileProviderManager.register(task, forItemWithIdentifier: NSFileProviderItemIdentifier(ocIdTransfer)) { _ in }
fileProviderData.shared.appendUploadMetadata(id: ocIdTransfer, metadata: metadataForUpload, task: task)
}
let item = FileProviderItem(metadata: tableMetadata.init(value: metadata), parentItemIdentifier: parentItemIdentifier)
let item = FileProviderItem(metadata: tableMetadata.init(value: metadataForUpload), parentItemIdentifier: parentItemIdentifier)
completionHandler(item, nil)
}
}

Просмотреть файл

@ -36,7 +36,7 @@ class FileProviderItem: NSObject, NSFileProviderItem {
return metadata.fileNameView
}
var typeIdentifier: String {
let results = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: metadata.fileNameView, mimeType: "", directory: metadata.directory)
let results = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: metadata.fileNameView, mimeType: "", directory: metadata.directory, account: metadata.account)
return results.typeIdentifier
}
var capabilities: NSFileProviderItemCapabilities {

Просмотреть файл

@ -26,15 +26,16 @@ import UIKit
class fileProviderUtility: NSObject {
let fileManager = FileManager()
let utilityFileSystem = NCUtilityFileSystem()
let database = NCManageDatabase.shared
func getAccountFromItemIdentifier(_ itemIdentifier: NSFileProviderItemIdentifier) -> String? {
let ocId = itemIdentifier.rawValue
return NCManageDatabase.shared.getMetadataFromOcId(ocId)?.account
return self.database.getMetadataFromOcId(ocId)?.account
}
func getTableMetadataFromItemIdentifier(_ itemIdentifier: NSFileProviderItemIdentifier) -> tableMetadata? {
let ocId = itemIdentifier.rawValue
return NCManageDatabase.shared.getMetadataFromOcId(ocId)
return self.database.getMetadataFromOcId(ocId)
}
func getItemIdentifier(metadata: tableMetadata) -> NSFileProviderItemIdentifier {
@ -42,13 +43,13 @@ class fileProviderUtility: NSObject {
}
func getParentItemIdentifier(metadata: tableMetadata) -> NSFileProviderItemIdentifier? {
let homeServerUrl = utilityFileSystem.getHomeServer(urlBase: metadata.urlBase, userId: metadata.userId)
if let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) {
let homeServerUrl = utilityFileSystem.getHomeServer(session: fileProviderData.shared.session)
if let directory = self.database.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, metadata.serverUrl)) {
if directory.serverUrl == homeServerUrl {
return NSFileProviderItemIdentifier(NSFileProviderItemIdentifier.rootContainer.rawValue)
} else {
// get the metadata.ocId of parent Directory
if let metadata = NCManageDatabase.shared.getMetadataFromOcId(directory.ocId) {
if let metadata = self.database.getMetadataFromOcId(directory.ocId) {
let identifier = getItemIdentifier(metadata: metadata)
return identifier
}
@ -65,7 +66,7 @@ class fileProviderUtility: NSObject {
guard let metadata = getTableMetadataFromItemIdentifier(parentItemIdentifier) else { return nil }
predicate = NSPredicate(format: "ocId == %@", metadata.ocId)
}
guard let directory = NCManageDatabase.shared.getTableDirectory(predicate: predicate) else { return nil }
guard let directory = self.database.getTableDirectory(predicate: predicate) else { return nil }
return directory
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -120,8 +120,12 @@
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<RemoteRunnable
runnableDebuggingMode = "0"
BundleIdentifier = "it.twsweb.Nextcloud"
RemotePath = "/var/containers/Bundle/Application/92F13FE8-7056-4509-8468-5856675AB1CA/Nextcloud.app">
</RemoteRunnable>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F77B0DEB1D118A16002130FE"
@ -129,7 +133,7 @@
BlueprintName = "Nextcloud"
ReferencedContainer = "container:Nextcloud.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</MacroExpansion>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

Просмотреть файл

@ -121,9 +121,9 @@
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<RemoteRunnable
runnableDebuggingMode = "1"
runnableDebuggingMode = "0"
BundleIdentifier = "it.twsweb.Nextcloud"
RemotePath = "/Users/marinofaggiana/Library/Developer/CoreSimulator/Devices/4DBB1715-4E24-4CE7-B67C-CA327B95130C/data/Containers/Bundle/Application/F427D7FF-1632-4BB9-ADEA-A094898BB6C7/Nextcloud.app">
RemotePath = "/var/containers/Bundle/Application/92F13FE8-7056-4509-8468-5856675AB1CA/Nextcloud.app">
</RemoteRunnable>
<MacroExpansion>
<BuildableReference

Просмотреть файл

@ -36,8 +36,7 @@ class NotificationService: UNNotificationServiceExtension {
bestAttemptContent.body = "Nextcloud notification"
do {
if let message = bestAttemptContent.userInfo["subject"] as? String {
let tableAccounts = NCManageDatabase.shared.getAllAccount()
for tableAccount in tableAccounts {
for tableAccount in NCManageDatabase.shared.getAllTableAccount() {
guard let privateKey = NCKeychain().getPushNotificationPrivateKey(account: tableAccount.account),
let decryptedMessage = NCPushNotificationEncryption.shared().decryptPushNotification(message, withDevicePrivateKey: privateKey),
let data = decryptedMessage.data(using: .utf8) else {

Просмотреть файл

@ -38,18 +38,10 @@ branch. Maybe start working on [starter issues](https://github.com/nextcloud/ios
Easy starting points are also reviewing [pull requests](https://github.com/nextcloud/ios/pulls)
### Xcode 15 Project Setup
### Xcode 16 Project Setup
#### Dependencies
After forking a repository you have to build the dependencies. Dependencies are managed with Carthage version 0.38.0 or later.
Run
```
carthage update --use-xcframeworks --platform iOS
```
to fetch and compile the dependencies.
In order to build the project in Xcode you will also need a file `GoogleService-Info.plist` at the root of the repository which contains the Firebase configuration. For development work you can use a mock version found [here](https://github.com/firebase/quickstart-ios/blob/master/mock-GoogleService-Info.plist).
### Creating Pull requests

Просмотреть файл

@ -27,7 +27,7 @@ import NextcloudKit
protocol NCShareCellDelegate: AnyObject {
var uploadStarted: Bool { get }
func removeFile(named fileName: String)
func renameFile(named fileName: String)
func renameFile(named fileName: String, account: String)
}
class NCShareCell: UITableViewCell {
@ -36,13 +36,15 @@ class NCShareCell: UITableViewCell {
@IBOutlet weak var moreButton: UIButton!
@IBOutlet weak var sizeCell: UILabel!
weak var delegate: (NCShareCellDelegate & UIViewController)?
var fileName = ""
var fileName: String = ""
var account: String = ""
let utilityFileSystem = NCUtilityFileSystem()
let utility = NCUtility()
func setup(fileName: String) {
func setup(fileName: String, account: String) {
self.fileName = fileName
let resultInternalType = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: fileName, mimeType: "", directory: false)
self.account = account
let resultInternalType = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: fileName, mimeType: "", directory: false, account: account)
backgroundColor = .systemBackground
imageCell?.layer.cornerRadius = 6
@ -52,7 +54,7 @@ class NCShareCell: UITableViewCell {
imageCell.image = image
imageCell.contentMode = .scaleAspectFill
} else {
imageCell.image = utility.loadImage(named: resultInternalType.iconName, useTypeIconFile: true)
imageCell.image = utility.loadImage(named: resultInternalType.iconName, useTypeIconFile: true, account: account)
imageCell.contentMode = .scaleAspectFit
}
@ -61,7 +63,7 @@ class NCShareCell: UITableViewCell {
let fileSize = utilityFileSystem.getFileSize(filePath: (NSTemporaryDirectory() + fileName))
sizeCell?.text = utilityFileSystem.transformedSize(fileSize)
moreButton?.setImage(NCImageCache.images.buttonMore, for: .normal)
moreButton?.setImage(NCImageCache.shared.getImageButtonMore(), for: .normal)
}
@IBAction func buttonTapped(_ sender: Any) {
@ -69,7 +71,7 @@ class NCShareCell: UITableViewCell {
let alertController = UIAlertController(title: "", message: fileName, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("_rename_file_", comment: ""), style: .default) { _ in
self.delegate?.renameFile(named: self.fileName)
self.delegate?.renameFile(named: self.fileName, account: self.account)
})
alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_file_", comment: ""), style: .default) { _ in

Просмотреть файл

@ -27,15 +27,14 @@ import NextcloudKit
// MARK: - Collection View (target folder)
extension NCShareExtension: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let metadata = dataSource.cellForItemAt(indexPath: indexPath) else { return showAlert(description: "_invalid_url_") }
guard let metadata = self.dataSource.getMetadata(indexPath: indexPath) else { return showAlert(description: "_invalid_url_") }
let serverUrl = utilityFileSystem.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName)
if metadata.e2eEncrypted && !NCKeychain().isEndToEndEnabled(account: activeAccount.account) {
if metadata.e2eEncrypted && !NCKeychain().isEndToEndEnabled(account: session.account) {
showAlert(title: "_info_", description: "_e2e_goto_settings_for_enable_")
}
if let fileNameError = FileNameValidator.shared.checkFileName(metadata.fileNameView) {
if let fileNameError = FileNameValidator.shared.checkFileName(metadata.fileNameView, account: session.account) {
present(UIAlertController.warning(message: "\(fileNameError.errorDescription) \(NSLocalizedString("_please_rename_file_", comment: ""))"), animated: true)
return
}
@ -49,11 +48,11 @@ extension NCShareExtension: UICollectionViewDelegate {
if kind == UICollectionView.elementKindSectionHeader {
guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFirstHeaderEmptyData", for: indexPath) as? NCSectionFirstHeaderEmptyData else { return NCSectionFirstHeaderEmptyData() }
if self.dataSourceTask?.state == .running {
header.emptyImage.image = utility.loadImage(named: "wifi", colors: [NCBrandColor.shared.brandElement])
header.emptyImage.image = utility.loadImage(named: "wifi", colors: [NCBrandColor.shared.getElement(account: session.account)])
header.emptyTitle.text = NSLocalizedString("_request_in_progress_", comment: "")
header.emptyDescription.text = ""
} else {
header.emptyImage.image = NCImageCache.images.folder
header.emptyImage.image = NCImageCache.shared.getFolder(account: self.session.account)
header.emptyTitle.text = NSLocalizedString("_files_no_folders_", comment: "")
header.emptyDescription.text = ""
}
@ -67,30 +66,30 @@ extension NCShareExtension: UICollectionViewDelegate {
extension NCShareExtension: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
var height: CGFloat = 0
if dataSource.getMetadataSourceForAllSections().isEmpty {
height = NCGlobal.shared.getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -50)
if self.dataSource.isEmpty() {
height = NCUtility().getHeightHeaderEmptyData(view: view, portraitOffset: 0, landscapeOffset: -50)
}
return CGSize(width: collectionView.frame.width, height: height)
}
}
extension NCShareExtension: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return dataSource.numberOfSections()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataSource.numberOfItemsInSection(section)
return self.dataSource.numberOfItemsInSection(section)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let metadata = dataSource.cellForItemAt(indexPath: indexPath), let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as? NCListCell else {
return UICollectionViewCell()
let cell = (collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as? NCListCell)!
guard let metadata = self.dataSource.getMetadata(indexPath: indexPath) else {
return cell
}
cell.fileObjectId = metadata.ocId
cell.indexPath = indexPath
cell.fileOcId = metadata.ocId
cell.fileOcIdTransfer = metadata.ocIdTransfer
cell.fileUser = metadata.ownerId
cell.labelTitle.text = metadata.fileNameView
cell.labelTitle.textColor = NCBrandColor.shared.textColor
@ -102,14 +101,13 @@ extension NCShareExtension: UICollectionViewDataSource {
cell.imageMore.image = nil
cell.imageItem.image = nil
cell.imageItem.backgroundColor = nil
cell.progressView.progress = 0.0
if metadata.directory {
setupDirectoryCell(cell, indexPath: indexPath, with: metadata)
}
if metadata.favorite {
cell.imageFavorite.image = NCImageCache.images.favorite
cell.imageFavorite.image = NCImageCache.shared.getImageFavorite()
}
cell.imageSelect.isHidden = true
@ -119,7 +117,7 @@ extension NCShareExtension: UICollectionViewDataSource {
cell.selected(false, isEditMode: false)
if metadata.isLivePhoto {
cell.imageStatus.image = NCImageCache.images.livePhoto
cell.imageStatus.image = utility.loadImage(named: "livephoto", colors: [NCBrandColor.shared.iconImageColor2])
}
cell.setTags(tags: Array(metadata.tags))
@ -139,31 +137,31 @@ extension NCShareExtension: UICollectionViewDataSource {
}
if metadata.e2eEncrypted {
cell.imageItem.image = NCImageCache.images.folderEncrypted
cell.imageItem.image = NCImageCache.shared.getFolderEncrypted(account: metadata.account)
} else if isShare {
cell.imageItem.image = NCImageCache.images.folderSharedWithMe
cell.imageItem.image = NCImageCache.shared.getFolderSharedWithMe(account: metadata.account)
} else if !metadata.shareType.isEmpty {
metadata.shareType.contains(3) ?
(cell.imageItem.image = NCImageCache.images.folderPublic) :
(cell.imageItem.image = NCImageCache.images.folderSharedWithMe)
(cell.imageItem.image = NCImageCache.shared.getFolderPublic(account: metadata.account)) :
(cell.imageItem.image = NCImageCache.shared.getFolderSharedWithMe(account: metadata.account))
} else if metadata.mountType == "group" {
cell.imageItem.image = NCImageCache.images.folderGroup
cell.imageItem.image = NCImageCache.shared.getFolderGroup(account: metadata.account)
} else if isMounted {
cell.imageItem.image = NCImageCache.images.folderExternal
cell.imageItem.image = NCImageCache.shared.getFolderExternal(account: metadata.account)
} else if metadata.fileName == autoUploadFileName && metadata.serverUrl == autoUploadDirectory {
cell.imageItem.image = NCImageCache.images.folderAutomaticUpload
cell.imageItem.image = NCImageCache.shared.getFolderAutomaticUpload(account: metadata.account)
} else {
cell.imageItem.image = NCImageCache.images.folder
cell.imageItem.image = NCImageCache.shared.getFolder(account: metadata.account)
}
cell.labelInfo.text = utility.dateDiff(metadata.date as Date)
let lockServerUrl = utilityFileSystem.stringAppendServerUrl(metadata.serverUrl, addFileName: metadata.fileName)
let tableDirectory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", activeAccount.account, lockServerUrl))
let tableDirectory = self.database.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", session.account, lockServerUrl))
// Local image: offline
if tableDirectory != nil && tableDirectory!.offline {
cell.imageLocal.image = NCImageCache.images.offlineFlag
cell.imageLocal.image = NCImageCache.shared.getImageOfflineFlag()
}
}
}
@ -171,7 +169,6 @@ extension NCShareExtension: UICollectionViewDataSource {
// MARK: - Table View (uploading files)
extension NCShareExtension: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return heightRowTableView
}
@ -179,12 +176,11 @@ extension NCShareExtension: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard !uploadStarted else { return }
let fileName = filesName[indexPath.row]
renameFile(named: fileName)
renameFile(named: fileName, account: session.account)
}
}
extension NCShareExtension: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
filesName.count
}
@ -192,7 +188,7 @@ extension NCShareExtension: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? NCShareCell else { return UITableViewCell() }
let fileName = filesName[indexPath.row]
cell.setup(fileName: fileName)
cell.setup(fileName: fileName, account: session.account)
cell.delegate = self
return cell
}

Просмотреть файл

@ -22,14 +22,16 @@
//
import Foundation
import UIKit
import UniformTypeIdentifiers
import NextcloudKit
extension NCShareExtension {
@objc func reloadDatasource(withLoadFolder: Bool) {
layoutForView = NCManageDatabase.shared.setLayoutForView(account: activeAccount.account, key: keyLayout, serverUrl: serverUrl)
let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND directory == true", activeAccount.account, serverUrl))
self.dataSource = NCDataSource(metadatas: metadatas, account: activeAccount.account, layoutForView: layoutForView)
let predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND directory == true", session.account, serverUrl)
let results = self.database.getResultsMetadatasPredicate(predicate, layoutForView: NCDBLayoutForView())
self.dataSource = NCCollectionViewDataSource(results: results)
if withLoadFolder {
loadFolder()
@ -42,7 +44,7 @@ extension NCShareExtension {
@objc func didCreateFolder(_ notification: NSNotification) {
guard let userInfo = notification.userInfo as NSDictionary?,
let ocId = userInfo["ocId"] as? String,
let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId)
let metadata = self.database.getMetadataFromOcId(ocId)
else { return }
self.serverUrl += "/" + metadata.fileName
@ -51,10 +53,13 @@ extension NCShareExtension {
}
func loadFolder() {
NCNetworking.shared.readFolder(serverUrl: serverUrl, account: activeAccount.account) { task in
NCNetworking.shared.readFolder(serverUrl: serverUrl,
account: session.account,
checkResponseDataChanged: false,
queue: .main) { task in
self.dataSourceTask = task
self.collectionView.reloadData()
} completion: { _, metadataFolder, _, _, _, error in
} completion: { _, metadataFolder, _, _, error in
DispatchQueue.main.async {
if error != .success {
self.showAlert(description: error.errorDescription)

Просмотреть файл

@ -29,16 +29,16 @@ extension NCShareExtension: NCAccountRequestDelegate {
// MARK: - Account
func showAccountPicker() {
let accounts = NCManageDatabase.shared.getAllAccountOrderAlias()
let accounts = self.database.getAllAccountOrderAlias()
guard accounts.count > 1,
let vcAccountRequest = UIStoryboard(name: "NCAccountRequest", bundle: nil).instantiateInitialViewController() as? NCAccountRequest else { return }
// Only here change the active account
for account in accounts {
account.active = account.account == self.activeAccount.account
account.active = account.account == session.account
}
vcAccountRequest.activeAccount = self.activeAccount
vcAccountRequest.activeAccount = self.session.account
vcAccountRequest.accounts = accounts.sorted { sorg, dest -> Bool in
return sorg.active && !dest.active
}
@ -57,49 +57,37 @@ extension NCShareExtension: NCAccountRequestDelegate {
func accountRequestAddAccount() { }
func accountRequestChangeAccount(account: String) {
guard let activeAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)) else {
func accountRequestChangeAccount(account: String, controller: UIViewController?) {
guard let tableAccount = self.database.getTableAccount(predicate: NSPredicate(format: "account == %@", account)),
let capabilities = self.database.setCapabilities(account: account) else {
cancel(with: NCShareExtensionError.noAccount)
return
}
self.activeAccount = activeAccount
// CAPABILITIES
NCManageDatabase.shared.setCapabilities(account: account)
self.account = account
// COLORS
NCBrandColor.shared.settingThemingColor(account: activeAccount.account)
NCBrandColor.shared.createUserColors()
NCImageCache.shared.createImagesBrandCache()
NCBrandColor.shared.settingThemingColor(account: account)
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeTheming, userInfo: ["account": account])
// NETWORKING
NextcloudKit.shared.setup(
account: activeAccount.account,
user: activeAccount.user,
userId: activeAccount.userId,
password: NCKeychain().getPassword(account: activeAccount.account),
urlBase: activeAccount.urlBase,
NextcloudKit.shared.setup(delegate: NCNetworking.shared)
NextcloudKit.shared.appendSession(account: tableAccount.account,
urlBase: tableAccount.urlBase,
user: tableAccount.user,
userId: tableAccount.userId,
password: NCKeychain().getPassword(account: tableAccount.account),
userAgent: userAgent,
nextcloudVersion: 0,
delegate: NCNetworking.shared)
nextcloudVersion: capabilities.capabilityServerVersionMajor,
groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
// get auto upload folder
autoUploadFileName = NCManageDatabase.shared.getAccountAutoUploadFileName()
autoUploadDirectory = NCManageDatabase.shared.getAccountAutoUploadDirectory(urlBase: activeAccount.urlBase, userId: activeAccount.userId, account: activeAccount.account)
autoUploadFileName = self.database.getAccountAutoUploadFileName()
autoUploadDirectory = self.database.getAccountAutoUploadDirectory(session: session)
serverUrl = utilityFileSystem.getHomeServer(urlBase: activeAccount.urlBase, userId: activeAccount.userId)
layoutForView = NCManageDatabase.shared.getLayoutForView(account: activeAccount.account, key: keyLayout, serverUrl: serverUrl)
serverUrl = utilityFileSystem.getHomeServer(session: session)
reloadDatasource(withLoadFolder: true)
setNavigationBar(navigationTitle: NCBrandOptions.shared.brand)
FileNameValidator.shared.setup(
forbiddenFileNames: NCGlobal.shared.capabilityForbiddenFileNames,
forbiddenFileNameBasenames: NCGlobal.shared.capabilityForbiddenFileNameBasenames,
forbiddenFileNameCharacters: NCGlobal.shared.capabilityForbiddenFileNameCharacters,
forbiddenFileNameExtensions: NCGlobal.shared.capabilityForbiddenFileNameExtensions
)
}
}
@ -117,20 +105,8 @@ extension NCShareExtension: NCCreateFormUploadConflictDelegate {
}
extension NCShareExtension: NCShareCellDelegate {
func removeFile(named fileName: String) {
guard let index = self.filesName.firstIndex(of: fileName) else {
return showAlert(title: "_file_not_found_", description: fileName)
}
self.filesName.remove(at: index)
if self.filesName.isEmpty {
cancel(with: NCShareExtensionError.noFiles)
} else {
self.setCommandView()
}
}
func renameFile(named fileName: String) {
let alert = UIAlertController.renameFile(fileName: fileName) { [self] newFileName in
func renameFile(named fileName: String, account: String) {
let alert = UIAlertController.renameFile(fileName: fileName, account: account) { [self] newFileName in
guard let fileIx = self.filesName.firstIndex(of: fileName),
!self.filesName.contains(newFileName),
utilityFileSystem.moveFile(atPath: (NSTemporaryDirectory() + fileName), toPath: (NSTemporaryDirectory() + newFileName)) else {
@ -143,4 +119,16 @@ extension NCShareExtension: NCShareCellDelegate {
present(alert, animated: true)
}
func removeFile(named fileName: String) {
guard let index = self.filesName.firstIndex(of: fileName) else {
return showAlert(title: "_file_not_found_", description: fileName)
}
self.filesName.remove(at: index)
if self.filesName.isEmpty {
cancel(with: NCShareExtensionError.noFiles)
} else {
self.setCommandView()
}
}
}

Просмотреть файл

@ -25,15 +25,12 @@
import UIKit
import NextcloudKit
import JGProgressHUD
import TOPasscodeViewController
enum NCShareExtensionError: Error {
case cancel, fileUpload, noAccount, noFiles
}
class NCShareExtension: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var cancelButton: UIBarButtonItem!
@ -57,22 +54,33 @@ class NCShareExtension: UIViewController {
let keyLayout = NCGlobal.shared.layoutViewShareExtension
var metadataFolder: tableMetadata?
var dataSourceTask: URLSessionTask?
var dataSource = NCDataSource()
var layoutForView: NCDBLayoutForView?
var dataSource = NCCollectionViewDataSource()
let heightRowTableView: CGFloat = 50
let heightCommandView: CGFloat = 170
var autoUploadFileName = ""
var autoUploadDirectory = ""
let refreshControl = UIRefreshControl()
var activeAccount: tableAccount!
var progress: CGFloat = 0
var counterUploaded: Int = 0
var uploadErrors: [tableMetadata] = []
var uploadMetadata: [tableMetadata] = []
var uploadStarted = false
let hud = JGProgressHUD()
let hud = NCHud()
let utilityFileSystem = NCUtilityFileSystem()
let utility = NCUtility()
let database = NCManageDatabase.shared
var account: String = ""
var session: NCSession.Session {
if !account.isEmpty,
let tableAccount = self.database.getTableAccount(account: account) {
return NCSession.Session(account: tableAccount.account, urlBase: tableAccount.urlBase, user: tableAccount.user, userId: tableAccount.userId)
} else if let activeTableAccount = self.database.getActiveTableAccount() {
self.account = activeTableAccount.account
return NCSession.Session(account: activeTableAccount.account, urlBase: activeTableAccount.urlBase, user: activeTableAccount.user, userId: activeTableAccount.userId)
} else {
return NCSession.Session(account: "", urlBase: "", user: "", userId: "")
}
}
// MARK: - View Life Cycle
@ -86,7 +94,7 @@ class NCShareExtension: UIViewController {
collectionView.collectionViewLayout = NCListLayout()
collectionView.refreshControl = refreshControl
refreshControl.tintColor = NCBrandColor.shared.brandText
refreshControl.tintColor = NCBrandColor.shared.iconImageColor
refreshControl.backgroundColor = .systemBackground
refreshControl.addTarget(self, action: #selector(reloadDatasource), for: .valueChanged)
@ -125,33 +133,20 @@ class NCShareExtension: UIViewController {
NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Start Share session with level \(levelLog) " + versionNextcloudiOS)
}
// Colors
if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
NCBrandColor.shared.settingThemingColor(account: activeAccount.account)
}
NCBrandColor.shared.createUserColors()
NCImageCache.shared.createImagesCache()
NCImageCache.shared.createImagesBrandCache()
hud.indicatorView = JGProgressHUDRingIndicatorView()
if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView {
indicatorView.ringWidth = 1.5
indicatorView.ringColor = NCBrandColor.shared.brandElement
}
NotificationCenter.default.addObserver(self, selector: #selector(didCreateFolder(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterCreateFolder), object: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard serverUrl.isEmpty else { return }
guard let activeAccount = NCManageDatabase.shared.getActiveAccount(),
guard !session.account.isEmpty,
!NCPasscode.shared.isPasscodeReset else {
return showAlert(description: "_no_active_account_") {
self.cancel(with: .noAccount)
}
}
accountRequestChangeAccount(account: activeAccount.account)
accountRequestChangeAccount(account: account, controller: nil)
guard let inputItems = extensionContext?.inputItems as? [NSExtensionItem] else {
cancel(with: .noFiles)
return
@ -197,7 +192,6 @@ class NCShareExtension: UIViewController {
}
func setNavigationBar(navigationTitle: String) {
navigationItem.title = navigationTitle
cancelButton.title = NSLocalizedString("_cancel_", comment: "")
@ -212,28 +206,26 @@ class NCShareExtension: UIViewController {
if !self.uploadStarted {
while self.serverUrl.last != "/" { self.serverUrl.removeLast() }
self.serverUrl.removeLast()
self.reloadDatasource(withLoadFolder: true)
var navigationTitle = (self.serverUrl as NSString).lastPathComponent
if self.utilityFileSystem.getHomeServer(urlBase: self.activeAccount.urlBase, userId: self.activeAccount.userId) == self.serverUrl {
if self.utilityFileSystem.getHomeServer(session: self.session) == self.serverUrl {
navigationTitle = NCBrandOptions.shared.brand
}
self.setNavigationBar(navigationTitle: navigationTitle)
}
}
let image = utility.loadUserImage(for: activeAccount.user, displayName: activeAccount.displayName, userBaseUrl: activeAccount)
let tableAccount = self.database.getTableAccount(account: session.account)
let image = utility.loadUserImage(for: session.user, displayName: tableAccount?.displayName, urlBase: session.urlBase)
let profileButton = UIButton(type: .custom)
profileButton.setImage(image, for: .normal)
if serverUrl == utilityFileSystem.getHomeServer(urlBase: activeAccount.urlBase, userId: activeAccount.userId) {
if serverUrl == utilityFileSystem.getHomeServer(session: self.session) {
var title = " "
if let userAlias = activeAccount?.alias, !userAlias.isEmpty {
if let userAlias = tableAccount?.alias, !userAlias.isEmpty {
title += userAlias
} else {
title += activeAccount?.displayName ?? ""
title += tableAccount?.displayName ?? ""
}
profileButton.setTitle(title, for: .normal)
@ -248,7 +240,7 @@ class NCShareExtension: UIViewController {
}
}
var navItems = [UIBarButtonItem(customView: profileButton)]
if serverUrl != utilityFileSystem.getHomeServer(urlBase: activeAccount.urlBase, userId: activeAccount.userId) {
if serverUrl != utilityFileSystem.getHomeServer(session: self.session) {
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
space.width = 20
navItems.append(contentsOf: [UIBarButtonItem(customView: backButton), space])
@ -278,7 +270,7 @@ class NCShareExtension: UIViewController {
}
@objc func actionCreateFolder() {
let alertController = UIAlertController.createFolder(serverUrl: serverUrl, userBaseUrl: activeAccount) { error in
let alertController = UIAlertController.createFolder(serverUrl: serverUrl, account: session.account) { error in
guard error != .success else { return }
self.showAlert(title: "_error_createsubfolders_upload_", description: error.errorDescription)
}
@ -298,7 +290,7 @@ extension NCShareExtension {
var conflicts: [tableMetadata] = []
for fileName in filesName {
if let fileNameError = FileNameValidator.shared.checkFileName(fileName) {
if let fileNameError = FileNameValidator.shared.checkFileName(fileName, account: session.account) {
present(UIAlertController.warning(message: "\(fileNameError.errorDescription) \(NSLocalizedString("_please_rename_file_", comment: ""))"), animated: true)
continue
@ -307,27 +299,32 @@ extension NCShareExtension {
let ocId = NSUUID().uuidString
let toPath = utilityFileSystem.getDirectoryProviderStorageOcId(ocId, fileNameView: fileName)
guard utilityFileSystem.copyFile(atPath: (NSTemporaryDirectory() + fileName), toPath: toPath) else { continue }
let metadata = NCManageDatabase.shared.createMetadata(
account: activeAccount.account, user: activeAccount.user, userId: activeAccount.userId,
fileName: fileName, fileNameView: fileName,
let metadataForUpload = self.database.createMetadata(fileName: fileName,
fileNameView: fileName,
ocId: ocId,
serverUrl: serverUrl, urlBase: activeAccount.urlBase, url: "",
contentType: "")
metadata.session = NextcloudKit.shared.nkCommonInstance.sessionIdentifierUpload
metadata.sessionSelector = NCGlobal.shared.selectorUploadFileShareExtension
metadata.size = utilityFileSystem.getFileSize(filePath: toPath)
metadata.status = NCGlobal.shared.metadataStatusWaitUpload
metadata.sessionDate = Date()
if NCManageDatabase.shared.getMetadataConflict(account: activeAccount.account, serverUrl: serverUrl, fileNameView: fileName) != nil {
conflicts.append(metadata)
serverUrl: serverUrl,
url: "",
contentType: "",
session: session,
sceneIdentifier: nil)
metadataForUpload.session = NCNetworking.shared.sessionUpload
metadataForUpload.sessionSelector = NCGlobal.shared.selectorUploadFileShareExtension
metadataForUpload.size = utilityFileSystem.getFileSize(filePath: toPath)
metadataForUpload.status = NCGlobal.shared.metadataStatusWaitUpload
metadataForUpload.sessionDate = Date()
if self.database.getMetadataConflict(account: session.account, serverUrl: serverUrl, fileNameView: fileName) != nil {
conflicts.append(metadataForUpload)
} else {
uploadMetadata.append(metadata)
uploadMetadata.append(metadataForUpload)
}
}
if !conflicts.isEmpty {
guard let conflict = UIStoryboard(name: "NCCreateFormUploadConflict", bundle: nil).instantiateInitialViewController() as? NCCreateFormUploadConflict
else { return }
conflict.account = session.account
conflict.serverUrl = self.serverUrl
conflict.metadatasUploadInConflict = conflicts
conflict.delegate = self
@ -341,8 +338,8 @@ extension NCShareExtension {
guard uploadStarted else { return }
guard uploadMetadata.count > counterUploaded else { return DispatchQueue.main.async { self.finishedUploading() } }
let metadata = uploadMetadata[counterUploaded]
let results = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: metadata.fileNameView, mimeType: metadata.contentType, directory: false, account: session.account)
let results = NextcloudKit.shared.nkCommonInstance.getInternalType(fileName: metadata.fileNameView, mimeType: metadata.contentType, directory: false)
metadata.contentType = results.mimeType
metadata.iconName = results.iconName
metadata.classFile = results.classFile
@ -359,22 +356,16 @@ extension NCShareExtension {
// E2EE
metadata.e2eEncrypted = metadata.isDirectoryE2EE
DispatchQueue.main.async {
self.hud.show(in: self.view)
self.hud.textLabel.text = NSLocalizedString("_upload_file_", comment: "") + " \(self.counterUploaded + 1) " + NSLocalizedString("_of_", comment: "") + " \(self.filesName.count)"
}
hud.initHudRing(view: self.view,
text: NSLocalizedString("_upload_file_", comment: "") + " \(self.counterUploaded + 1) " + NSLocalizedString("_of_", comment: "") + " \(self.filesName.count)")
NCNetworking.shared.upload(metadata: metadata, uploadE2EEDelegate: self, hudView: self.view, hud: JGProgressHUD()) {
DispatchQueue.main.async {
self.hud.progress = 0
}
NCNetworking.shared.upload(metadata: metadata, uploadE2EEDelegate: self, controller: self) {
self.hud.progress(0)
} progressHandler: { _, _, fractionCompleted in
DispatchQueue.main.async {
self.hud.progress = Float(fractionCompleted)
}
self.hud.progress(fractionCompleted)
} completion: { _, error in
if error != .success {
NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))
self.database.deleteMetadataOcId(metadata.ocId)
self.utilityFileSystem.removeFile(atPath: self.utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId))
self.uploadErrors.append(metadata)
}
@ -391,9 +382,7 @@ extension NCShareExtension {
self.extensionContext?.cancelRequest(withError: NCShareExtensionError.fileUpload)
}
} else {
hud.indicatorView = JGProgressHUDSuccessIndicatorView()
hud.indicatorView?.tintColor = NCBrandColor.shared.brandElement
hud.textLabel.text = NSLocalizedString("_success_", comment: "")
hud.success()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.extensionContext?.completeRequest(returningItems: self.extensionContext?.inputItems, completionHandler: nil)
}
@ -403,11 +392,11 @@ extension NCShareExtension {
extension NCShareExtension: uploadE2EEDelegate {
func start() {
self.hud.progress = 0
self.hud.progress(0)
}
func uploadE2EEProgress(_ totalBytesExpected: Int64, _ totalBytes: Int64, _ fractionCompleted: Double) {
self.hud.progress = Float(fractionCompleted)
self.hud.progress(fractionCompleted)
}
}

Просмотреть файл

@ -4,3 +4,4 @@
#import "NCEndToEndEncryption.h"
#import "UIImage+animatedGIF.h"
#import "TOPasscodeViewController.h"

Просмотреть файл

@ -8,6 +8,7 @@
import XCTest
import Foundation
import UIKit
import Alamofire
import NextcloudKit
@testable import Nextcloud

Просмотреть файл

@ -20,6 +20,7 @@
//
import Foundation
import UIKit
public class TestConstants {
static let timeoutLong: Double = 600

Просмотреть файл

@ -24,10 +24,9 @@ import NextcloudKit
@testable import Nextcloud
final class FilesIntegrationTests: BaseIntegrationXCTestCase {
private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
override func setUp() {
appDelegate.deleteAllAccounts()
NCAccount().deleteAllAccounts()
}
func test_createReadDeleteFolder_withProperParams_shouldCreateReadDeleteFolder() throws {
@ -36,11 +35,14 @@ final class FilesIntegrationTests: BaseIntegrationXCTestCase {
let folderName = "TestFolder\(randomInt)"
let serverUrl = "\(TestConstants.server)/remote.php/dav/files/\(TestConstants.username)"
let serverUrlFileName = "\(serverUrl)/\(folderName)"
let domain = NCDomain.Domain(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, sceneIdentifier: "")
NextcloudKit.shared.setup(account: TestConstants.account, user: TestConstants.username, userId: TestConstants.username, password: appToken, urlBase: TestConstants.server, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
NextcloudKit.shared.setup(delegate: NCNetworking.shared)
NextcloudKit.shared.appendAccount(TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, password: appToken, userAgent: userAgent, nextcloudVersion: 0, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
// Test creating folder
NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, account: TestConstants.account, urlBase: TestConstants.server, userId: TestConstants.username, withPush: true, sceneIdentifier: nil) { error in
NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, overwrite: true, withPush: true, sceneIdentifier: nil, domain: domain) { error in
XCTAssertEqual(NKError.success.errorCode, error.errorCode)
XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
@ -61,7 +63,7 @@ final class FilesIntegrationTests: BaseIntegrationXCTestCase {
Task {
// Test deleting folder
await _ = NCNetworking.shared.deleteMetadata(metadataFolder!, onlyLocalCache: false)
await _ = NCNetworking.shared.deleteMetadata(metadataFolder!)
XCTAssertEqual(NKError.success.errorCode, error.errorCode)
XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)

Просмотреть файл

@ -39,6 +39,7 @@ struct DashboardDataEntry: TimelineEntry {
let title: String
let footerImage: String
let footerText: String
let account: String
}
struct DashboardData: Identifiable, Hashable {
@ -101,45 +102,44 @@ func getDashboardDataEntry(configuration: DashboardIntent?, isPreview: Bool, dis
let utility = NCUtility()
let dashboardItems = getDashboardItems(displaySize: displaySize, withButton: false)
let datasPlaceholder = Array(dashboardDatasTest[0...dashboardItems - 1])
var account: tableAccount?
var activeTableAccount: tableAccount?
if isPreview {
return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, dashboard: nil, buttons: nil, isPlaceholder: true, isEmpty: false, titleImage: UIImage(named: "widget")!, title: "Dashboard", footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard"))
return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, dashboard: nil, buttons: nil, isPlaceholder: true, isEmpty: false, titleImage: UIImage(named: "widget")!, title: "Dashboard", footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " dashboard", account: ""))
}
let accountIdentifier: String = configuration?.accounts?.identifier ?? "active"
if accountIdentifier == "active" {
account = NCManageDatabase.shared.getActiveAccount()
activeTableAccount = NCManageDatabase.shared.getActiveTableAccount()
} else {
account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", accountIdentifier))
activeTableAccount = NCManageDatabase.shared.getTableAccount(predicate: NSPredicate(format: "account == %@", accountIdentifier))
}
guard let account = account else {
return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, dashboard: nil, buttons: nil, isPlaceholder: true, isEmpty: false, titleImage: UIImage(named: "widget")!, title: "Dashboard", footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", comment: "")))
guard let activeTableAccount,
let capabilities = NCManageDatabase.shared.setCapabilities(account: activeTableAccount.account) else {
return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, dashboard: nil, buttons: nil, isPlaceholder: true, isEmpty: false, titleImage: UIImage(named: "widget")!, title: "Dashboard", footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", comment: ""), account: ""))
}
// Default widget
let result = NCManageDatabase.shared.getDashboardWidgetApplications(account: account.account).first
let result = NCManageDatabase.shared.getDashboardWidgetApplications(account: activeTableAccount.account).first
let id: String = configuration?.applications?.identifier ?? (result?.id ?? "recommendations")
// Capabilities
NCManageDatabase.shared.setCapabilities(account: account.account)
guard NCGlobal.shared.capabilityServerVersionMajor >= NCGlobal.shared.nextcloudVersion25 else {
return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, dashboard: nil, buttons: nil, isPlaceholder: true, isEmpty: false, titleImage: UIImage(named: "widget")!, title: "Dashboard", footerImage: "xmark.icloud", footerText: NSLocalizedString("_widget_available_nc25_", comment: "")))
guard capabilities.capabilityServerVersionMajor >= NCGlobal.shared.nextcloudVersion25 else {
return completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, dashboard: nil, buttons: nil, isPlaceholder: true, isEmpty: false, titleImage: UIImage(named: "widget")!, title: "Dashboard", footerImage: "xmark.icloud", footerText: NSLocalizedString("_widget_available_nc25_", comment: ""), account: activeTableAccount.account))
}
// NETWORKING
let password = NCKeychain().getPassword(account: account.account)
NextcloudKit.shared.setup(
account: account.account,
user: account.user,
userId: account.userId,
let password = NCKeychain().getPassword(account: activeTableAccount.account)
NextcloudKit.shared.setup(delegate: NCNetworking.shared)
NextcloudKit.shared.appendSession(account: activeTableAccount.account,
urlBase: activeTableAccount.urlBase,
user: activeTableAccount.user,
userId: activeTableAccount.userId,
password: password,
urlBase: account.urlBase,
userAgent: userAgent,
nextcloudVersion: 0,
delegate: NCNetworking.shared)
nextcloudVersion: capabilities.capabilityServerVersionMajor,
groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
// LOG
let levelLog = NCKeychain().logLevel
@ -154,7 +154,7 @@ func getDashboardDataEntry(configuration: DashboardIntent?, isPreview: Bool, dis
NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Start \(NCBrandOptions.shared.brand) dashboard widget session with level \(levelLog) " + versionNextcloudiOS)
}
let (tableDashboard, tableButton) = NCManageDatabase.shared.getDashboardWidget(account: account.account, id: id)
let (tableDashboard, tableButton) = NCManageDatabase.shared.getDashboardWidget(account: activeTableAccount.account, id: id)
let existsButton = (tableButton?.isEmpty ?? true) ? false : true
let title = tableDashboard?.title ?? id
@ -168,7 +168,7 @@ func getDashboardDataEntry(configuration: DashboardIntent?, isPreview: Bool, dis
let titleImage = imagetmp
let options = NKRequestOptions(timeout: 90, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
NextcloudKit.shared.getDashboardWidgetsApplication(id, account: account.account, options: options) { _, results, data, error in
NextcloudKit.shared.getDashboardWidgetsApplication(id, account: activeTableAccount.account, options: options) { account, results, responseData, error in
Task {
var datas = [DashboardData]()
var numberItems = 0
@ -225,9 +225,10 @@ func getDashboardDataEntry(configuration: DashboardIntent?, isPreview: Bool, dis
if FileManager().fileExists(atPath: fileNamePath), let image = UIImage(contentsOfFile: fileNamePath) {
icon = image
} else {
let (_, data, error) = await NCNetworking.shared.downloadPreview(url: url, account: account.account)
let (_, data, error) = await NCNetworking.shared.downloadPreview(url: url, account: activeTableAccount.account)
if error == .success,
let image = convertDataToImage(data: data, size: CGSize(width: 256, height: 256), fileNameToWrite: fileName) {
let data = responseData?.data,
let image = convertDataToImage(data: data, size: NCGlobal.shared.size256, fileNameToWrite: fileName) {
icon = image
}
}
@ -248,13 +249,13 @@ func getDashboardDataEntry(configuration: DashboardIntent?, isPreview: Bool, dis
buttons = tableButton.filter(({ $0.type != "more" }))
}
let alias = (account.alias.isEmpty) ? "" : (" (" + account.alias + ")")
let footerText = "Dashboard " + NSLocalizedString("_of_", comment: "") + " " + account.displayName + alias
let alias = (activeTableAccount.alias.isEmpty) ? "" : (" (" + activeTableAccount.alias + ")")
let footerText = "Dashboard " + NSLocalizedString("_of_", comment: "") + " " + activeTableAccount.displayName + alias
if error != .success {
completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, dashboard: tableDashboard, buttons: buttons, isPlaceholder: true, isEmpty: false, titleImage: titleImage, title: title, footerImage: "xmark.icloud", footerText: error.errorDescription))
completion(DashboardDataEntry(date: Date(), datas: datasPlaceholder, dashboard: tableDashboard, buttons: buttons, isPlaceholder: true, isEmpty: false, titleImage: titleImage, title: title, footerImage: "xmark.icloud", footerText: error.errorDescription, account: account))
} else {
completion(DashboardDataEntry(date: Date(), datas: datas, dashboard: tableDashboard, buttons: buttons, isPlaceholder: false, isEmpty: datas.isEmpty, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: footerText))
completion(DashboardDataEntry(date: Date(), datas: datas, dashboard: tableDashboard, buttons: buttons, isPlaceholder: false, isEmpty: datas.isEmpty, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: footerText, account: account))
}
}
}

Просмотреть файл

@ -35,7 +35,7 @@ struct DashboardWidgetProvider: IntentTimelineProvider {
let datasPlaceholder = Array(dashboardDatasTest[0...dashboardItems])
let title = "Dashboard"
let titleImage = UIImage(named: "widget")!
return Entry(date: Date(), datas: datasPlaceholder, dashboard: nil, buttons: nil, isPlaceholder: true, isEmpty: false, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget")
return Entry(date: Date(), datas: datasPlaceholder, dashboard: nil, buttons: nil, isPlaceholder: true, isEmpty: false, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " widget", account: "")
}
func getSnapshot(for configuration: DashboardIntent, in context: Context, completion: @escaping (DashboardDataEntry) -> Void) {

Просмотреть файл

@ -25,13 +25,9 @@ import SwiftUI
import WidgetKit
struct DashboardWidgetView: View {
var entry: DashboardDataEntry
var body: some View {
GeometryReader { geo in
if entry.isEmpty {
VStack(alignment: .center) {
Image(systemName: "checkmark")
@ -156,9 +152,8 @@ struct DashboardWidgetView: View {
if let buttons = entry.buttons, !buttons.isEmpty, !entry.isPlaceholder {
HStack(spacing: 10) {
let brandColor = Color(NCBrandColor.shared.brandElement)
let brandTextColor = Color(NCBrandColor.shared.brandText)
let brandColor = Color(NCBrandColor.shared.getElement(account: entry.account))
let brandTextColor = Color(NCBrandColor.shared.getText(account: entry.account))
ForEach(buttons, id: \.index) { element in
Link(destination: URL(string: element.link)!, label: {
@ -183,12 +178,12 @@ struct DashboardWidgetView: View {
.scaledToFit()
.frame(width: 15, height: 15)
.font(Font.system(.body).weight(.light))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
Text(entry.footerText)
.font(.caption2)
.lineLimit(1)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
}
.padding(.horizontal, 15.0)
.frame(maxWidth: geo.size.width, maxHeight: geo.size.height - 2, alignment: .bottomTrailing)
@ -203,7 +198,7 @@ struct DashboardWidget_Previews: PreviewProvider {
let datas = Array(dashboardDatasTest[0...4])
let title = "Dashboard"
let titleImage = UIImage(named: "widget")!
let entry = DashboardDataEntry(date: Date(), datas: datas, dashboard: nil, buttons: nil, isPlaceholder: false, isEmpty: true, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: "Nextcloud widget")
let entry = DashboardDataEntry(date: Date(), datas: datas, dashboard: nil, buttons: nil, isPlaceholder: false, isEmpty: true, titleImage: titleImage, title: title, footerImage: "checkmark.icloud", footerText: "Nextcloud widget", account: "")
DashboardWidgetView(entry: entry).previewContext(WidgetPreviewContext(family: .systemLarge))
}
}

Просмотреть файл

@ -33,6 +33,7 @@ struct FilesDataEntry: TimelineEntry {
let isEmpty: Bool
let userId: String
let url: String
let account: String
let tile: String
let footerImage: String
let footerText: String
@ -60,7 +61,7 @@ let filesDatasTest: [FilesData] = [
.init(id: "9", image: UIImage(named: "widget")!, title: "title4", subTitle: "subTitle-description4", url: URL(string: "https://nextcloud.com/")!)
]
func getTitleFilesWidget(account: tableAccount?) -> String {
func getTitleFilesWidget(tableAccount: tableAccount?) -> String {
let hour = Calendar.current.component(.hour, from: Date())
var good = ""
@ -72,8 +73,8 @@ func getTitleFilesWidget(account: tableAccount?) -> String {
default: good = NSLocalizedString("_good_night_", value: "Good night", comment: "")
}
if let account = account {
return good + ", " + account.displayName
if let tableAccount {
return good + ", " + tableAccount.displayName
} else {
return good
}
@ -89,34 +90,35 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi
let utility = NCUtility()
let filesItems = getFilesItems(displaySize: displaySize)
let datasPlaceholder = Array(filesDatasTest[0...filesItems - 1])
var account: tableAccount?
var activeTableAccount: tableAccount?
if isPreview {
return completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, isEmpty: false, userId: "", url: "", tile: getTitleFilesWidget(account: nil), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " files"))
return completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, isEmpty: false, userId: "", url: "", account: "", tile: getTitleFilesWidget(tableAccount: nil), footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " files"))
}
let accountIdentifier: String = configuration?.accounts?.identifier ?? "active"
if accountIdentifier == "active" {
account = NCManageDatabase.shared.getActiveAccount()
activeTableAccount = NCManageDatabase.shared.getActiveTableAccount()
} else {
account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", accountIdentifier))
activeTableAccount = NCManageDatabase.shared.getTableAccount(predicate: NSPredicate(format: "account == %@", accountIdentifier))
}
guard let account = account else {
return completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, isEmpty: false, userId: "", url: "", tile: getTitleFilesWidget(account: nil), footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
guard let activeTableAccount else {
return completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, isEmpty: false, userId: "", url: "", account: "", tile: getTitleFilesWidget(tableAccount: nil), footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
}
// NETWORKING
let password = NCKeychain().getPassword(account: account.account)
NextcloudKit.shared.setup(
account: account.account,
user: account.user,
userId: account.userId,
let password = NCKeychain().getPassword(account: activeTableAccount.account)
NextcloudKit.shared.setup(delegate: NCNetworking.shared)
NextcloudKit.shared.appendSession(account: activeTableAccount.account,
urlBase: activeTableAccount.urlBase,
user: activeTableAccount.user,
userId: activeTableAccount.userId,
password: password,
urlBase: account.urlBase,
userAgent: userAgent,
nextcloudVersion: 0,
delegate: NCNetworking.shared)
nextcloudVersion: NCCapabilities.shared.getCapabilities(account: activeTableAccount.account).capabilityServerVersionMajor,
groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
let requestBodyRecent =
"""
@ -173,7 +175,7 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
let lessDateString = dateFormatter.string(from: Date())
let requestBody = String(format: requestBodyRecent, "/files/" + account.userId, lessDateString)
let requestBody = String(format: requestBodyRecent, "/files/" + activeTableAccount.userId, lessDateString)
// LOG
let levelLog = NCKeychain().logLevel
@ -190,11 +192,11 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi
}
let options = NKRequestOptions(timeout: 30, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
NextcloudKit.shared.searchBodyRequest(serverUrl: account.urlBase, requestBody: requestBody, showHiddenFiles: NCKeychain().showHiddenFiles, account: account.account, options: options) { _, files, data, error in
NextcloudKit.shared.searchBodyRequest(serverUrl: activeTableAccount.urlBase, requestBody: requestBody, showHiddenFiles: NCKeychain().showHiddenFiles, account: activeTableAccount.account, options: options) { _, files, data, error in
Task {
var datas: [FilesData] = []
let title = getTitleFilesWidget(account: account)
let files = files.sorted(by: { ($0.date as Date) > ($1.date as Date) })
let title = getTitleFilesWidget(tableAccount: activeTableAccount)
let files = files?.sorted(by: { ($0.date as Date) > ($1.date as Date) }) ?? []
for file in files {
var useTypeIconFile = false
@ -216,18 +218,18 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi
guard let url = URL(string: urlString) else { continue }
// IMAGE
let fileNamePreviewLocalPath = utilityFileSystem.getDirectoryProviderStoragePreviewOcId(file.ocId, etag: file.etag)
let fileNameIconLocalPath = utilityFileSystem.getDirectoryProviderStorageIconOcId(file.ocId, etag: file.etag)
if FileManager.default.fileExists(atPath: fileNameIconLocalPath) {
image = UIImage(contentsOfFile: fileNameIconLocalPath)
}
image = utility.getImage(ocId: file.ocId, etag: file.etag, ext: NCGlobal.shared.previewExt512)
if image == nil, file.hasPreview {
let sizePreview = NCUtility().getSizePreview(width: Int(file.width), height: Int(file.height))
let (_, _, imageIcon, _, _, _) = await NCNetworking.shared.downloadPreview(fileId: file.fileId, fileNamePreviewLocalPath: fileNamePreviewLocalPath, fileNameIconLocalPath: fileNameIconLocalPath, widthPreview: Int(sizePreview.width), heightPreview: Int(sizePreview.height), sizeIcon: NCGlobal.shared.sizeIcon, account: account.account, options: options)
image = imageIcon
let result = await NCNetworking.shared.downloadPreview(fileId: file.fileId,
account: activeTableAccount.account,
options: options)
if result.error == .success, let data = result.responseData?.data {
utility.createImageFileFrom(data: data, ocId: file.ocId, etag: file.etag)
image = utility.getImage(ocId: file.ocId, etag: file.etag, ext: NCGlobal.shared.previewExt256)
}
}
if image == nil {
image = utility.loadImage(named: file.iconName, useTypeIconFile: true)
image = utility.loadImage(named: file.iconName, useTypeIconFile: true, account: file.account)
useTypeIconFile = true
}
@ -240,13 +242,13 @@ func getFilesDataEntry(configuration: AccountIntent?, isPreview: Bool, displaySi
if datas.count == filesItems { break}
}
let alias = (account.alias.isEmpty) ? "" : (" (" + account.alias + ")")
let footerText = "Files " + NSLocalizedString("_of_", comment: "") + " " + account.displayName + alias
let alias = (activeTableAccount.alias.isEmpty) ? "" : (" (" + activeTableAccount.alias + ")")
let footerText = "Files " + NSLocalizedString("_of_", comment: "") + " " + activeTableAccount.displayName + alias
if error != .success {
completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, isEmpty: false, userId: account.userId, url: account.urlBase, tile: title, footerImage: "xmark.icloud", footerText: error.errorDescription))
completion(FilesDataEntry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, isEmpty: false, userId: activeTableAccount.userId, url: activeTableAccount.urlBase, account: activeTableAccount.account, tile: title, footerImage: "xmark.icloud", footerText: error.errorDescription))
} else {
completion(FilesDataEntry(date: Date(), datas: datas, isPlaceholder: false, isEmpty: datas.isEmpty, userId: account.userId, url: account.urlBase, tile: title, footerImage: "checkmark.icloud", footerText: footerText))
completion(FilesDataEntry(date: Date(), datas: datas, isPlaceholder: false, isEmpty: datas.isEmpty, userId: activeTableAccount.userId, url: activeTableAccount.urlBase, account: activeTableAccount.account, tile: title, footerImage: "checkmark.icloud", footerText: footerText))
}
}
}

Просмотреть файл

@ -33,8 +33,8 @@ struct FilesWidgetProvider: IntentTimelineProvider {
func placeholder(in context: Context) -> Entry {
let filesItems = getFilesItems(displaySize: context.displaySize)
let datasPlaceholder = Array(filesDatasTest[0...filesItems - 1])
let title = getTitleFilesWidget(account: nil)
return Entry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, isEmpty: false, userId: "", url: "", tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " files")
let title = getTitleFilesWidget(tableAccount: nil)
return Entry(date: Date(), datas: datasPlaceholder, isPlaceholder: true, isEmpty: false, userId: "", url: "", account: "", tile: title, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " files")
}
func getSnapshot(for configuration: AccountIntent, in context: Context, completion: @escaping (Entry) -> Void) {

Просмотреть файл

@ -120,9 +120,9 @@ struct FilesWidgetView: View {
Image("addImage")
.resizable()
.renderingMode(.template)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandText))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getText(account: entry.account)))
.padding(11)
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
.clipShape(Circle())
.scaledToFit()
.frame(width: geo.size.width / 4, height: sizeButton)
@ -132,9 +132,9 @@ struct FilesWidgetView: View {
Image(systemName: "doc.text.viewfinder")
.resizable()
.renderingMode(.template)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandText))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getText(account: entry.account)))
.padding(11)
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
.clipShape(Circle())
.scaledToFit()
.font(Font.system(.body).weight(.light))
@ -145,9 +145,9 @@ struct FilesWidgetView: View {
Image("note.text")
.resizable()
.renderingMode(.template)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandText))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getText(account: entry.account)))
.padding(11)
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
.clipShape(Circle())
.scaledToFit()
.frame(width: geo.size.width / 4, height: sizeButton)
@ -157,9 +157,9 @@ struct FilesWidgetView: View {
Image("microphone")
.resizable()
.renderingMode(.template)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandText))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getText(account: entry.account)))
.padding(11)
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
.clipShape(Circle())
.scaledToFit()
.frame(width: geo.size.width / 4, height: sizeButton)
@ -174,12 +174,12 @@ struct FilesWidgetView: View {
.scaledToFit()
.frame(width: 15, height: 15)
.font(Font.system(.body).weight(.light))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
Text(entry.footerText)
.font(.caption2)
.lineLimit(1)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
}
.padding(.horizontal, 15.0)
.frame(maxWidth: geo.size.width, maxHeight: geo.size.height - 2, alignment: .bottomTrailing)
@ -192,7 +192,7 @@ struct FilesWidgetView: View {
struct FilesWidget_Previews: PreviewProvider {
static var previews: some View {
let datas = Array(filesDatasTest[0...4])
let entry = FilesDataEntry(date: Date(), datas: datas, isPlaceholder: false, isEmpty: true, userId: "", url: "", tile: "Good afternoon, Marino Faggiana", footerImage: "checkmark.icloud", footerText: "Nextcloud files")
let entry = FilesDataEntry(date: Date(), datas: datas, isPlaceholder: false, isEmpty: true, userId: "", url: "", account: "", tile: "Good afternoon, Marino Faggiana", footerImage: "checkmark.icloud", footerText: "Nextcloud files")
FilesWidgetView(entry: entry).previewContext(WidgetPreviewContext(family: .systemLarge))
}
}

Просмотреть файл

@ -38,7 +38,7 @@ struct LockscreenData: TimelineEntry {
func getLockscreenDataEntry(configuration: AccountIntent?, isPreview: Bool, family: WidgetFamily, completion: @escaping (_ entry: LockscreenData) -> Void) {
let utilityFileSystem = NCUtilityFileSystem()
var account: tableAccount?
var activeTableAccount: tableAccount?
var quotaRelative: Float = 0
if isPreview {
@ -47,38 +47,37 @@ func getLockscreenDataEntry(configuration: AccountIntent?, isPreview: Bool, fami
let accountIdentifier: String = configuration?.accounts?.identifier ?? "active"
if accountIdentifier == "active" {
account = NCManageDatabase.shared.getActiveAccount()
activeTableAccount = NCManageDatabase.shared.getActiveTableAccount()
} else {
account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", accountIdentifier))
activeTableAccount = NCManageDatabase.shared.getTableAccount(predicate: NSPredicate(format: "account == %@", accountIdentifier))
}
guard let account else {
guard let activeTableAccount,
let capabilities = NCManageDatabase.shared.setCapabilities(account: activeTableAccount.account) else {
return completion(LockscreenData(date: Date(), isPlaceholder: true, activity: "", link: URL(string: "https://")!, quotaRelative: 0, quotaUsed: "", quotaTotal: "", error: false))
}
// Capabilities
NCManageDatabase.shared.setCapabilities(account: account.account)
if NCGlobal.shared.capabilityServerVersionMajor < NCGlobal.shared.nextcloudVersion25 {
if capabilities.capabilityServerVersionMajor < NCGlobal.shared.nextcloudVersion25 {
completion(LockscreenData(date: Date(), isPlaceholder: false, activity: NSLocalizedString("_widget_available_nc25_", comment: ""), link: URL(string: "https://")!, quotaRelative: 0, quotaUsed: "", quotaTotal: "", error: true))
}
// NETWORKING
let password = NCKeychain().getPassword(account: account.account)
NextcloudKit.shared.setup(
account: account.account,
user: account.user,
userId: account.userId,
let password = NCKeychain().getPassword(account: activeTableAccount.account)
NextcloudKit.shared.setup(delegate: NCNetworking.shared)
NextcloudKit.shared.appendSession(account: activeTableAccount.account,
urlBase: activeTableAccount.urlBase,
user: activeTableAccount.user,
userId: activeTableAccount.userId,
password: password,
urlBase: account.urlBase,
userAgent: userAgent,
nextcloudVersion: 0,
delegate: NCNetworking.shared)
nextcloudVersion: capabilities.capabilityServerVersionMajor,
groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
let options = NKRequestOptions(timeout: 90, queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)
if #available(iOSApplicationExtension 16.0, *) {
if family == .accessoryCircular {
NextcloudKit.shared.getUserProfile(account: account.account, options: options) { _, userProfile, _, error in
NextcloudKit.shared.getUserProfile(account: activeTableAccount.account, options: options) { _, userProfile, _, error in
if error == .success, let userProfile = userProfile {
if userProfile.quotaRelative > 0 {
quotaRelative = Float(userProfile.quotaRelative) / 100
@ -102,7 +101,7 @@ func getLockscreenDataEntry(configuration: AccountIntent?, isPreview: Bool, fami
}
}
} else if family == .accessoryRectangular {
NextcloudKit.shared.getDashboardWidgetsApplication("activity", account: account.account, options: options) { _, results, _, error in
NextcloudKit.shared.getDashboardWidgetsApplication("activity", account: activeTableAccount.account, options: options) { _, results, _, error in
var activity: String = NSLocalizedString("_no_data_available_", comment: "")
var link = URL(string: "https://")!
if error == .success, let result = results?.first {

Просмотреть файл

@ -29,6 +29,7 @@ struct ToolbarDataEntry: TimelineEntry {
let isPlaceholder: Bool
let userId: String
let url: String
let account: String
let footerImage: String
let footerText: String
}
@ -36,19 +37,21 @@ struct ToolbarDataEntry: TimelineEntry {
func getToolbarDataEntry(isPreview: Bool, completion: @escaping (_ entry: ToolbarDataEntry) -> Void) {
var userId = ""
var url = ""
var account = ""
if let account = NCManageDatabase.shared.getActiveAccount() {
userId = account.userId
url = account.urlBase
if let activeTableAccount = NCManageDatabase.shared.getActiveTableAccount() {
userId = activeTableAccount.userId
url = activeTableAccount.urlBase
account = activeTableAccount.account
}
if isPreview {
return completion(ToolbarDataEntry(date: Date(), isPlaceholder: true, userId: userId, url: url, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar"))
return completion(ToolbarDataEntry(date: Date(), isPlaceholder: true, userId: userId, url: url, account: account, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar"))
}
if NCManageDatabase.shared.getActiveAccount() == nil {
return completion(ToolbarDataEntry(date: Date(), isPlaceholder: true, userId: userId, url: url, footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
if NCManageDatabase.shared.getActiveTableAccount() == nil {
return completion(ToolbarDataEntry(date: Date(), isPlaceholder: true, userId: userId, url: url, account: account, footerImage: "xmark.icloud", footerText: NSLocalizedString("_no_active_account_", value: "No account found", comment: "")))
}
completion(ToolbarDataEntry(date: Date(), isPlaceholder: false, userId: userId, url: url, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar"))
completion(ToolbarDataEntry(date: Date(), isPlaceholder: false, userId: userId, url: url, account: account, footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar"))
}

Просмотреть файл

@ -29,7 +29,7 @@ struct ToolbarWidgetProvider: TimelineProvider {
typealias Entry = ToolbarDataEntry
func placeholder(in context: Context) -> Entry {
return Entry(date: Date(), isPlaceholder: true, userId: "", url: "", footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar")
return Entry(date: Date(), isPlaceholder: true, userId: "", url: "", account: "", footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar")
}
func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) {

Просмотреть файл

@ -49,9 +49,9 @@ struct ToolbarWidgetView: View {
Image("addImage")
.resizable()
.renderingMode(.template)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandText))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getText(account: entry.account)))
.padding()
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
.clipShape(Circle())
.scaledToFit()
.frame(width: geo.size.width / 4, height: sizeButton)
@ -62,9 +62,9 @@ struct ToolbarWidgetView: View {
.resizable()
.renderingMode(.template)
.font(Font.system(.body).weight(.light))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandText))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getText(account: entry.account)))
.padding()
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
.clipShape(Circle())
.scaledToFit()
.frame(width: geo.size.width / 4, height: sizeButton)
@ -74,9 +74,9 @@ struct ToolbarWidgetView: View {
Image("note.text")
.resizable()
.renderingMode(.template)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandText))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getText(account: entry.account)))
.padding()
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
.clipShape(Circle())
.scaledToFit()
.frame(width: geo.size.width / 4, height: sizeButton)
@ -85,9 +85,9 @@ struct ToolbarWidgetView: View {
Link(destination: entry.isPlaceholder ? linkNoAction : linkActionVoiceMemo, label: {
Image("microphone")
.resizable()
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandText))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getText(account: entry.account)))
.padding()
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.background(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
.clipShape(Circle())
.scaledToFit()
.frame(width: geo.size.width / 4, height: sizeButton)
@ -102,12 +102,12 @@ struct ToolbarWidgetView: View {
.font(Font.system(.body).weight(.light))
.scaledToFit()
.frame(width: 15, height: 15)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
Text(entry.footerText)
.font(.caption2)
.padding(.trailing, 13.0)
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.brandElement))
.foregroundColor(entry.isPlaceholder ? Color(.systemGray4) : Color(NCBrandColor.shared.getElement(account: entry.account)))
}
.frame(maxWidth: geo.size.width - 5, maxHeight: geo.size.height - 2, alignment: .bottomTrailing)
}
@ -118,7 +118,7 @@ struct ToolbarWidgetView: View {
struct ToolbarWidget_Previews: PreviewProvider {
static var previews: some View {
let entry = ToolbarDataEntry(date: Date(), isPlaceholder: false, userId: "", url: "", footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar")
let entry = ToolbarDataEntry(date: Date(), isPlaceholder: false, userId: "", url: "", account: "", footerImage: "checkmark.icloud", footerText: NCBrandOptions.shared.brand + " toolbar")
ToolbarWidgetView(entry: entry).previewContext(WidgetPreviewContext(family: .systemMedium))
}
}

Просмотреть файл

@ -30,7 +30,7 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling
func provideAccountsOptionsCollection(for intent: AccountIntent, with completion: @escaping (INObjectCollection<Accounts>?, Error?) -> Void) {
var accounts: [Accounts] = []
let results = NCManageDatabase.shared.getAllAccount()
let results = NCManageDatabase.shared.getAllTableAccount()
accounts.append(Accounts(identifier: "active", display: "Active account"))
@ -49,7 +49,7 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling
}
func defaultAccounts(for intent: AccountIntent) -> Accounts? {
if NCManageDatabase.shared.getActiveAccount() == nil {
if NCManageDatabase.shared.getActiveTableAccount() == nil {
return nil
} else {
return Accounts(identifier: "active", display: "Active account")
@ -61,20 +61,20 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling
// Application
func provideApplicationsOptionsCollection(for intent: DashboardIntent, with completion: @escaping (INObjectCollection<Applications>?, Error?) -> Void) {
var applications: [Applications] = []
var account: tableAccount?
var activeTableAccount: tableAccount?
let accountIdentifier: String = intent.accounts?.identifier ?? "active"
if accountIdentifier == "active" {
account = NCManageDatabase.shared.getActiveAccount()
activeTableAccount = NCManageDatabase.shared.getActiveTableAccount()
} else {
account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", accountIdentifier))
activeTableAccount = NCManageDatabase.shared.getTableAccount(predicate: NSPredicate(format: "account == %@", accountIdentifier))
}
guard let account = account else {
guard let activeTableAccount else {
return completion(nil, nil)
}
let results = NCManageDatabase.shared.getDashboardWidgetApplications(account: account.account)
let results = NCManageDatabase.shared.getDashboardWidgetApplications(account: activeTableAccount.account)
for result in results {
let application = Applications(identifier: result.id, display: result.title)
applications.append(application)
@ -84,7 +84,7 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling
}
func defaultApplications(for intent: DashboardIntent) -> Applications? {
guard let account = NCManageDatabase.shared.getActiveAccount() else {
guard let account = NCManageDatabase.shared.getActiveTableAccount() else {
return nil
}
if let result = NCManageDatabase.shared.getDashboardWidgetApplications(account: account.account).first {
@ -96,7 +96,7 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling
// Account
func provideAccountsOptionsCollection(for intent: DashboardIntent, with completion: @escaping (INObjectCollection<Accounts>?, Error?) -> Void) {
var accounts: [Accounts] = []
let results = NCManageDatabase.shared.getAllAccount()
let results = NCManageDatabase.shared.getAllTableAccount()
accounts.append(Accounts(identifier: "active", display: "Active account"))
@ -115,7 +115,7 @@ class IntentHandler: INExtension, DashboardIntentHandling, AccountIntentHandling
}
func defaultAccounts(for intent: DashboardIntent) -> Accounts? {
if NCManageDatabase.shared.getActiveAccount() == nil {
if NCManageDatabase.shared.getActiveTableAccount() == nil {
return nil
} else {
return Accounts(identifier: "active", display: "Active account")

Просмотреть файл

@ -26,7 +26,7 @@ import NextcloudKit
public protocol NCAccountRequestDelegate: AnyObject {
func accountRequestAddAccount()
func accountRequestChangeAccount(account: String)
func accountRequestChangeAccount(account: String, controller: UIViewController?)
}
class NCAccountRequest: UIViewController {
@ -35,11 +35,12 @@ class NCAccountRequest: UIViewController {
@IBOutlet weak var progressView: UIProgressView!
public var accounts: [tableAccount] = []
public var activeAccount: tableAccount?
public var activeAccount: String?
public let heightCell: CGFloat = 60
public var enableTimerProgress: Bool = true
public var enableAddAccount: Bool = false
public var dismissDidEnterBackground: Bool = false
public var controller: UIViewController?
public weak var delegate: NCAccountRequestDelegate?
let utility = NCUtility()
private var timer: Timer?
@ -134,9 +135,9 @@ extension NCAccountRequest: UITableViewDelegate {
delegate?.accountRequestAddAccount()
} else {
let account = accounts[indexPath.row]
if account.account != activeAccount?.account {
if account.account != activeAccount {
dismiss(animated: true) {
self.delegate?.accountRequestChangeAccount(account: account.account)
self.delegate?.accountRequestChangeAccount(account: account.account, controller: self.controller)
}
} else {
dismiss(animated: true)
@ -177,10 +178,7 @@ extension NCAccountRequest: UITableViewDataSource {
let account = accounts[indexPath.row]
avatarImage?.image = utility.loadUserImage(
for: account.user,
displayName: account.displayName,
userBaseUrl: account)
avatarImage?.image = utility.loadUserImage(for: account.user, displayName: account.displayName, urlBase: account.urlBase)
if account.alias.isEmpty {
userLabel?.text = account.user.uppercased()

Просмотреть файл

@ -27,7 +27,7 @@ import RealmSwift
/// Protocol for know when the Account Settings has dimissed
protocol NCAccountSettingsModelDelegate: AnyObject {
func accountSettingsDidDismiss(tableAccount: tableAccount?)
func accountSettingsDidDismiss(tableAccount: tableAccount?, controller: NCMainTabBarController?)
}
/// A model that allows the user to configure the account
@ -37,36 +37,34 @@ class NCAccountSettingsModel: ObservableObject, ViewOnAppearHandling {
/// Root View Controller
var controller: NCMainTabBarController?
/// All account
var accounts: [tableAccount] = []
var tblAccounts: [tableAccount] = []
/// Delegate
weak var delegate: NCAccountSettingsModelDelegate?
/// Timer change user
var timerChangeAccount: Timer?
/// Token observe tableAccount
var notificationToken: NotificationToken?
/// Account now active
@Published var activeAccount: tableAccount?
/// Account now
@Published var tblAccount: tableAccount?
/// Index
@Published var indexActiveAccount: Int = 0
/// Current alias
@Published var alias: String = ""
/// Set true for dismiss the view
@Published var dismissView = false
/// DB
let database = NCManageDatabase.shared
/// Initialization code to set up the ViewModel with the active account
init(controller: NCMainTabBarController?, delegate: NCAccountSettingsModelDelegate?) {
self.controller = controller
self.delegate = delegate
if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" {
NCManageDatabase.shared.previewCreateDB()
database.previewCreateDB()
}
onViewAppear()
observeTableAccount()
}
deinit {
timerChangeAccount?.invalidate()
timerChangeAccount = nil
notificationToken?.invalidate()
notificationToken = nil
}
@ -96,45 +94,44 @@ class NCAccountSettingsModel: ObservableObject, ViewOnAppearHandling {
/// Triggered when the view appears.
func onViewAppear() {
var indexActiveAccount = 0
let accounts = NCManageDatabase.shared.getAllAccount()
var activeAccount = NCManageDatabase.shared.getActiveAccount()
let tableAccounts = database.getAllTableAccount()
var alias = ""
for (index, account) in accounts.enumerated() {
for (index, account) in tableAccounts.enumerated() {
if account.active {
activeAccount = account
tblAccount = account
indexActiveAccount = index
alias = account.alias
}
}
self.indexActiveAccount = indexActiveAccount
self.accounts = accounts
self.activeAccount = activeAccount
self.tblAccounts = tableAccounts
self.tblAccount = tblAccount
self.alias = alias
}
/// Func to get the user display name + alias
func getUserName() -> String {
guard let activeAccount else { return "" }
guard let tblAccount else { return "" }
if alias.isEmpty {
return activeAccount.displayName
return tblAccount.displayName
} else {
return activeAccount.displayName + " (\(alias))"
return tblAccount.displayName + " (\(alias))"
}
}
/// Func to set alias
func setAlias(_ value: String) {
guard let activeAccount else { return }
NCManageDatabase.shared.setAccountAlias(activeAccount.account, alias: alias)
guard let tblAccount else { return }
database.setAccountAlias(tblAccount.account, alias: alias)
}
/// Function to update the user data
func getUserStatus() -> (statusImage: UIImage?, statusMessage: String, descriptionMessage: String) {
guard let activeAccount else { return (UIImage(), "", "") }
if NCGlobal.shared.capabilityUserStatusEnabled,
let tableAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", activeAccount.account)) {
guard let tblAccount else { return (UIImage(), "", "") }
if NCCapabilities.shared.getCapabilities(account: tblAccount.account).capabilityUserStatusEnabled,
let tableAccount = database.getTableAccount(predicate: NSPredicate(format: "account == %@", tblAccount.account)) {
return NCUtility().getUserStatus(userIcon: tableAccount.userStatusIcon, userStatus: tableAccount.userStatusStatus, userMessage: tableAccount.userStatusMessage)
}
return (nil, "", "")
@ -142,17 +139,18 @@ class NCAccountSettingsModel: ObservableObject, ViewOnAppearHandling {
/// Is the user an Admin
func isAdminGroup() -> Bool {
guard let activeAccount else { return false }
let groups = NCManageDatabase.shared.getAccountGroups(account: activeAccount.account)
guard let tblAccount else { return false }
let groups = database.getAccountGroups(account: tblAccount.account)
return groups.contains(NCGlobal.shared.groupAdmin)
}
/// Function to know the height of "account" data
func getTableViewHeight() -> CGFloat {
guard let activeAccount else { return 0 }
var height: CGFloat = NCGlobal.shared.capabilityUserStatusEnabled ? 190 : 220
if NCGlobal.shared.capabilityUserStatusEnabled,
let tableAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", activeAccount.account)) {
guard let tblAccount else { return 0 }
let capabilities = NCCapabilities.shared.getCapabilities(account: tblAccount.account)
var height: CGFloat = capabilities.capabilityUserStatusEnabled ? 190 : 220
if capabilities.capabilityUserStatusEnabled,
let tableAccount = database.getTableAccount(predicate: NSPredicate(format: "account == %@", tblAccount.account)) {
if !tableAccount.email.isEmpty { height += 30 }
if !tableAccount.phone.isEmpty { height += 30 }
if !tableAccount.address.isEmpty { height += 30 }
@ -163,33 +161,23 @@ class NCAccountSettingsModel: ObservableObject, ViewOnAppearHandling {
/// Function to change account after 1.5 sec of change
func setAccount(account: String) {
if let tableAccount = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)), self.activeAccount?.account != tableAccount.account {
self.activeAccount = tableAccount
if let tableAccount = database.getTableAccount(predicate: NSPredicate(format: "account == %@", account)) {
self.tblAccount = tableAccount
self.alias = tableAccount.alias
/// Change active account
timerChangeAccount?.invalidate()
timerChangeAccount = Timer.scheduledTimer(timeInterval: 1.5, target: self, selector: #selector(changeAccount), userInfo: nil, repeats: false)
}
}
@objc func changeAccount() {
if let activeAccount {
self.appDelegate.changeAccount(activeAccount.account, userProfile: nil) { }
}
}
/// Function to delete the current account
func deleteAccount() {
if let activeAccount {
appDelegate.deleteAccount(activeAccount.account)
if let account = NCManageDatabase.shared.getAllAccount().first?.account {
appDelegate.changeAccount(account, userProfile: nil) {
if let tblAccount {
NCAccount().deleteAccount(tblAccount.account)
if let account = database.getAllTableAccount().first?.account {
NCAccount().changeAccount(account, userProfile: nil, controller: self.controller) {
onViewAppear()
}
} else {
dismissView = true
appDelegate.openLogin(selector: NCGlobal.shared.introLogin, openLoginWeb: false)
appDelegate.openLogin(selector: NCGlobal.shared.introLogin)
}
}
}

Просмотреть файл

@ -41,9 +41,9 @@ struct NCAccountSettingsView: View {
Form {
Section(content: {
TabView(selection: $model.indexActiveAccount) {
ForEach(0..<model.accounts.count, id: \.self) { index in
ForEach(0..<model.tblAccounts.count, id: \.self) { index in
let status = model.getUserStatus()
let avatar = NCUtility().loadUserImage(for: model.accounts[index].user, displayName: model.accounts[index].displayName, userBaseUrl: model.accounts[index])
let avatar = NCUtility().loadUserImage(for: model.tblAccounts[index].user, displayName: model.tblAccounts[index].displayName, urlBase: model.tblAccounts[index].urlBase)
///
/// User
VStack {
@ -76,15 +76,15 @@ struct NCAccountSettingsView: View {
.frame(height: 20)
///
/// Personal data
if let activeAccount = model.activeAccount {
if !activeAccount.email.isEmpty {
if let tblAccount = model.tblAccount {
if !tblAccount.email.isEmpty {
HStack {
Image(systemName: "mail")
.resizable()
.scaledToFit()
.font(Font.system(.body).weight(.light))
.frame(width: 20, height: 20)
Text(activeAccount.email)
Text(tblAccount.email)
.lineLimit(1)
.truncationMode(.middle)
.frame(maxWidth: .infinity, alignment: .leading)
@ -92,28 +92,28 @@ struct NCAccountSettingsView: View {
}
.frame(maxWidth: .infinity, maxHeight: 30)
}
if !activeAccount.phone.isEmpty {
if !tblAccount.phone.isEmpty {
HStack {
Image(systemName: "phone")
.resizable()
.scaledToFit()
.font(Font.system(.body).weight(.light))
.frame(width: 20, height: 20)
Text(activeAccount.phone)
Text(tblAccount.phone)
.lineLimit(1)
.truncationMode(.middle)
.frame(maxWidth: .infinity, alignment: .leading)
}
.frame(maxWidth: .infinity, maxHeight: 30)
}
if !activeAccount.address.isEmpty {
if !tblAccount.address.isEmpty {
HStack {
Image(systemName: "house")
.resizable()
.scaledToFit()
.font(Font.system(.body).weight(.light))
.frame(width: 20, height: 20)
Text(activeAccount.address)
Text(tblAccount.address)
.lineLimit(1)
.truncationMode(.middle)
.frame(maxWidth: .infinity, alignment: .leading)
@ -130,7 +130,7 @@ struct NCAccountSettingsView: View {
.animation(.easeIn(duration: 0.3), value: animation)
.onChange(of: model.indexActiveAccount) { index in
animation.toggle()
model.setAccount(account: model.accounts[index].account)
model.setAccount(account: model.tblAccounts[index].account)
}
///
/// Change alias
@ -155,7 +155,7 @@ struct NCAccountSettingsView: View {
}
///
/// User Status
if NCGlobal.shared.capabilityUserStatusEnabled {
if NCCapabilities.shared.getCapabilities(account: model.tblAccount?.account).capabilityUserStatusEnabled {
Button(action: {
showUserStatus = true
}, label: {
@ -175,7 +175,9 @@ struct NCAccountSettingsView: View {
.font(.system(size: 14))
})
.sheet(isPresented: $showUserStatus) {
UserStatusView(showUserStatus: $showUserStatus)
if let account = model.tblAccount?.account {
UserStatusView(showUserStatus: $showUserStatus, account: account)
}
}
.onChange(of: showUserStatus) { _ in }
}
@ -201,7 +203,7 @@ struct NCAccountSettingsView: View {
.font(.system(size: 14))
})
.sheet(isPresented: $showServerCertificate) {
if let url = URL(string: model.activeAccount?.urlBase), let host = url.host {
if let url = URL(string: model.tblAccount?.urlBase), let host = url.host {
certificateDetailsView(host: host, title: NSLocalizedString("_certificate_view_", comment: ""))
}
}
@ -279,7 +281,7 @@ struct NCAccountSettingsView: View {
}
}
.onDisappear {
model.delegate?.accountSettingsDidDismiss(tableAccount: model.activeAccount)
model.delegate?.accountSettingsDidDismiss(tableAccount: model.tblAccount, controller: model.controller)
}
}
}

Просмотреть файл

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="nhT-TJ-YvX">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="nhT-TJ-YvX">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -20,28 +20,28 @@
<rect key="frame" x="0.0" y="48" width="414" height="848"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="tableCell" rowHeight="35" id="ggj-aE-fnh" customClass="NCActivityTableViewCell" customModule="Nextcloud" customModuleProvider="target">
<rect key="frame" x="0.0" y="50" width="414" height="35"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="tableCell" rowHeight="50" id="ggj-aE-fnh" customClass="NCActivityTableViewCell" customModule="Nextcloud" customModuleProvider="target">
<rect key="frame" x="0.0" y="50" width="414" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ggj-aE-fnh" id="i35-U4-bEk">
<rect key="frame" x="0.0" y="0.0" width="414" height="35"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" text="Label" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fcO-YL-MuT">
<rect key="frame" x="100" y="0.0" width="304" height="18"/>
<fontDescription key="fontDescription" name=".AppleSystemUIFont" family=".AppleSystemUIFont" pointSize="15"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" text="Label" lineBreakMode="tailTruncation" numberOfLines="4" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fcO-YL-MuT">
<rect key="frame" x="90" y="3" width="314" height="44"/>
<fontDescription key="fontDescription" name=".AppleSystemUIFont" family=".AppleSystemUIFont" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="LQ8-cO-794" userLabel="avatar">
<rect key="frame" x="50" y="0.0" width="35" height="35"/>
<imageView contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="LQ8-cO-794" userLabel="avatar">
<rect key="frame" x="50" y="12.5" width="25" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="35" id="OKz-e8-DzD"/>
<constraint firstAttribute="height" constant="35" id="fwd-J4-5uY"/>
<constraint firstAttribute="width" constant="25" id="OKz-e8-DzD" userLabel="25"/>
<constraint firstAttribute="height" constant="25" id="fwd-J4-5uY"/>
</constraints>
</imageView>
<imageView userInteractionEnabled="NO" alpha="0.59999999999999998" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="xNG-sf-PnA">
<rect key="frame" x="20" y="8" width="20" height="20"/>
<rect key="frame" x="20" y="15" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="20" id="Lbv-yi-vAh"/>
<constraint firstAttribute="height" constant="20" id="TML-VJ-2i3"/>
@ -50,12 +50,13 @@
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="fcO-YL-MuT" secondAttribute="trailing" constant="10" id="1pG-qk-inI"/>
<constraint firstItem="LQ8-cO-794" firstAttribute="top" secondItem="i35-U4-bEk" secondAttribute="top" id="3fU-rp-D7s"/>
<constraint firstItem="xNG-sf-PnA" firstAttribute="top" secondItem="i35-U4-bEk" secondAttribute="top" constant="8" id="4EB-59-y1Y"/>
<constraint firstAttribute="bottom" secondItem="fcO-YL-MuT" secondAttribute="bottom" constant="3" id="9Yo-kF-q3Y"/>
<constraint firstItem="xNG-sf-PnA" firstAttribute="leading" secondItem="i35-U4-bEk" secondAttribute="leading" constant="20" id="CRN-18-SeU"/>
<constraint firstItem="LQ8-cO-794" firstAttribute="centerY" secondItem="i35-U4-bEk" secondAttribute="centerY" id="Giz-bM-Jpm"/>
<constraint firstItem="xNG-sf-PnA" firstAttribute="centerY" secondItem="i35-U4-bEk" secondAttribute="centerY" id="PDf-gj-Y2F"/>
<constraint firstItem="fcO-YL-MuT" firstAttribute="leading" secondItem="LQ8-cO-794" secondAttribute="trailing" constant="15" id="am5-CT-0kZ" userLabel="Subject.leading = Icon.trailing + 50"/>
<constraint firstItem="LQ8-cO-794" firstAttribute="leading" secondItem="xNG-sf-PnA" secondAttribute="trailing" constant="10" id="aqp-Wu-9Hk"/>
<constraint firstItem="fcO-YL-MuT" firstAttribute="top" secondItem="i35-U4-bEk" secondAttribute="top" id="faC-by-km5"/>
<constraint firstItem="fcO-YL-MuT" firstAttribute="top" secondItem="i35-U4-bEk" secondAttribute="top" constant="3" id="faC-by-km5"/>
</constraints>
</tableViewCellContentView>
<connections>

Просмотреть файл

@ -25,6 +25,7 @@
import UIKit
import SwiftRichString
import NextcloudKit
import SVGKit
class NCActivity: UIViewController, NCSharePagingContent {
@IBOutlet weak var viewContainerConstraint: NSLayoutConstraint!
@ -36,9 +37,9 @@ class NCActivity: UIViewController, NCSharePagingContent {
var metadata: tableMetadata?
var showComments: Bool = false
let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
let utilityFileSystem = NCUtilityFileSystem()
let utility = NCUtility()
let database = NCManageDatabase.shared
var allItems: [DateCompareable] = []
var sectionDates: [Date] = []
var dataSourceTask: URLSessionTask?
@ -46,6 +47,7 @@ class NCActivity: UIViewController, NCSharePagingContent {
var insets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0)
var didSelectItemEnable: Bool = true
var objectType: String?
var account: String = ""
var isFetchingActivity = false
var hasActivityToLoad = true {
@ -53,6 +55,14 @@ class NCActivity: UIViewController, NCSharePagingContent {
}
var dateAutomaticFetch: Date?
var session: NCSession.Session {
if account.isEmpty {
NCSession.shared.getSession(controller: tabBarController)
} else {
NCSession.shared.getSession(account: account)
}
}
// MARK: - View Life Cycle
override func viewDidLoad() {
@ -74,15 +84,12 @@ class NCActivity: UIViewController, NCSharePagingContent {
func setupComments() {
// Display Name & Quota
guard let activeAccount = NCManageDatabase.shared.getActiveAccount(), height > 0 else {
return
}
guard let metadata else { return }
tableView.register(UINib(nibName: "NCShareCommentsCell", bundle: nil), forCellReuseIdentifier: "cell")
commentView = Bundle.main.loadNibNamed("NCActivityCommentView", owner: self, options: nil)?.first as? NCActivityCommentView
commentView?.setup(urlBase: appDelegate, account: activeAccount) { newComment in
commentView?.setup(account: metadata.account) { newComment in
guard let newComment = newComment, !newComment.isEmpty, let metadata = self.metadata else { return }
NextcloudKit.shared.putComments(fileId: metadata.fileId, message: newComment, account: self.appDelegate.account) { _, error in
NextcloudKit.shared.putComments(fileId: metadata.fileId, message: newComment, account: metadata.account) { _, _, error in
if error == .success {
self.commentView?.newCommentField.text?.removeAll()
self.loadComments()
@ -145,7 +152,7 @@ extension NCActivity: UITableViewDelegate {
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80
return 80.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
@ -209,34 +216,49 @@ extension NCActivity: UITableViewDataSource {
}
func makeCommentCell(_ comment: tableComments, for indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? NCShareCommentsCell else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? NCShareCommentsCell,
let metadata else {
return UITableViewCell()
}
cell.indexPath = indexPath
cell.tableComments = comment
cell.delegate = self
cell.sizeToFit()
// Image
let fileName = appDelegate.userBaseUrl + "-" + comment.actorId + ".png"
NCNetworking.shared.downloadAvatar(user: comment.actorId, dispalyName: comment.actorDisplayName, fileName: fileName, cell: cell, view: tableView)
// Avatar
let fileName = NCSession.shared.getFileName(urlBase: metadata.urlBase, user: comment.actorId)
let results = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName)
if results.image == nil {
cell.fileAvatarImageView?.image = utility.loadUserImage(for: comment.actorId, displayName: comment.actorDisplayName, urlBase: NCSession.shared.getSession(account: account).urlBase)
} else {
cell.fileAvatarImageView?.image = results.image
}
if let tableAvatar = results.tableAvatar,
!tableAvatar.loaded,
NCNetworking.shared.downloadAvatarQueue.operations.filter({ ($0 as? NCOperationDownloadAvatar)?.fileName == fileName }).isEmpty {
NCNetworking.shared.downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: comment.actorId, fileName: fileName, account: account, view: tableView))
}
// Username
cell.labelUser.text = comment.actorDisplayName
cell.labelUser.textColor = NCBrandColor.shared.textColor
// Date
cell.labelDate.text = utility.dateDiff(comment.creationDateTime as Date)
cell.labelDate.textColor = .systemGray4
cell.labelDate.textColor = .lightGray
// Message
cell.labelMessage.text = comment.message
cell.labelMessage.textColor = NCBrandColor.shared.textColor
// Button Menu
if comment.actorId == appDelegate.userId {
if comment.actorId == metadata.userId {
cell.buttonMenu.isHidden = false
} else {
cell.buttonMenu.isHidden = true
}
cell.sizeToFit()
return cell
}
@ -247,6 +269,7 @@ extension NCActivity: UITableViewDataSource {
var orderKeysId: [String] = []
cell.idActivity = activity.idActivity
cell.account = activity.account
cell.indexPath = indexPath
cell.avatar.image = nil
cell.avatar.isHidden = true
@ -256,18 +279,21 @@ extension NCActivity: UITableViewDataSource {
// icon
if !activity.icon.isEmpty {
activity.icon = activity.icon.replacingOccurrences(of: ".png", with: ".svg")
let fileNameIcon = (activity.icon as NSString).lastPathComponent
let fileNameLocalPath = utilityFileSystem.directoryUserData + "/" + fileNameIcon
if FileManager.default.fileExists(atPath: fileNameLocalPath) {
if let image = UIImage(contentsOfFile: fileNameLocalPath) {
let image = fileNameIcon.contains(".svg") ? SVGKImage(contentsOfFile: fileNameLocalPath)?.uiImage : UIImage(contentsOfFile: fileNameLocalPath)
if let image {
cell.icon.image = image.withTintColor(NCBrandColor.shared.textColor, renderingMode: .alwaysOriginal)
}
} else {
NextcloudKit.shared.downloadContent(serverUrl: activity.icon, account: appDelegate.account) { _, data, error in
if error == .success {
NextcloudKit.shared.downloadContent(serverUrl: activity.icon, account: activity.account) { _, responseData, error in
if error == .success, let data = responseData?.data {
do {
try data!.write(to: NSURL(fileURLWithPath: fileNameLocalPath) as URL, options: .atomic)
try data.write(to: NSURL(fileURLWithPath: fileNameLocalPath) as URL, options: .atomic)
self.tableView.reloadData()
} catch { return }
}
@ -276,12 +302,24 @@ extension NCActivity: UITableViewDataSource {
}
// avatar
if !activity.user.isEmpty && activity.user != appDelegate.userId {
if !activity.user.isEmpty && activity.user != session.userId {
cell.avatar.isHidden = false
cell.fileUser = activity.user
let fileName = appDelegate.userBaseUrl + "-" + activity.user + ".png"
NCNetworking.shared.downloadAvatar(user: activity.user, dispalyName: nil, fileName: fileName, cell: cell, view: tableView)
cell.subjectLeadingConstraint.constant = 15
let fileName = NCSession.shared.getFileName(urlBase: session.urlBase, user: activity.user)
let results = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName)
if results.image == nil {
cell.fileAvatarImageView?.image = utility.loadUserImage(for: activity.user, displayName: nil, urlBase: session.urlBase)
} else {
cell.fileAvatarImageView?.image = results.image
}
if !(results.tableAvatar?.loaded ?? false),
NCNetworking.shared.downloadAvatarQueue.operations.filter({ ($0 as? NCOperationDownloadAvatar)?.fileName == fileName }).isEmpty {
NCNetworking.shared.downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: activity.user, fileName: fileName, account: session.account, view: tableView))
}
} else {
cell.subjectLeadingConstraint.constant = -30
}
@ -300,7 +338,7 @@ extension NCActivity: UITableViewDataSource {
}
for key in keys {
if let result = NCManageDatabase.shared.getActivitySubjectRich(account: appDelegate.account, idActivity: activity.idActivity, key: key) {
if let result = database.getActivitySubjectRich(account: session.account, idActivity: activity.idActivity, key: key) {
orderKeysId.append(result.id)
subject = subject.replacingOccurrences(of: "{\(key)}", with: "<bold>" + result.name + "</bold>")
}
@ -371,13 +409,13 @@ extension NCActivity {
func loadDataSource() {
var newItems = [DateCompareable]()
if showComments, let metadata = metadata, let account = NCManageDatabase.shared.getActiveAccount() {
let comments = NCManageDatabase.shared.getComments(account: account.account, objectId: metadata.fileId)
if showComments, let metadata {
let comments = database.getComments(account: metadata.account, objectId: metadata.fileId)
newItems += comments
}
let activities = NCManageDatabase.shared.getActivity(
predicate: NSPredicate(format: "account == %@", appDelegate.account),
let activities = database.getActivity(
predicate: NSPredicate(format: "account == %@", session.account),
filterFileId: metadata?.fileId)
newItems += activities.filter
@ -395,7 +433,7 @@ extension NCActivity {
NextcloudKit.shared.getComments(fileId: metadata.fileId, account: metadata.account) { _, comments, _, error in
if error == .success, let comments = comments {
NCManageDatabase.shared.addComments(comments, account: metadata.account, objectId: metadata.fileId)
self.database.addComments(comments, account: metadata.account, objectId: metadata.fileId)
} else if error.errorCode != NCGlobal.shared.errorResourceNotFound {
NCContentPresenter().showError(error: error)
}
@ -410,7 +448,7 @@ extension NCActivity {
/// Check if most recent activivities are loaded, if not trigger reload
func checkRecentActivity(disptachGroup: DispatchGroup) {
guard let result = NCManageDatabase.shared.getLatestActivityId(account: appDelegate.account), metadata == nil, hasActivityToLoad else {
guard let result = database.getLatestActivityId(account: session.account), metadata == nil, hasActivityToLoad else {
return self.loadActivity(idActivity: 0, disptachGroup: disptachGroup)
}
let resultActivityId = max(result.activityFirstKnown, result.activityLastGiven)
@ -423,14 +461,14 @@ extension NCActivity {
objectId: nil,
objectType: objectType,
previews: true,
account: appDelegate.account) { task in
account: session.account) { task in
self.dataSourceTask = task
} completion: { account, _, activityFirstKnown, activityLastGiven, _, error in
defer { disptachGroup.leave() }
let largestActivityId = max(activityFirstKnown, activityLastGiven)
guard error == .success,
account == self.appDelegate.account,
account == self.session.account,
largestActivityId > resultActivityId
else {
self.hasActivityToLoad = error.errorCode == NCGlobal.shared.errorNotModified ? false : self.hasActivityToLoad
@ -452,26 +490,26 @@ extension NCActivity {
objectId: metadata?.fileId,
objectType: objectType,
previews: true,
account: appDelegate.account) { task in
account: session.account) { task in
self.dataSourceTask = task
} completion: { account, activities, activityFirstKnown, activityLastGiven, _, error in
defer { disptachGroup.leave() }
guard error == .success,
account == self.appDelegate.account,
account == self.session.account,
!activities.isEmpty
else {
self.hasActivityToLoad = error.errorCode == NCGlobal.shared.errorNotModified ? false : self.hasActivityToLoad
return
}
NCManageDatabase.shared.addActivity(activities, account: account)
self.database.addActivity(activities, account: account)
// update most recently loaded activity only when all activities are loaded (not filtered)
let largestActivityId = max(activityFirstKnown, activityLastGiven)
if let result = NCManageDatabase.shared.getLatestActivityId(account: self.appDelegate.account) {
if let result = self.database.getLatestActivityId(account: self.session.account) {
resultActivityId = max(result.activityFirstKnown, result.activityLastGiven)
}
if self.metadata == nil, largestActivityId > resultActivityId {
NCManageDatabase.shared.updateLatestActivityId(activityFirstKnown: activityFirstKnown, activityLastGiven: activityLastGiven, account: account)
self.database.updateLatestActivityId(activityFirstKnown: activityFirstKnown, activityLastGiven: activityLastGiven, account: account)
}
}
}
@ -482,7 +520,7 @@ extension NCActivity: NCShareCommentsCellDelegate {
guard let tableComment = tableComment else {
return
}
self.showProfileMenu(userId: tableComment.actorId)
self.showProfileMenu(userId: tableComment.actorId, session: session)
}
func tapMenu(with tableComments: tableComments?, sender: Any) {
@ -509,7 +547,7 @@ extension NCActivity: NCShareCommentsCellDelegate {
alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in
guard let message = alert.textFields?.first?.text, !message.isEmpty else { return }
NextcloudKit.shared.updateComments(fileId: metadata.fileId, messageId: tableComments.messageId, message: message, account: self.appDelegate.account) { _, error in
NextcloudKit.shared.updateComments(fileId: metadata.fileId, messageId: tableComments.messageId, message: message, account: metadata.account) { _, _, error in
if error == .success {
self.loadComments()
} else {
@ -531,7 +569,7 @@ extension NCActivity: NCShareCommentsCellDelegate {
action: { _ in
guard let metadata = self.metadata, let tableComments = tableComments else { return }
NextcloudKit.shared.deleteComments(fileId: metadata.fileId, messageId: tableComments.messageId, account: metadata.account) { _, error in
NextcloudKit.shared.deleteComments(fileId: metadata.fileId, messageId: tableComments.messageId, account: metadata.account) { _, _, error in
if error == .success {
self.loadComments()
} else {

Просмотреть файл

@ -29,12 +29,13 @@ class NCActivityCommentView: UIView, UITextFieldDelegate {
var completionHandler: ((String?) -> Void)?
func setup(urlBase: NCUserBaseUrl, account: tableAccount, completionHandler: @escaping (String?) -> Void) {
func setup(account: String, completionHandler: @escaping (String?) -> Void) {
let session = NCSession.shared.getSession(account: account)
self.completionHandler = completionHandler
newCommentField.placeholder = NSLocalizedString("_new_comment_", comment: "")
newCommentField.delegate = self
let fileName = urlBase.userBaseUrl + "-" + urlBase.user + ".png"
let fileName = NCSession.shared.getFileName(urlBase: session.urlBase, user: session.user)
let fileNameLocalPath = NCUtilityFileSystem().directoryUserData + "/" + fileName
if let image = UIImage(contentsOfFile: fileNameLocalPath) {
imageItem.image = image

Просмотреть файл

@ -22,10 +22,11 @@
//
import Foundation
import UIKit
import NextcloudKit
import FloatingPanel
import JGProgressHUD
import Queuer
import Alamofire
class NCActivityCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
@ -44,14 +45,15 @@ class NCActivityTableViewCell: UITableViewCell, NCCellProtocol {
@IBOutlet weak var subject: UILabel!
@IBOutlet weak var subjectLeadingConstraint: NSLayoutConstraint!
private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
private var user: String = ""
private var index = IndexPath()
var idActivity: Int = 0
var activityPreviews: [tableActivityPreview] = []
var didSelectItemEnable: Bool = true
var viewController = UIViewController()
var viewController = NCActivity()
var account: String!
let utility = NCUtility()
var indexPath: IndexPath {
@ -75,7 +77,7 @@ class NCActivityTableViewCell: UITableViewCell, NCCellProtocol {
@objc func tapAvatarImage() {
guard let fileUser = fileUser else { return }
viewController.showProfileMenu(userId: fileUser)
viewController.showProfileMenu(userId: fileUser, session: NCSession.shared.getSession(account: account))
}
}
@ -100,9 +102,9 @@ extension NCActivityTableViewCell: UICollectionViewDelegate {
}
if (responder as? UIViewController)!.navigationController != nil {
if let viewController = UIStoryboard(name: "NCTrash", bundle: nil).instantiateInitialViewController() as? NCTrash {
if let result = NCManageDatabase.shared.getTrashItem(fileId: String(activityPreview.fileId), account: activityPreview.account) {
viewController.blinkFileId = result.fileId
viewController.filePath = result.filePath
if let resultTableTrash = NCManageDatabase.shared.getResultTrashItem(fileId: String(activityPreview.fileId), account: activityPreview.account) {
viewController.blinkFileId = resultTableTrash.fileId
viewController.filePath = resultTableTrash.filePath
(responder as? UIViewController)!.navigationController?.pushViewController(viewController, animated: true)
} else {
let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_trash_file_not_found_")
@ -117,7 +119,7 @@ extension NCActivityTableViewCell: UICollectionViewDelegate {
guard let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: activityPreview.account, idActivity: activityPreview.idActivity, id: String(activityPreview.fileId)) else {
return
}
NCActionCenter.shared.viewerFile(account: appDelegate.account, fileId: activitySubjectRich.id, viewController: viewController)
NCActionCenter.shared.viewerFile(account: account, fileId: activitySubjectRich.id, viewController: viewController)
}
}
}
@ -133,9 +135,7 @@ extension NCActivityTableViewCell: UICollectionViewDataSource {
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell: NCActivityCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as? NCActivityCollectionViewCell else {
return UICollectionViewCell()
}
let cell: NCActivityCollectionViewCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as? NCActivityCollectionViewCell)!
cell.imageView.image = nil
cell.indexPath = indexPath
@ -147,22 +147,22 @@ extension NCActivityTableViewCell: UICollectionViewDataSource {
if activityPreview.view == "trashbin" {
let source = activityPreview.source
utility.convertSVGtoPNGWriteToUserData(svgUrlString: source, width: 100, rewrite: false, account: appDelegate.account, id: idActivity) { imageNamePath, id in
utility.convertSVGtoPNGWriteToUserData(svgUrlString: source, width: 100, rewrite: false, account: account, id: idActivity) { imageNamePath, id in
if let imageNamePath = imageNamePath, id == self.idActivity, let image = UIImage(contentsOfFile: imageNamePath) {
cell.imageView.image = image
} else {
cell.imageView.image = NCImageCache.images.file
cell.imageView.image = NCImageCache.shared.getImageFile()
}
}
} else {
if activityPreview.isMimeTypeIcon {
let source = activityPreview.source
utility.convertSVGtoPNGWriteToUserData(svgUrlString: source, width: 150, rewrite: false, account: appDelegate.account, id: idActivity) { imageNamePath, id in
utility.convertSVGtoPNGWriteToUserData(svgUrlString: source, width: 150, rewrite: false, account: account, id: idActivity) { imageNamePath, id in
if let imageNamePath = imageNamePath, id == self.idActivity, let image = UIImage(contentsOfFile: imageNamePath) {
cell.imageView.image = image
} else {
cell.imageView.image = NCImageCache.images.file
cell.imageView.image = NCImageCache.shared.getImageFile()
}
}
} else {
@ -178,7 +178,7 @@ extension NCActivityTableViewCell: UICollectionViewDataSource {
cell.fileId = fileId
if !FileManager.default.fileExists(atPath: fileNamePath) {
if NCNetworking.shared.downloadThumbnailActivityQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailActivity)?.fileId == fileId }).isEmpty {
NCNetworking.shared.downloadThumbnailActivityQueue.addOperation(NCOperationDownloadThumbnailActivity(fileId: fileId, fileNamePreviewLocalPath: fileNamePath, account: appDelegate.account, cell: cell, collectionView: collectionView))
NCNetworking.shared.downloadThumbnailActivityQueue.addOperation(NCOperationDownloadThumbnailActivity(fileId: fileId, fileNamePreviewLocalPath: fileNamePath, account: account, collectionView: collectionView))
}
}
}
@ -203,18 +203,16 @@ extension NCActivityTableViewCell: UICollectionViewDelegateFlowLayout {
}
}
class NCOperationDownloadThumbnailActivity: ConcurrentOperation {
var cell: NCActivityCollectionViewCell?
class NCOperationDownloadThumbnailActivity: ConcurrentOperation, @unchecked Sendable {
var collectionView: UICollectionView?
var fileNamePreviewLocalPath: String
var fileId: String
var account: String
init(fileId: String, fileNamePreviewLocalPath: String, account: String, cell: NCActivityCollectionViewCell?, collectionView: UICollectionView?) {
init(fileId: String, fileNamePreviewLocalPath: String, account: String, collectionView: UICollectionView?) {
self.fileNamePreviewLocalPath = fileNamePreviewLocalPath
self.fileId = fileId
self.account = account
self.cell = cell
self.collectionView = collectionView
}
@ -222,19 +220,15 @@ class NCOperationDownloadThumbnailActivity: ConcurrentOperation {
guard !isCancelled else { return self.finish() }
NextcloudKit.shared.downloadPreview(fileId: fileId,
fileNamePreviewLocalPath: fileNamePreviewLocalPath,
account: account,
options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { _, imagePreview, _, _, _, error in
if error == .success, let imagePreview = imagePreview {
DispatchQueue.main.async {
if self.fileId == self.cell?.fileId, let imageView = self.cell?.imageView {
UIView.transition(with: imageView,
account: account) { _, _, _, _, responseData, error in
if error == .success, let data = responseData?.data, let collectionView = self.collectionView {
for case let cell as NCActivityCollectionViewCell in collectionView.visibleCells {
if self.fileId == cell.fileId {
UIView.transition(with: cell.imageView,
duration: 0.75,
options: .transitionCrossDissolve,
animations: { imageView.image = imagePreview },
animations: { cell.imageView.image = UIImage(data: data) },
completion: nil)
} else {
self.collectionView?.reloadData()
}
}
}

Просмотреть файл

@ -32,20 +32,11 @@ import EasyTipView
import SwiftUI
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, NCUserBaseUrl {
var account: String = ""
var urlBase: String = ""
var user: String = ""
var userId: String = ""
var password: String = ""
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var tipView: EasyTipView?
var backgroundSessionCompletionHandler: (() -> Void)?
var activeLogin: NCLogin?
var activeLoginWeb: NCLoginProvider?
var timerErrorNetworking: Timer?
var timerErrorNetworkingDisabled: Bool = false
var taskAutoUploadDate: Date = Date()
var isUiTestingEnabled: Bool {
return ProcessInfo.processInfo.arguments.contains("UI_TESTING")
@ -58,15 +49,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if isUiTestingEnabled {
deleteAllAccounts()
NCAccount().deleteAllAccounts()
}
let utilityFileSystem = NCUtilityFileSystem()
let utility = NCUtility()
var levelLog = 0
let versionNextcloudiOS = String(format: NCBrandOptions.shared.textCopyrightNextcloudiOS, utility.getVersionApp())
NCSettingsBundleHelper.checkAndExecuteSettings(delay: 0)
let versionNextcloudiOS = String(format: NCBrandOptions.shared.textCopyrightNextcloudiOS, utility.getVersionApp())
UserDefaults.standard.register(defaults: ["UserAgent": userAgent])
if !NCKeychain().disableCrashservice, !NCBrandOptions.shared.disable_crash_service {
FirebaseApp.configure()
@ -76,14 +67,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
utilityFileSystem.emptyTemporaryDirectory()
utilityFileSystem.clearCacheDirectory("com.limit-point.LivePhoto")
// Activated singleton
_ = NCActionCenter.shared
_ = NCNetworking.shared
// Create users colors
NCBrandColor.shared.createUserColors()
NextcloudKit.shared.setup(delegate: NCNetworking.shared)
NextcloudKit.shared.setup(userAgent: userAgent)
var levelLog = 0
NextcloudKit.shared.nkCommonInstance.pathLog = utilityFileSystem.directoryGroup
if NCBrandOptions.shared.disable_log {
@ -96,37 +83,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Start session with level \(levelLog) " + versionNextcloudiOS)
}
if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Account active \(activeAccount.account)")
if NCKeychain().getPassword(account: activeAccount.account).isEmpty {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] PASSWORD NOT FOUND for \(activeAccount.account)")
}
account = activeAccount.account
urlBase = activeAccount.urlBase
user = activeAccount.user
userId = activeAccount.userId
password = NCKeychain().getPassword(account: account)
NextcloudKit.shared.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase)
NCManageDatabase.shared.setCapabilities(account: account)
NCBrandColor.shared.settingThemingColor(account: activeAccount.account)
DispatchQueue.global().async {
NCImageCache.shared.createMediaCache(account: self.account, withCacheSize: true)
}
} else {
NCKeychain().removeAll()
if let bundleID = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: bundleID)
}
}
NCBrandColor.shared.createUserColors()
NCImageCache.shared.createImagesCache()
// Push Notification & display notification
/// Push Notification & display notification
UNUserNotificationCenter.current().getNotificationSettings { settings in
self.notificationSettings = settings
}
@ -140,7 +97,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
review.showStoreReview()
}
// Background task register
/// Background task register
BGTaskScheduler.shared.register(forTaskWithIdentifier: NCGlobal.shared.refreshTask, using: nil) { task in
self.handleAppRefresh(task)
}
@ -148,12 +105,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
self.handleProcessingTask(task)
}
FileNameValidator.shared.setup(
forbiddenFileNames: NCGlobal.shared.capabilityForbiddenFileNames,
forbiddenFileNameBasenames: NCGlobal.shared.capabilityForbiddenFileNameBasenames,
forbiddenFileNameCharacters: NCGlobal.shared.capabilityForbiddenFileNameCharacters,
forbiddenFileNameExtensions: NCGlobal.shared.capabilityForbiddenFileNameExtensions
)
/// Activation singleton
_ = NCActionCenter.shared
_ = NCNetworkingProcess.shared
return true
}
@ -235,39 +189,46 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func handleAppRefreshProcessingTask(taskText: String, completion: @escaping () -> Void = {}) {
Task {
var itemsAutoUpload = 0
var numAutoUpload = 0
guard let account = NCManageDatabase.shared.getActiveTableAccount()?.account else {
return
}
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) start handle")
// Test every > 1 min
if Date() > self.taskAutoUploadDate.addingTimeInterval(60) {
self.taskAutoUploadDate = Date()
itemsAutoUpload = await NCAutoUpload.shared.initAutoUpload()
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) auto upload with \(itemsAutoUpload) uploads")
numAutoUpload = await NCAutoUpload.shared.initAutoUpload(account: account)
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) auto upload with \(numAutoUpload) uploads")
} else {
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) disabled auto upload")
}
let results = await NCNetworkingProcess.shared.start(scene: nil)
let results = await NCNetworkingProcess.shared.refreshProcessingTask()
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) networking process with download: \(results.counterDownloading) upload: \(results.counterUploading)")
if taskText == "ProcessingTask",
itemsAutoUpload == 0,
numAutoUpload == 0,
results.counterDownloading == 0,
results.counterUploading == 0,
let directories = NCManageDatabase.shared.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", self.account), sorted: "offlineDate", ascending: true) {
let directories = NCManageDatabase.shared.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", account), sorted: "offlineDate", ascending: true) {
for directory: tableDirectory in directories {
// test only 3 time for day (every 8 h.)
if let offlineDate = directory.offlineDate, offlineDate.addingTimeInterval(28800) > Date() {
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) skip synchronization for \(directory.serverUrl) in date \(offlineDate)")
continue
}
let results = await NCNetworking.shared.synchronization(account: self.account, serverUrl: directory.serverUrl, add: false)
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) end synchronization for \(directory.serverUrl), errorCode: \(results.errorCode), item: \(results.items)")
let results = await NCNetworking.shared.synchronization(account: account, serverUrl: directory.serverUrl, add: false)
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) end synchronization for \(directory.serverUrl), errorCode: \(results.errorCode), item: \(results.num)")
}
}
let counter = NCManageDatabase.shared.getResultsMetadatas(predicate: NSPredicate(format: "account == %@ AND (session == %@ || session == %@) AND status != %d", self.account, NCNetworking.shared.sessionDownloadBackground, NCNetworking.shared.sessionUploadBackground, NCGlobal.shared.metadataStatusNormal))?.count ?? 0
let counter = NCManageDatabase.shared.getResultsMetadatas(predicate: NSPredicate(format: "account == %@ AND (session == %@ || session == %@) AND status != %d",
account,
NCNetworking.shared.sessionDownloadBackground,
NCNetworking.shared.sessionUploadBackground,
NCGlobal.shared.metadataStatusNormal))?.count ?? 0
UIApplication.shared.applicationIconBadgeNumber = counter
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] \(taskText) completion handle")
@ -315,28 +276,28 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
func nextcloudPushNotificationAction(data: [String: AnyObject]) {
guard let data = NCApplicationHandle().nextcloudPushNotificationAction(data: data) else { return }
var findAccount: Bool = false
var findAccount: String?
if let accountPush = data["account"] as? String {
if accountPush == self.account {
findAccount = true
} else {
let accounts = NCManageDatabase.shared.getAllAccount()
for account in accounts {
if account.account == accountPush {
self.changeAccount(account.account, userProfile: nil) {
findAccount = true
for tableAccount in NCManageDatabase.shared.getAllTableAccount() {
if tableAccount.account == accountPush {
for controller in SceneManager.shared.getControllers() {
if controller.account == accountPush {
NCAccount().changeAccount(tableAccount.account, userProfile: nil, controller: controller) {
findAccount = tableAccount.account
}
}
}
}
if findAccount, let viewController = UIStoryboard(name: "NCNotification", bundle: nil).instantiateInitialViewController() as? NCNotification {
}
if let account = findAccount, let viewController = UIStoryboard(name: "NCNotification", bundle: nil).instantiateInitialViewController() as? NCNotification {
viewController.session = NCSession.shared.getSession(account: account)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
let navigationController = UINavigationController(rootViewController: viewController)
navigationController.modalPresentationStyle = .fullScreen
UIApplication.shared.firstWindow?.rootViewController?.present(navigationController, animated: true)
}
} else if !findAccount {
} else {
let message = NSLocalizedString("_the_account_", comment: "") + " " + accountPush + " " + NSLocalizedString("_does_not_exist_", comment: "")
let alertController = UIAlertController(title: NSLocalizedString("_info_", comment: ""), message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in }))
@ -347,7 +308,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// MARK: - Login
func openLogin(selector: Int, openLoginWeb: Bool, windowForRootViewController: UIWindow? = nil) {
func openLogin(selector: Int) {
UIApplication.shared.allSceneSessionDestructionExceptFirst()
func showLoginViewController(_ viewController: UIViewController?) {
guard let viewController else { return }
let navigationController = NCLoginNavigationController(rootViewController: viewController)
@ -358,20 +321,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
navigationController.navigationBar.barTintColor = NCBrandColor.shared.customer
navigationController.navigationBar.isTranslucent = false
if let window = windowForRootViewController {
window.rootViewController = navigationController
window.makeKeyAndVisible()
} else {
UIApplication.shared.allSceneSessionDestructionExceptFirst()
if let rootVC = UIApplication.shared.firstWindow?.rootViewController {
if let presentedVC = rootVC.presentedViewController, !(presentedVC is NCLoginNavigationController) {
if let controller = UIApplication.shared.firstWindow?.rootViewController {
if let presentedVC = controller.presentedViewController, !(presentedVC is NCLoginNavigationController) {
presentedVC.dismiss(animated: false) {
rootVC.present(navigationController, animated: true)
controller.present(navigationController, animated: true)
}
} else {
rootVC.present(navigationController, animated: true)
}
controller.present(navigationController, animated: true)
}
}
}
@ -379,14 +335,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// Nextcloud standard login
if selector == NCGlobal.shared.introSignup {
if activeLogin?.view.window == nil {
activeLogin = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLogin") as? NCLogin
if selector == NCGlobal.shared.introSignup {
activeLogin?.urlBase = NCBrandOptions.shared.linkloginPreferredProviders
let web = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLoginProvider") as? NCLoginProvider
web?.urlBase = NCBrandOptions.shared.linkloginPreferredProviders
showLoginViewController(web)
} else {
activeLogin?.urlBase = self.urlBase
activeLogin = UIStoryboard(name: "NCLogin", bundle: nil).instantiateViewController(withIdentifier: "NCLogin") as? NCLogin
if let controller = UIApplication.shared.firstWindow?.rootViewController as? NCMainTabBarController, !controller.account.isEmpty {
let session = NCSession.shared.getSession(account: controller.account)
activeLogin?.urlBase = session.urlBase
}
showLoginViewController(activeLogin)
}
}
@ -399,35 +357,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
}
// MARK: - Error Networking
func startTimerErrorNetworking(scene: UIScene) {
timerErrorNetworkingDisabled = false
timerErrorNetworking = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(checkErrorNetworking(_:)), userInfo: nil, repeats: true)
}
@objc private func checkErrorNetworking(_ notification: NSNotification) {
guard !self.timerErrorNetworkingDisabled,
!account.isEmpty,
NCKeychain().getPassword(account: account).isEmpty else { return }
let description = String.localizedStringWithFormat(NSLocalizedString("_error_check_remote_user_", comment: ""))
let error = NKError(errorCode: NCKeychain().getPassword(account: account).isEmpty ? NCGlobal.shared.errorUnauthorized997 : NCGlobal.shared.errorInternalServerError, errorDescription: description)
NCContentPresenter().showError(error: error, priority: .max)
deleteAccount(account)
let accounts = NCManageDatabase.shared.getAccounts()
if accounts?.count ?? 0 > 0, let newAccount = accounts?.first {
changeAccount(newAccount, userProfile: nil) { }
} else {
openLogin(selector: NCGlobal.shared.introLogin, openLoginWeb: false)
}
}
// MARK: -
func trustCertificateError(host: String) {
guard let currentHost = URL(string: self.urlBase)?.host,
guard let activeTableAccount = NCManageDatabase.shared.getActiveTableAccount(),
let currentHost = URL(string: activeTableAccount.urlBase)?.host,
let pushNotificationServerProxyHost = URL(string: NCBrandOptions.shared.pushNotificationServerProxy)?.host,
host != pushNotificationServerProxyHost,
host == currentHost
@ -459,136 +393,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
UIApplication.shared.firstWindow?.rootViewController?.present(alertController, animated: true)
}
// MARK: - Account
func createAccount(urlBase: String,
user: String,
password: String,
completion: @escaping (_ error: NKError) -> Void) {
var urlBase = urlBase
if urlBase.last == "/" { urlBase = String(urlBase.dropLast()) }
let account: String = "\(user) \(urlBase)"
NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase)
NextcloudKit.shared.getUserProfile(account: account) { account, userProfile, _, error in
if error == .success, let userProfile {
NCManageDatabase.shared.deleteAccount(account)
NCManageDatabase.shared.addAccount(account, urlBase: urlBase, user: user, userId: userProfile.userId, password: password)
NCKeychain().setClientCertificate(account: account, p12Data: NCNetworking.shared.p12Data, p12Password: NCNetworking.shared.p12Password)
self.changeAccount(account, userProfile: userProfile) {
completion(error)
}
} else {
NextcloudKit.shared.setup(account: self.account, user: self.user, userId: self.userId, password: self.password, urlBase: self.urlBase)
let alertController = UIAlertController(title: NSLocalizedString("_error_", comment: ""), message: error.errorDescription, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in }))
UIApplication.shared.firstWindow?.rootViewController?.present(alertController, animated: true)
completion(error)
}
}
}
func changeAccount(_ account: String,
userProfile: NKUserProfile?,
completion: () -> Void) {
guard let tableAccount = NCManageDatabase.shared.setAccountActive(account) else {
return completion()
}
NCNetworking.shared.cancelAllQueue()
NCNetworking.shared.cancelDataTask()
NCNetworking.shared.cancelDownloadTasks()
NCNetworking.shared.cancelUploadTasks()
if account != self.account {
DispatchQueue.global().async {
if NCManageDatabase.shared.getAccounts()?.count == 1 {
NCImageCache.shared.createMediaCache(account: account, withCacheSize: true)
} else {
NCImageCache.shared.createMediaCache(account: account, withCacheSize: false)
}
}
}
self.account = tableAccount.account
self.urlBase = tableAccount.urlBase
self.user = tableAccount.user
self.userId = tableAccount.userId
self.password = NCKeychain().getPassword(account: tableAccount.account)
NextcloudKit.shared.setup(account: account, user: user, userId: userId, password: password, urlBase: urlBase)
NCManageDatabase.shared.setCapabilities(account: account)
if let userProfile {
NCManageDatabase.shared.setAccountUserProfile(account: account, userProfile: userProfile)
}
NCPushNotification.shared.pushNotification()
NCService().startRequestServicesServer(account: self.account, user: self.user, userId: self.userId)
NCAutoUpload.shared.initAutoUpload(viewController: nil) { items in
NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] Initialize Auto upload with \(items) uploads")
}
FileNameValidator.shared.setup(
forbiddenFileNames: NCGlobal.shared.capabilityForbiddenFileNames,
forbiddenFileNameBasenames: NCGlobal.shared.capabilityForbiddenFileNameBasenames,
forbiddenFileNameCharacters: NCGlobal.shared.capabilityForbiddenFileNameCharacters,
forbiddenFileNameExtensions: NCGlobal.shared.capabilityForbiddenFileNameExtensions
)
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterChangeUser)
completion()
}
func deleteAccount(_ account: String) {
UIApplication.shared.allSceneSessionDestructionExceptFirst()
if let account = NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "account == %@", account)) {
NCPushNotification.shared.unsubscribingNextcloudServerPushNotification(account: account.account, urlBase: account.urlBase, user: account.user, withSubscribing: false)
}
let results = NCManageDatabase.shared.getTableLocalFiles(predicate: NSPredicate(format: "account == %@", account), sorted: "ocId", ascending: false)
let utilityFileSystem = NCUtilityFileSystem()
for result in results {
utilityFileSystem.removeFile(atPath: utilityFileSystem.getDirectoryProviderStorageOcId(result.ocId))
}
NCManageDatabase.shared.clearDatabase(account: account, removeAccount: true)
NCKeychain().clearAllKeysEndToEnd(account: account)
NCKeychain().clearAllKeysPushNotification(account: account)
NCKeychain().setPassword(account: account, password: nil)
self.account = ""
self.urlBase = ""
self.user = ""
self.userId = ""
self.password = ""
}
func deleteAllAccounts() {
let accounts = NCManageDatabase.shared.getAccounts()
accounts?.forEach({ account in
deleteAccount(account)
})
}
func updateShareAccounts() -> Error? {
guard let dirGroupApps = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.shared.capabilitiesGroupApps) else { return nil }
let tableAccount = NCManageDatabase.shared.getAllAccount()
var accounts = [NKShareAccounts.DataAccounts]()
for account in tableAccount {
let name = account.alias.isEmpty ? account.displayName : account.alias
let userBaseUrl = account.user + "-" + (URL(string: account.urlBase)?.host ?? "")
let avatarFileName = userBaseUrl + "-\(account.user).png"
let pathAvatarFileName = NCUtilityFileSystem().directoryUserData + "/" + avatarFileName
let image = UIImage(contentsOfFile: pathAvatarFileName)
accounts.append(NKShareAccounts.DataAccounts(withUrl: account.urlBase, user: account.user, name: name, image: image))
}
return NKShareAccounts().putShareAccounts(at: dirGroupApps, app: NCGlobal.shared.appScheme, dataAccounts: accounts)
}
// MARK: - Reset Application
func resetApplication() {
@ -596,8 +400,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
NCNetworking.shared.cancelAllTask()
URLCache.shared.memoryCapacity = 0
URLCache.shared.diskCapacity = 0
URLCache.shared.removeAllCachedResponses()
utilityFileSystem.removeGroupDirectoryProviderStorage()
utilityFileSystem.removeGroupApplicationSupport()
@ -605,6 +408,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
utilityFileSystem.removeTemporaryDirectory()
NCKeychain().removeAll()
NCNetworking.shared.removeAllKeyUserDefaultsData(account: nil)
exit(0)
}

Просмотреть файл

@ -55,7 +55,7 @@ struct NCAssistantCreateNewTask: View {
}
#Preview {
let model = NCAssistantTask()
let model = NCAssistantTask(controller: nil)
return NCAssistantCreateNewTask()
.environmentObject(model)

Просмотреть файл

@ -7,6 +7,7 @@
//
import Foundation
import UIKit
import NextcloudKit
import SwiftUI
@ -17,12 +18,16 @@ class NCAssistantTask: ObservableObject {
@Published var selectedTask: NKTextProcessingTask?
@Published var hasError: Bool = false
@Published var isLoading: Bool = false
@Published var controller: NCMainTabBarController?
private var tasks: [NKTextProcessingTask] = []
private let excludedTypeIds = ["OCA\\ContextChat\\TextProcessing\\ContextChatTaskType"]
private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
private var session: NCSession.Session {
NCSession.shared.getSession(controller: controller)
}
init() {
init(controller: NCMainTabBarController?) {
self.controller = controller
load()
}
@ -50,7 +55,7 @@ class NCAssistantTask: ObservableObject {
guard let id = task.id else { return }
isLoading = true
NextcloudKit.shared.textProcessingGetTask(taskId: id, account: appDelegate.account) { _, task, _, error in
NextcloudKit.shared.textProcessingGetTask(taskId: id, account: session.account) { _, task, _, error in
self.isLoading = false
if error != .success {
@ -65,7 +70,7 @@ class NCAssistantTask: ObservableObject {
func scheduleTask(input: String) {
isLoading = true
NextcloudKit.shared.textProcessingSchedule(input: input, typeId: selectedType?.id ?? "", identifier: "assistant", account: appDelegate.account) { _, task, _, error in
NextcloudKit.shared.textProcessingSchedule(input: input, typeId: selectedType?.id ?? "", identifier: "assistant", account: session.account) { _, task, _, error in
self.isLoading = false
if error != .success {
@ -86,7 +91,7 @@ class NCAssistantTask: ObservableObject {
guard let id = task.id else { return }
isLoading = true
NextcloudKit.shared.textProcessingDeleteTask(taskId: id, account: appDelegate.account) { _, task, _, error in
NextcloudKit.shared.textProcessingDeleteTask(taskId: id, account: session.account) { _, task, _, error in
self.isLoading = false
if error != .success {
@ -105,7 +110,7 @@ class NCAssistantTask: ObservableObject {
private func loadAllTypes() {
isLoading = true
NextcloudKit.shared.textProcessingGetTypes(account: appDelegate.account) { _, types, _, error in
NextcloudKit.shared.textProcessingGetTypes(account: session.account) { _, types, _, error in
self.isLoading = false
if error != .success {
@ -130,7 +135,7 @@ class NCAssistantTask: ObservableObject {
private func loadAllTasks(appId: String = "assistant") {
isLoading = true
NextcloudKit.shared.textProcessingTaskList(appId: appId, account: appDelegate.account) { _, tasks, _, error in
NextcloudKit.shared.textProcessingTaskList(appId: appId, account: session.account) { _, tasks, _, error in
self.isLoading = false
if error != .success {

Просмотреть файл

@ -81,7 +81,7 @@ struct NCAssistant: View {
}
#Preview {
let model = NCAssistantTask()
let model = NCAssistantTask(controller: nil)
return NCAssistant()
.environmentObject(model)
@ -125,7 +125,7 @@ struct TypeButton: View {
.padding(.vertical, 7)
.foregroundStyle(model.selectedType?.id == taskType?.id ? .white : .primary)
.if(model.selectedType?.id == taskType?.id) { view in
view.background(Color(NCBrandColor.shared.brandElement))
view.background(Color(NCBrandColor.shared.getElement(account: model.controller?.account)))
}
.if(model.selectedType?.id != taskType?.id) { view in
view.background(.ultraThinMaterial)

Просмотреть файл

@ -9,6 +9,7 @@
import SwiftUI
struct NCAssistantEmptyView: View {
@EnvironmentObject var model: NCAssistantTask
let titleKey, subtitleKey: String
var body: some View {
@ -17,7 +18,7 @@ struct NCAssistantEmptyView: View {
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundStyle(Color(NCBrandColor.shared.brandElement))
.foregroundStyle(Color(NCBrandColor.shared.getElement(account: model.controller?.account)))
.font(Font.system(.body).weight(.light))
.frame(height: 100)

Просмотреть файл

@ -28,7 +28,7 @@ struct NCAssistantTaskDetail: View {
}
#Preview {
let model = NCAssistantTask()
let model = NCAssistantTask(controller: nil)
return NCAssistantTaskDetail(task: NKTextProcessingTask(id: 1, type: "OCP\\TextProcessing\\FreePromptTaskType", status: 1, userId: "christine", appId: "assistant", input: "", output: "", identifier: "", completionExpectedAt: 1712666412))
.environmentObject(model)

Просмотреть файл

@ -27,20 +27,22 @@
import UIKit
import AVFoundation
import QuartzCore
import NextcloudKit
class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate {
var recording: NCAudioRecorder!
var startDate: Date = Date()
var fileName: String = ""
var serverUrl = ""
let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
@IBOutlet weak var contentContainerView: UIView!
@IBOutlet weak var durationLabel: UILabel!
@IBOutlet weak var startStopLabel: UILabel!
@IBOutlet weak var voiceRecordHUD: VoiceRecordHUD!
var recording: NCAudioRecorder!
var startDate: Date = Date()
var fileName: String = ""
var controller: NCMainTabBarController!
var session: NCSession.Session {
NCSession.shared.getSession(controller: controller)
}
// MARK: - View Life Cycle
override func viewDidLoad() {
@ -55,7 +57,7 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate {
voiceRecordHUD.fillColor = UIColor.green
Task {
self.fileName = await NCNetworking.shared.createFileName(fileNameBase: NSLocalizedString("_untitled_", comment: "") + ".m4a", account: self.appDelegate.account, serverUrl: self.serverUrl)
self.fileName = await NCNetworking.shared.createFileName(fileNameBase: NSLocalizedString("_untitled_", comment: "") + ".m4a", account: self.session.account, serverUrl: controller.currentServerUrl())
recording = NCAudioRecorder(to: self.fileName)
recording.delegate = self
do {
@ -97,7 +99,15 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate {
func uploadMetadata() {
let fileNamePath = NSTemporaryDirectory() + self.fileName
let metadata = NCManageDatabase.shared.createMetadata(account: appDelegate.account, user: appDelegate.user, userId: appDelegate.userId, fileName: fileName, fileNameView: fileName, ocId: UUID().uuidString, serverUrl: self.serverUrl, urlBase: appDelegate.urlBase, url: "", contentType: "")
let metadata = NCManageDatabase.shared.createMetadata(fileName: fileName,
fileNameView: fileName,
ocId: UUID().uuidString,
serverUrl: controller.currentServerUrl(),
url: "",
contentType: "",
session: self.session,
sceneIdentifier: self.controller?.sceneIdentifier)
metadata.session = NCNetworking.shared.sessionUploadBackground
metadata.sessionSelector = NCGlobal.shared.selectorUploadFile
metadata.status = NCGlobal.shared.metadataStatusWaitUpload

Просмотреть файл

@ -22,7 +22,7 @@
//
import UIKit
import WebKit
@preconcurrency import WebKit
@objc protocol NCBrowserWebDelegate: AnyObject {
@objc optional func browserWebDismiss()

Просмотреть файл

@ -129,7 +129,7 @@ class NCColorPicker: UIViewController {
systemIndigoButton.layer.cornerRadius = 5
systemIndigoButton.layer.masksToBounds = true
defaultButton.backgroundColor = NCBrandColor.shared.brandElement
defaultButton.backgroundColor = NCBrandColor.shared.customer
defaultButton.layer.cornerRadius = 5
defaultButton.layer.masksToBounds = true
}
@ -214,7 +214,7 @@ class NCColorPicker: UIViewController {
let serverUrl = metadata.serverUrl + "/" + metadata.fileName
NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, colorFolder: hexColor, metadata: metadata)
self.dismiss(animated: true)
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource)
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl, "clearDataSource": true])
}
self.dismiss(animated: true)
}

Просмотреть файл

@ -22,10 +22,11 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit
class tableAccount: Object, NCUserBaseUrl {
class tableAccount: Object {
@objc dynamic var account = ""
@objc dynamic var active: Bool = false
@objc dynamic var address = ""
@ -84,13 +85,16 @@ extension NCManageDatabase {
do {
let realm = try Realm()
try realm.write {
let addObject = tableAccount()
addObject.account = account
if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
realm.delete(result)
}
let tableAccount = tableAccount()
tableAccount.account = account
NCKeychain().setPassword(account: account, password: password)
addObject.urlBase = urlBase
addObject.user = user
addObject.userId = userId
realm.add(addObject, update: .all)
tableAccount.urlBase = urlBase
tableAccount.user = user
tableAccount.userId = userId
realm.add(tableAccount, update: .all)
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
@ -108,19 +112,7 @@ extension NCManageDatabase {
}
}
func deleteAccount(_ account: String) {
do {
let realm = try Realm()
try realm.write {
let result = realm.objects(tableAccount.self).filter("account == %@", account)
realm.delete(result)
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
}
}
func getActiveAccount() -> tableAccount? {
func getActiveTableAccount() -> tableAccount? {
do {
let realm = try Realm()
guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return nil }
@ -131,6 +123,17 @@ extension NCManageDatabase {
return nil
}
func getTableAccount(account: String) -> tableAccount? {
do {
let realm = try Realm()
guard let result = realm.objects(tableAccount.self).filter("account == %@", account).first else { return nil }
return tableAccount.init(value: result)
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
}
return nil
}
func getAccounts() -> [String]? {
do {
let realm = try Realm()
@ -144,7 +147,7 @@ extension NCManageDatabase {
return nil
}
func getAccount(predicate: NSPredicate) -> tableAccount? {
func getTableAccount(predicate: NSPredicate) -> tableAccount? {
do {
let realm = try Realm()
guard let result = realm.objects(tableAccount.self).filter(predicate).first else { return nil }
@ -155,7 +158,7 @@ extension NCManageDatabase {
return nil
}
func getAllAccount() -> [tableAccount] {
func getAllTableAccount() -> [tableAccount] {
do {
let realm = try Realm()
let sorted = [SortDescriptor(keyPath: "active", ascending: false), SortDescriptor(keyPath: "user", ascending: true)]
@ -194,16 +197,16 @@ extension NCManageDatabase {
return ""
}
func getAccountAutoUploadDirectory(urlBase: String, userId: String, account: String) -> String {
func getAccountAutoUploadDirectory(session: NCSession.Session) -> String {
do {
let realm = try Realm()
guard let result = realm.objects(tableAccount.self).filter("active == true").first else { return "" }
if result.autoUploadDirectory.isEmpty {
return utilityFileSystem.getHomeServer(urlBase: urlBase, userId: userId)
return utilityFileSystem.getHomeServer(session: session)
} else {
// FIX change webdav -> /dav/files/
if result.autoUploadDirectory.contains("/webdav") {
return utilityFileSystem.getHomeServer(urlBase: urlBase, userId: userId)
return utilityFileSystem.getHomeServer(session: session)
} else {
return result.autoUploadDirectory
}
@ -214,9 +217,9 @@ extension NCManageDatabase {
return ""
}
func getAccountAutoUploadPath(urlBase: String, userId: String, account: String) -> String {
func getAccountAutoUploadPath(session: NCSession.Session) -> String {
let cameraFileName = self.getAccountAutoUploadFileName()
let cameraDirectory = self.getAccountAutoUploadDirectory(urlBase: urlBase, userId: userId, account: account)
let cameraDirectory = self.getAccountAutoUploadDirectory(session: session)
let folderPhotos = utilityFileSystem.stringAppendServerUrl(cameraDirectory, addFileName: cameraFileName)
return folderPhotos
}
@ -232,9 +235,7 @@ extension NCManageDatabase {
return NCGlobal.shared.subfolderGranularityMonthly
}
func setAccountActive(_ account: String) -> tableAccount? {
var accountReturn = tableAccount()
func setAccountActive(_ account: String) {
do {
let realm = try Realm()
try realm.write {
@ -242,27 +243,11 @@ extension NCManageDatabase {
for result in results {
if result.account == account {
result.active = true
accountReturn = result
} else {
result.active = false
}
}
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
return nil
}
return tableAccount.init(value: accountReturn)
}
func removePasswordAccount(_ account: String) {
do {
let realm = try Realm()
try realm.write {
if let result = realm.objects(tableAccount.self).filter("account == %@", account).first {
result.password = "********"
}
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
}
@ -309,7 +294,7 @@ extension NCManageDatabase {
}
}
func setAccountAutoUploadDirectory(_ serverUrl: String?, urlBase: String, userId: String, account: String) {
func setAccountAutoUploadDirectory(_ serverUrl: String?, session: NCSession.Session) {
do {
let realm = try Realm()
try realm.write {
@ -317,7 +302,7 @@ extension NCManageDatabase {
if let serverUrl = serverUrl {
result.autoUploadDirectory = serverUrl
} else {
result.autoUploadDirectory = self.getAccountAutoUploadDirectory(urlBase: urlBase, userId: userId, account: account)
result.autoUploadDirectory = self.getAccountAutoUploadDirectory(session: session)
}
}
}

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit
import SwiftyJSON

Просмотреть файл

@ -104,8 +104,9 @@ extension NCManageDatabase {
return image
}
func getImageAvatarLoaded(fileName: String) -> UIImage? {
func getImageAvatarLoaded(fileName: String) -> (image: UIImage?, tableAvatar: tableAvatar?) {
let fileNameLocalPath = utilityFileSystem.directoryUserData + "/" + fileName
let image = UIImage(contentsOfFile: fileNameLocalPath)
do {
let realm = try Realm()
@ -113,16 +114,13 @@ extension NCManageDatabase {
let result = realm.objects(tableAvatar.self).filter("fileName == %@", fileName).first
if result == nil {
utilityFileSystem.removeFile(atPath: fileNameLocalPath)
return nil
} else if result?.loaded == false {
return nil
}
return UIImage(contentsOfFile: fileNameLocalPath)
return (image, result)
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
}
utilityFileSystem.removeFile(atPath: fileNameLocalPath)
return nil
return (nil, nil)
}
}

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit
@ -62,7 +63,8 @@ extension NCManageDatabase {
return nil
}
func setCapabilities(account: String, data: Data? = nil) {
@discardableResult
func setCapabilities(account: String, data: Data? = nil) -> NCCapabilities.Capabilities? {
let jsonData: Data?
struct CapabilityNextcloud: Codable {
@ -285,97 +287,108 @@ extension NCManageDatabase {
let ocs: Ocs
}
if let data = data {
if let data {
jsonData = data
} else {
do {
let realm = try Realm()
guard let result = realm.objects(tableCapabilities.self).filter("account == %@", account).first,
let data = result.jsondata else {
return
return nil
}
jsonData = data
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
return
return nil
}
}
guard let jsonData = jsonData else { return }
guard let jsonData = jsonData else {
return nil
}
do {
let global = NCGlobal.shared
let json = try JSONDecoder().decode(CapabilityNextcloud.self, from: jsonData)
let data = json.ocs.data
let capabilities = NCCapabilities.Capabilities()
global.capabilityServerVersion = data.version.string
global.capabilityServerVersionMajor = data.version.major
capabilities.capabilityServerVersion = data.version.string
capabilities.capabilityServerVersionMajor = data.version.major
if global.capabilityServerVersionMajor > 0 {
NextcloudKit.shared.setup(nextcloudVersion: global.capabilityServerVersionMajor)
if capabilities.capabilityServerVersionMajor > 0 {
NextcloudKit.shared.updateSession(account: account, nextcloudVersion: capabilities.capabilityServerVersionMajor)
}
global.capabilityFileSharingApiEnabled = data.capabilities.filessharing?.apienabled ?? false
global.capabilityFileSharingDefaultPermission = data.capabilities.filessharing?.defaultpermissions ?? 0
global.capabilityFileSharingPubPasswdEnforced = data.capabilities.filessharing?.ncpublic?.password?.enforced ?? false
global.capabilityFileSharingPubExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredate?.enforced ?? false
global.capabilityFileSharingPubExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredate?.days ?? 0
global.capabilityFileSharingInternalExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredateinternal?.enforced ?? false
global.capabilityFileSharingInternalExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredateinternal?.days ?? 0
global.capabilityFileSharingRemoteExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredateremote?.enforced ?? false
global.capabilityFileSharingRemoteExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredateremote?.days ?? 0
capabilities.capabilityFileSharingApiEnabled = data.capabilities.filessharing?.apienabled ?? false
capabilities.capabilityFileSharingDefaultPermission = data.capabilities.filessharing?.defaultpermissions ?? 0
capabilities.capabilityFileSharingPubPasswdEnforced = data.capabilities.filessharing?.ncpublic?.password?.enforced ?? false
capabilities.capabilityFileSharingPubExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredate?.enforced ?? false
capabilities.capabilityFileSharingPubExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredate?.days ?? 0
capabilities.capabilityFileSharingInternalExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredateinternal?.enforced ?? false
capabilities.capabilityFileSharingInternalExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredateinternal?.days ?? 0
capabilities.capabilityFileSharingRemoteExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredateremote?.enforced ?? false
capabilities.capabilityFileSharingRemoteExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredateremote?.days ?? 0
global.capabilityThemingColor = data.capabilities.theming?.color ?? ""
global.capabilityThemingColorElement = data.capabilities.theming?.colorelement ?? ""
global.capabilityThemingColorText = data.capabilities.theming?.colortext ?? ""
global.capabilityThemingName = data.capabilities.theming?.name ?? ""
global.capabilityThemingSlogan = data.capabilities.theming?.slogan ?? ""
capabilities.capabilityThemingColor = data.capabilities.theming?.color ?? ""
capabilities.capabilityThemingColorElement = data.capabilities.theming?.colorelement ?? ""
capabilities.capabilityThemingColorText = data.capabilities.theming?.colortext ?? ""
capabilities.capabilityThemingName = data.capabilities.theming?.name ?? ""
capabilities.capabilityThemingSlogan = data.capabilities.theming?.slogan ?? ""
global.capabilityE2EEEnabled = data.capabilities.endtoendencryption?.enabled ?? false
global.capabilityE2EEApiVersion = data.capabilities.endtoendencryption?.apiversion ?? ""
capabilities.capabilityE2EEEnabled = data.capabilities.endtoendencryption?.enabled ?? false
capabilities.capabilityE2EEApiVersion = data.capabilities.endtoendencryption?.apiversion ?? ""
global.capabilityRichDocumentsEnabled = json.ocs.data.capabilities.richdocuments?.directediting ?? false
global.capabilityRichDocumentsMimetypes.removeAll()
capabilities.capabilityRichDocumentsEnabled = json.ocs.data.capabilities.richdocuments?.directediting ?? false
capabilities.capabilityRichDocumentsMimetypes.removeAll()
if let mimetypes = data.capabilities.richdocuments?.mimetypes {
for mimetype in mimetypes {
global.capabilityRichDocumentsMimetypes.append(mimetype)
capabilities.capabilityRichDocumentsMimetypes.append(mimetype)
}
}
global.capabilityAssistantEnabled = data.capabilities.assistant?.enabled ?? false
capabilities.capabilityAssistantEnabled = data.capabilities.assistant?.enabled ?? false
global.capabilityActivity.removeAll()
capabilities.capabilityActivity.removeAll()
if let activities = data.capabilities.activity?.apiv2 {
for activity in activities {
global.capabilityActivity.append(activity)
capabilities.capabilityActivity.append(activity)
}
}
global.capabilityNotification.removeAll()
capabilities.capabilityNotification.removeAll()
if let notifications = data.capabilities.notifications?.ocsendpoints {
for notification in notifications {
global.capabilityNotification.append(notification)
capabilities.capabilityNotification.append(notification)
}
}
global.capabilityFilesUndelete = data.capabilities.files?.undelete ?? false
global.capabilityFilesLockVersion = data.capabilities.files?.locking ?? ""
global.capabilityFilesComments = data.capabilities.files?.comments ?? false
global.capabilityFilesBigfilechunking = data.capabilities.files?.bigfilechunking ?? false
capabilities.capabilityFilesUndelete = data.capabilities.files?.undelete ?? false
capabilities.capabilityFilesLockVersion = data.capabilities.files?.locking ?? ""
capabilities.capabilityFilesComments = data.capabilities.files?.comments ?? false
capabilities.capabilityFilesBigfilechunking = data.capabilities.files?.bigfilechunking ?? false
global.capabilityUserStatusEnabled = data.capabilities.userstatus?.enabled ?? false
capabilities.capabilityUserStatusEnabled = data.capabilities.userstatus?.enabled ?? false
if data.capabilities.external != nil {
global.capabilityExternalSites = true
capabilities.capabilityExternalSites = true
}
global.capabilityGroupfoldersEnabled = data.capabilities.groupfolders?.hasGroupFolders ?? false
global.capabilitySecurityGuardDiagnostics = data.capabilities.securityguard?.diagnostics ?? false
capabilities.capabilityGroupfoldersEnabled = data.capabilities.groupfolders?.hasGroupFolders ?? false
global.capabilityForbiddenFileNames = data.capabilities.files?.forbiddenFileNames ?? []
global.capabilityForbiddenFileNameBasenames = data.capabilities.files?.forbiddenFileNameBasenames ?? []
global.capabilityForbiddenFileNameCharacters = data.capabilities.files?.forbiddenFileNameCharacters ?? []
global.capabilityForbiddenFileNameExtensions = data.capabilities.files?.forbiddenFileNameExtensions ?? []
if capabilities.capabilityServerVersionMajor >= NCGlobal.shared.nextcloudVersion28 {
capabilities.isLivePhotoServerAvailable = true
}
capabilities.capabilitySecurityGuardDiagnostics = data.capabilities.securityguard?.diagnostics ?? false
capabilities.capabilityForbiddenFileNames = data.capabilities.files?.forbiddenFileNames ?? []
capabilities.capabilityForbiddenFileNameBasenames = data.capabilities.files?.forbiddenFileNameBasenames ?? []
capabilities.capabilityForbiddenFileNameCharacters = data.capabilities.files?.forbiddenFileNameCharacters ?? []
capabilities.capabilityForbiddenFileNameExtensions = data.capabilities.files?.forbiddenFileNameExtensions ?? []
NCCapabilities.shared.appendCapabilities(account: account, capabilities: capabilities)
return capabilities
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
return
return nil
}
}
}

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit
@ -102,7 +103,7 @@ extension NCManageDatabase {
let results = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl BEGINSWITH %@", account, serverUrl)
for result in results {
self.deleteMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", result.account, result.serverUrl))
self.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", result.ocId))
self.deleteLocalFileOcId(result.ocId)
}
try realm.write {
realm.delete(results)
@ -142,19 +143,6 @@ extension NCManageDatabase {
}
}
func cleanEtagDirectory(account: String, serverUrl: String) {
do {
let realm = try Realm()
try realm.write {
if let result = realm.objects(tableDirectory.self).filter("account == %@ AND serverUrl == %@", account, serverUrl).first {
result.etag = ""
}
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
}
}
func getTableDirectory(predicate: NSPredicate) -> tableDirectory? {
do {
let realm = try Realm()

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit
@ -100,11 +101,13 @@ extension NCManageDatabase {
}
}
func deleteLocalFile(predicate: NSPredicate) {
func deleteLocalFileOcId(_ ocId: String?) {
guard let ocId else { return }
do {
let realm = try Realm()
try realm.write {
let results = realm.objects(tableLocalFile.self).filter(predicate)
let results = realm.objects(tableLocalFile.self).filter("ocId == %@", ocId)
realm.delete(results)
}
} catch let error {

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit
@ -29,6 +30,7 @@ extension NCManageDatabase {
func setMetadataSession(ocId: String,
newFileName: String? = nil,
session: String? = nil,
sessionTaskIdentifier: Int? = nil,
sessionError: String? = nil,
selector: String? = nil,
status: Int? = nil,
@ -46,6 +48,9 @@ extension NCManageDatabase {
if let session {
result.session = session
}
if let sessionTaskIdentifier {
result.sessionTaskIdentifier = sessionTaskIdentifier
}
if let sessionError {
result.sessionError = sessionError
if sessionError.isEmpty {
@ -76,31 +81,6 @@ extension NCManageDatabase {
}
}
func setMetadataSession(ocId: String,
status: Int? = nil,
taskIdentifier: Int? = nil) {
do {
let realm = try Realm()
try realm.write {
if let result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first {
if let status {
result.status = status
if status == NCGlobal.shared.metadataStatusWaitDownload || status == NCGlobal.shared.metadataStatusWaitUpload {
result.sessionDate = Date()
} else if status == NCGlobal.shared.metadataStatusNormal {
result.sessionDate = nil
}
}
if let taskIdentifier {
result.sessionTaskIdentifier = taskIdentifier
}
}
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
}
}
@discardableResult
func setMetadatasSessionInWaitDownload(metadatas: [tableMetadata], session: String, selector: String, sceneIdentifier: String? = nil) -> tableMetadata? {
if metadatas.isEmpty { return nil }
@ -113,6 +93,7 @@ extension NCManageDatabase {
if let result = realm.objects(tableMetadata.self).filter("ocId == %@", metadata.ocId).first {
result.sceneIdentifier = sceneIdentifier
result.session = session
result.sessionTaskIdentifier = 0
result.sessionError = ""
result.sessionSelector = selector
result.status = NCGlobal.shared.metadataStatusWaitDownload
@ -121,6 +102,7 @@ extension NCManageDatabase {
} else {
metadata.sceneIdentifier = sceneIdentifier
metadata.session = session
metadata.sessionTaskIdentifier = 0
metadata.sessionError = ""
metadata.sessionSelector = selector
metadata.status = NCGlobal.shared.metadataStatusWaitDownload
@ -137,17 +119,39 @@ extension NCManageDatabase {
return metadataUpdated
}
func clearMetadataSession(metadatas: Results<tableMetadata>) {
func clearMetadataSession(metadatas: [tableMetadata]) {
do {
let realm = try Realm()
try realm.write {
for metadata in metadatas {
metadata.sceneIdentifier = nil
metadata.session = ""
metadata.sessionError = ""
metadata.sessionSelector = ""
metadata.sessionDate = nil
metadata.status = NCGlobal.shared.metadataStatusNormal
if let result = realm.objects(tableMetadata.self).filter("ocId == %@", metadata.ocId).first {
result.sceneIdentifier = nil
result.session = ""
result.sessionTaskIdentifier = 0
result.sessionError = ""
result.sessionSelector = ""
result.sessionDate = nil
result.status = NCGlobal.shared.metadataStatusNormal
}
}
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
}
}
func clearMetadataSession(metadata: tableMetadata) {
do {
let realm = try Realm()
try realm.write {
if let result = realm.objects(tableMetadata.self).filter("ocId == %@", metadata.ocId).first {
result.sceneIdentifier = nil
result.session = ""
result.sessionTaskIdentifier = 0
result.sessionError = ""
result.sessionSelector = ""
result.sessionDate = nil
result.status = NCGlobal.shared.metadataStatusNormal
}
}
} catch let error {
@ -164,6 +168,12 @@ extension NCManageDatabase {
try realm.write {
result = realm.objects(tableMetadata.self).filter("ocId == %@", ocId).first
result?.status = status
if status == NCGlobal.shared.metadataStatusNormal {
result?.sessionDate = nil
} else {
result?.sessionDate = Date()
}
}
} catch let error {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
@ -184,6 +194,9 @@ extension NCManageDatabase {
if serverUrl.hasSuffix("/") {
serverUrl = String(serverUrl.dropLast())
}
return NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "serverUrl == %@ AND fileName == %@ AND sessionTaskIdentifier == %d", serverUrl, fileName, sessionTaskIdentifier))
return getMetadata(predicate: NSPredicate(format: "serverUrl == %@ AND fileName == %@ AND sessionTaskIdentifier == %d",
serverUrl,
fileName,
sessionTaskIdentifier))
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit
@ -113,24 +114,22 @@ extension NCManageDatabase {
}
}
func getTrash(filePath: String, account: String) -> [tableTrash] {
func getResultsTrash(filePath: String, account: String) -> Results<tableTrash>? {
do {
let realm = try Realm()
realm.refresh()
let results = realm.objects(tableTrash.self).filter("account == %@ AND filePath == %@", account, filePath).sorted(byKeyPath: "trashbinDeletionTime", ascending: false)
return Array(results.map { tableTrash.init(value: $0) })
return realm.objects(tableTrash.self).filter("account == %@ AND filePath == %@", account, filePath).sorted(byKeyPath: "trashbinDeletionTime", ascending: false)
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)")
}
return []
return nil
}
func getTrashItem(fileId: String, account: String) -> tableTrash? {
func getResultTrashItem(fileId: String, account: String) -> tableTrash? {
do {
let realm = try Realm()
realm.refresh()
guard let result = realm.objects(tableTrash.self).filter("account == %@ AND fileId == %@", account, fileId).first else { return nil }
return tableTrash.init(value: result)
return realm.objects(tableTrash.self).filter("account == %@ AND fileId == %@", account, fileId).first
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access to database: \(error)")
}

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -22,6 +22,7 @@
//
import Foundation
import UIKit
import RealmSwift
import NextcloudKit

Просмотреть файл

@ -27,6 +27,7 @@ import RealmSwift
import NextcloudKit
import CoreMedia
import Photos
import CommonCrypto
protocol DateCompareable {
var dateKey: Date { get }
@ -41,17 +42,20 @@ class NCManageDatabase: NSObject {
override init() {
func migrationSchema(_ migration: Migration, _ oldSchemaVersion: UInt64) {
if oldSchemaVersion < 354 {
migration.deleteData(forType: NCDBLayoutForView.className())
if oldSchemaVersion < 365 {
migration.deleteData(forType: tableMetadata.className())
migration.enumerateObjects(ofType: tableDirectory.className()) { _, newObject in
newObject?["etag"] = ""
}
}
}
func compactDB(_ totalBytes: Int, _ usedBytes: Int) -> Bool {
// totalBytes refers to the size of the file on disk in bytes (data + free space)
// usedBytes refers to the number of bytes used by data in the file
// Compact if the file is over 100MB in size and less than 50% 'used'
let oneHundredMB = 100 * 1024 * 1024
return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5
let usedPercentage = (Double(usedBytes) / Double(totalBytes)) * 100
/// Compact the database if more than 25% of the space is free
let shouldCompact = (usedPercentage < 75.0) && (totalBytes > 100 * 1024 * 1024)
return shouldCompact
}
var realm: Realm?
let dirGroup = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
@ -60,7 +64,8 @@ class NCManageDatabase: NSObject {
let bundlePathExtension: String = bundleUrl.pathExtension
let bundleFileName: String = (bundleUrl.path as NSString).lastPathComponent
let isAppex: Bool = bundlePathExtension == "appex"
var objectTypesAppex = [tableMetadata.self,
var objectTypesAppex = [NCKeyValue.self,
tableMetadata.self,
tableLocalFile.self,
tableDirectory.self,
tableTag.self,
@ -94,12 +99,14 @@ class NCManageDatabase: NSObject {
if isAppex {
if bundleFileName == "File Provider Extension.appex" {
objectTypesAppex = [tableMetadata.self,
objectTypesAppex = [NCKeyValue.self,
tableMetadata.self,
tableLocalFile.self,
tableDirectory.self,
tableTag.self,
tableAccount.self,
tableCapabilities.self]
tableCapabilities.self,
tableE2eEncryption.self]
}
do {
Realm.Configuration.defaultConfiguration =
@ -145,7 +152,6 @@ class NCManageDatabase: NSObject {
let realm = try Realm()
try realm.write {
var results: Results<Object>
if let account = account {
results = realm.objects(table).filter("account == %@", account)
} else {
@ -159,7 +165,7 @@ class NCManageDatabase: NSObject {
}
}
func clearDatabase(account: String?, removeAccount: Bool) {
func clearDatabase(account: String? = nil, removeAccount: Bool = false) {
if removeAccount {
self.clearTable(tableAccount.self, account: account)
}
@ -216,6 +222,24 @@ class NCManageDatabase: NSObject {
return nil
}
func realmRefresh() {
do {
let realm = try Realm()
realm.refresh()
} catch let error as NSError {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not refresh database: \(error)")
}
}
func sha256Hash(_ input: String) -> String {
let data = Data(input.utf8)
var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &digest)
}
return digest.map { String(format: "%02hhx", $0) }.joined()
}
// MARK: -
// MARK: Func T
@ -250,17 +274,22 @@ class NCManageDatabase: NSObject {
/// Account
let account = "marinofaggiana https://cloudtest.nextcloud.com"
let account2 = "mariorossi https://cloudtest.nextcloud.com"
NCManageDatabase.shared.addAccount(account, urlBase: "https://cloudtest.nextcloud.com", user: "marinofaggiana", userId: "marinofaggiana", password: "password")
NCManageDatabase.shared.addAccount(account2, urlBase: "https://cloudtest.nextcloud.com", user: "mariorossi", userId: "mariorossi", password: "password")
addAccount(account, urlBase: "https://cloudtest.nextcloud.com", user: "marinofaggiana", userId: "marinofaggiana", password: "password")
addAccount(account2, urlBase: "https://cloudtest.nextcloud.com", user: "mariorossi", userId: "mariorossi", password: "password")
let userProfile = NKUserProfile()
userProfile.displayName = "Marino Faggiana"
userProfile.address = "Hirschstrasse 26, 70192 Stuttgart, Germany"
userProfile.phone = "+49 (711) 252 428 - 90"
userProfile.email = "cloudtest@nextcloud.com"
NCManageDatabase.shared.setAccountUserProfile(account: account, userProfile: userProfile)
setAccountUserProfile(account: account, userProfile: userProfile)
let userProfile2 = NKUserProfile()
userProfile2.displayName = "Mario Rossi"
userProfile2.email = "cloudtest@nextcloud.com"
NCManageDatabase.shared.setAccountUserProfile(account: account2, userProfile: userProfile2)
setAccountUserProfile(account: account2, userProfile: userProfile2)
}
}
class NCKeyValue: Object {
@Persisted var key: String = ""
@Persisted var value: String?
}

Просмотреть файл

@ -103,6 +103,7 @@ class NCDeepLinkHandler {
controller.selectedIndex = ControllerConstants.filesIndex
guard let navigationController = controller.viewControllers?[controller.selectedIndex] as? UINavigationController,
let viewController = UIStoryboard(name: ControllerConstants.notification, bundle: nil).instantiateInitialViewController() as? NCNotification else { return }
viewController.session = NCSession.shared.getSession(controller: controller)
navigationController.pushViewController(viewController, animated: true)
}
@ -111,10 +112,11 @@ class NCDeepLinkHandler {
controller.selectedIndex = ControllerConstants.filesIndex
DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
let serverUrl = controller.currentServerUrl()
let fileFolderPath = NCUtilityFileSystem().getFileNamePath("", serverUrl: serverUrl, urlBase: appDelegate.urlBase, userId: appDelegate.userId)
let session = NCSession.shared.getSession(controller: controller)
let fileFolderPath = NCUtilityFileSystem().getFileNamePath("", serverUrl: serverUrl, session: session)
let fileFolderName = (serverUrl as NSString).lastPathComponent
if !FileNameValidator.shared.checkFolderPath(folderPath: fileFolderPath) {
if !FileNameValidator.shared.checkFolderPath(fileFolderPath, account: controller.account) {
controller.present(UIAlertController.warning(message: "\(String(format: NSLocalizedString("_file_name_validator_error_reserved_name_", comment: ""), fileFolderName)) \(NSLocalizedString("_please_rename_file_", comment: ""))"), animated: true)
return

Просмотреть файл

@ -25,7 +25,6 @@ import Foundation
import UIKit
extension NotificationCenter {
func postOnMainThread(name: String, object anObject: Any? = nil, userInfo aUserInfo: [AnyHashable: Any]? = nil, second: Double = 0) {
DispatchQueue.main.asyncAfter(deadline: .now() + second) {
NotificationCenter.default.post(name: Notification.Name(rawValue: name), object: anObject, userInfo: aUserInfo)

Просмотреть файл

@ -32,16 +32,21 @@ extension UIAlertController {
/// - urlBase: UrlBase object
/// - completion: If not` nil` it overrides the default behavior which shows an error using `NCContentPresenter`
/// - Returns: The presentable alert controller
static func createFolder(serverUrl: String, userBaseUrl: NCUserBaseUrl, markE2ee: Bool = false, sceneIdentifier: String? = nil, completion: ((_ error: NKError) -> Void)? = nil) -> UIAlertController {
static func createFolder(serverUrl: String, account: String, markE2ee: Bool = false, sceneIdentifier: String? = nil, completion: ((_ error: NKError) -> Void)? = nil) -> UIAlertController {
let alertController = UIAlertController(title: NSLocalizedString("_create_folder_", comment: ""), message: nil, preferredStyle: .alert)
let session = NCSession.shared.getSession(account: account)
let isDirectoryEncrypted = NCUtilityFileSystem().isDirectoryE2EE(session: session, serverUrl: serverUrl)
let okAction = UIAlertAction(title: NSLocalizedString("_save_", comment: ""), style: .default, handler: { _ in
guard let fileNameFolder = alertController.textFields?.first?.text else { return }
if markE2ee {
if NCNetworking.shared.isOffline {
return NCContentPresenter().showInfo(error: NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_offline_not_allowed_"))
}
Task {
let createFolderResults = await NCNetworking.shared.createFolder(serverUrlFileName: serverUrl + "/" + fileNameFolder, account: userBaseUrl.account)
let createFolderResults = await NCNetworking.shared.createFolder(serverUrlFileName: serverUrl + "/" + fileNameFolder, account: session.account)
if createFolderResults.error == .success {
let error = await NCNetworkingE2EEMarkFolder().markFolderE2ee(account: userBaseUrl.account, fileName: fileNameFolder, serverUrl: serverUrl, userId: userBaseUrl.userId)
let error = await NCNetworkingE2EEMarkFolder().markFolderE2ee(account: session.account, fileName: fileNameFolder, serverUrl: serverUrl, userId: session.userId)
if error != .success {
NCContentPresenter().showError(error: error)
}
@ -49,14 +54,29 @@ extension UIAlertController {
NCContentPresenter().showError(error: createFolderResults.error)
}
}
} else {
NCNetworking.shared.createFolder(fileName: fileNameFolder, serverUrl: serverUrl, account: userBaseUrl.account, urlBase: userBaseUrl.urlBase, userId: userBaseUrl.userId, overwrite: false, withPush: true, sceneIdentifier: sceneIdentifier) { error in
if let completion = completion {
completion(error)
} else if error != .success {
NCContentPresenter().showError(error: error)
} // else: successful, no action
} else if isDirectoryEncrypted {
if NCNetworking.shared.isOffline {
return NCContentPresenter().showInfo(error: NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "_offline_not_allowed_"))
}
#if !EXTENSION
Task {
await NCNetworkingE2EECreateFolder().createFolder(fileName: fileNameFolder, serverUrl: serverUrl, withPush: true, sceneIdentifier: sceneIdentifier, session: session)
}
#endif
} else {
let metadataForCreateFolder = NCManageDatabase.shared.createMetadata(fileName: fileNameFolder,
fileNameView: fileNameFolder,
ocId: NSUUID().uuidString,
serverUrl: serverUrl,
url: "",
contentType: "httpd/unix-directory",
directory: true,
session: session,
sceneIdentifier: sceneIdentifier)
metadataForCreateFolder.status = NCGlobal.shared.metadataStatusWaitCreateFolder
metadataForCreateFolder.sessionDate = Date()
NCManageDatabase.shared.addMetadata(metadataForCreateFolder)
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCreateFolder, userInfo: ["ocId": metadataForCreateFolder.ocId, "serverUrl": metadataForCreateFolder.serverUrl, "account": metadataForCreateFolder.account, "withPush": true, "sceneIdentifier": sceneIdentifier as Any])
}
})
@ -76,7 +96,7 @@ extension UIAlertController {
guard let text = alertController.textFields?.first?.text else { return }
let folderName = text.trimmingCharacters(in: .whitespaces)
let textCheck = FileNameValidator.shared.checkFileName(folderName)
let textCheck = FileNameValidator.shared.checkFileName(folderName, account: account)
okAction.isEnabled = textCheck?.error == nil && !folderName.isEmpty
alertController.message = textCheck?.error.localizedDescription
}
@ -107,24 +127,15 @@ extension UIAlertController {
}, completion: completion)
}
static func deleteFileOrFolder(titleString: String, message: String?, canDeleteServer: Bool, selectedMetadatas: [tableMetadata], completion: @escaping (_ cancelled: Bool) -> Void) -> UIAlertController {
static func deleteFileOrFolder(titleString: String, message: String?, canDeleteServer: Bool, selectedMetadatas: [tableMetadata], sceneIdentifier: String?, completion: @escaping (_ cancelled: Bool) -> Void) -> UIAlertController {
let alertController = UIAlertController(
title: titleString,
message: message,
preferredStyle: .alert)
if canDeleteServer {
alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_", comment: ""), style: .destructive) { (_: UIAlertAction) in
Task {
var error = NKError()
var ocId: [String] = []
for metadata in selectedMetadatas where error == .success {
error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: false)
if error == .success {
ocId.append(metadata.ocId)
}
}
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "onlyLocalCache": false, "error": error])
}
NCNetworking.shared.deleteMetadatas(selectedMetadatas, sceneIdentifier: sceneIdentifier)
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource)
completion(false)
})
}
@ -134,15 +145,12 @@ extension UIAlertController {
var error = NKError()
var ocId: [String] = []
for metadata in selectedMetadatas where error == .success {
error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: true)
error = await NCNetworking.shared.deleteCache(metadata, sceneIdentifier: sceneIdentifier)
if error == .success {
ocId.append(metadata.ocId)
}
}
if error != .success {
NCContentPresenter().showError(error: error)
}
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "onlyLocalCache": true, "error": error])
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "error": error])
}
completion(false)
})
@ -153,7 +161,7 @@ extension UIAlertController {
return alertController
}
static func renameFile(fileName: String, completion: @escaping (_ newFileName: String) -> Void) -> UIAlertController {
static func renameFile(fileName: String, account: String, completion: @escaping (_ newFileName: String) -> Void) -> UIAlertController {
let alertController = UIAlertController(title: NSLocalizedString("_rename_", comment: ""), message: nil, preferredStyle: .alert)
let okAction = UIAlertAction(title: NSLocalizedString("_save_", comment: ""), style: .default, handler: { _ in
@ -190,7 +198,7 @@ extension UIAlertController {
queue: .main) { _ in
guard let text = alertController.textFields?.first?.text else { return }
let textCheck = FileNameValidator.shared.checkFileName(text)
let textCheck = FileNameValidator.shared.checkFileName(text, account: account)
okAction.isEnabled = textCheck?.error == nil && !text.isEmpty
alertController.message = textCheck?.error.localizedDescription
}
@ -200,28 +208,21 @@ extension UIAlertController {
return alertController
}
static func renameFile(metadata: tableMetadata, indexPath: IndexPath) -> UIAlertController {
static func renameFile(metadata: tableMetadata) -> UIAlertController {
let alertController = UIAlertController(title: NSLocalizedString("_rename_", comment: ""), message: nil, preferredStyle: .alert)
let okAction = UIAlertAction(title: NSLocalizedString("_save_", comment: ""), style: .default, handler: { _ in
guard let newFileName = alertController.textFields?.first?.text else { return }
guard let fileNameNew = alertController.textFields?.first?.text else { return }
// verify if already exists
if NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", metadata.account, metadata.serverUrl, newFileName)) != nil {
if NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", metadata.account, metadata.serverUrl, fileNameNew)) != nil {
NCContentPresenter().showError(error: NKError(errorCode: 0, errorDescription: "_rename_already_exists_"))
return
}
NCActivityIndicator.shared.start()
NCNetworking.shared.renameMetadata(metadata, fileNameNew: fileNameNew)
NCNetworking.shared.renameMetadata(metadata, fileNameNew: newFileName, indexPath: indexPath) { error in
NCActivityIndicator.shared.stop()
if error != .success {
NCContentPresenter().showError(error: error)
}
}
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSource, userInfo: ["serverUrl": metadata.serverUrl])
})
// text field is initially empty, no action
@ -229,7 +230,7 @@ extension UIAlertController {
let cancelAction = UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel)
alertController.addTextField { textField in
textField.text = metadata.fileName
textField.text = metadata.fileNameView
textField.autocapitalizationType = .words
}
@ -252,7 +253,7 @@ extension UIAlertController {
queue: .main) { _ in
guard let text = alertController.textFields?.first?.text else { return }
let textCheck = FileNameValidator.shared.checkFileName(text)
let textCheck = FileNameValidator.shared.checkFileName(text, account: NCManageDatabase.shared.getActiveTableAccount()?.account)
okAction.isEnabled = textCheck?.error == nil && !text.isEmpty
alertController.message = textCheck?.error.localizedDescription
}

Просмотреть файл

@ -26,9 +26,7 @@ import UIKit
import Accelerate
extension UIImage {
@objc func resizeImage(size: CGSize, isAspectRation: Bool = true) -> UIImage? {
func resizeImage(size: CGSize, isAspectRation: Bool = true) -> UIImage? {
let originRatio = self.size.width / self.size.height
let newRatio = size.width / size.height
var newSize = size
@ -44,13 +42,9 @@ extension UIImage {
}
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
if let image = newImage {
return image
}
return self
self.draw(in: CGRect(origin: .zero, size: newSize))
defer { UIGraphicsEndImageContext() }
return UIGraphicsGetImageFromCurrentImageContext()
}
func fixedOrientation() -> UIImage? {

Просмотреть файл

@ -33,7 +33,8 @@ class NCFavorite: NCCollectionViewCommon {
layoutKey = NCGlobal.shared.layoutViewFavorite
enableSearchBar = false
headerRichWorkspaceDisable = true
emptyImage = utility.loadImage(named: "star.fill", colors: [NCBrandColor.shared.yellowFavorite])
emptyImageName = "star.fill"
emptyImageColors = [NCBrandColor.shared.yellowFavorite]
emptyTitle = "_favorite_no_files_"
emptyDescription = "_tutorial_favorite_view_"
}
@ -43,43 +44,44 @@ class NCFavorite: NCCollectionViewCommon {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if dataSource.metadatas.isEmpty {
reloadDataSource()
}
reloadDataSourceNetwork()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
getServerData()
}
// MARK: - DataSource + NC Endpoint
// MARK: - DataSource
override func queryDB() {
super.queryDB()
var metadatas: [tableMetadata] = []
override func reloadDataSource() {
var predicate = self.defaultPredicate
if self.serverUrl.isEmpty {
metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND favorite == true", self.appDelegate.account))
} else {
metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
predicate = NSPredicate(format: "account == %@ AND favorite == true", session.account)
}
self.dataSource = NCDataSource(metadatas: metadatas, account: self.appDelegate.account, layoutForView: layoutForView, providers: self.providers, searchResults: self.searchResults)
let results = self.database.getResultsMetadatasPredicate(predicate, layoutForView: layoutForView)
self.dataSource = NCCollectionViewDataSource(results: results, layoutForView: layoutForView)
super.reloadDataSource()
}
override func reloadDataSourceNetwork(withQueryDB: Bool = false) {
super.reloadDataSourceNetwork()
NextcloudKit.shared.listingFavorites(showHiddenFiles: NCKeychain().showHiddenFiles, account: self.appDelegate.account, options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { task in
override func getServerData() {
NextcloudKit.shared.listingFavorites(showHiddenFiles: NCKeychain().showHiddenFiles, account: session.account) { task in
self.dataSourceTask = task
if self.dataSource.isEmpty() {
self.collectionView.reloadData()
}
} completion: { account, files, _, error in
if error == .success {
NCManageDatabase.shared.convertFilesToMetadatas(files, useFirstAsMetadataFolder: false) { _, metadatas in
NCManageDatabase.shared.updateMetadatasFavorite(account: account, metadatas: metadatas)
if error == .success, let files {
self.database.convertFilesToMetadatas(files, useFirstAsMetadataFolder: false) { _, metadatas in
self.database.updateMetadatasFavorite(account: account, metadatas: metadatas)
}
self.reloadDataSource()
}
} else {
self.reloadDataSource(withQueryDB: withQueryDB)
}
self.refreshControl.endRefreshing()
}
}
}

Просмотреть файл

@ -23,11 +23,13 @@
import UIKit
import NextcloudKit
import RealmSwift
class NCFiles: NCCollectionViewCommon {
internal var isRoot: Bool = true
internal var fileNameBlink: String?
internal var fileNameOpen: String?
internal var matadatasHash: String = ""
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
@ -37,7 +39,6 @@ class NCFiles: NCCollectionViewCommon {
enableSearchBar = true
headerRichWorkspaceDisable = false
headerMenuTransferView = true
emptyImage = NCImageCache.images.folder
emptyTitle = "_files_no_files_"
emptyDescription = "_no_file_pull_down_"
}
@ -48,44 +49,65 @@ class NCFiles: NCCollectionViewCommon {
super.viewDidLoad()
if isRoot {
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeUser), object: nil, queue: nil) { _ in
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeUser), object: nil, queue: nil) { notification in
if let userInfo = notification.userInfo, let account = userInfo["account"] as? String {
if let controller = userInfo["controller"] as? NCMainTabBarController,
controller == self.controller {
controller.account = account
} else {
return
}
}
self.navigationController?.popToRootViewController(animated: false)
self.serverUrl = self.utilityFileSystem.getHomeServer(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId)
self.serverUrl = self.utilityFileSystem.getHomeServer(session: self.session)
self.isSearchingMode = false
self.isEditMode = false
self.selectOcId.removeAll()
self.fileSelect.removeAll()
self.layoutForView = self.database.getLayoutForView(account: self.session.account, key: self.layoutKey, serverUrl: self.serverUrl)
self.layoutForView = NCManageDatabase.shared.getLayoutForView(account: self.appDelegate.account, key: self.layoutKey, serverUrl: self.serverUrl)
if self.layoutForView?.layout == NCGlobal.shared.layoutList {
if self.isLayoutList {
self.collectionView?.collectionViewLayout = self.listLayout
} else if self.layoutForView?.layout == NCGlobal.shared.layoutGrid {
} else if self.isLayoutGrid {
self.collectionView?.collectionViewLayout = self.gridLayout
} else if self.layoutForView?.layout == NCGlobal.shared.layoutPhotoSquare || self.layoutForView?.layout == NCGlobal.shared.layoutPhotoRatio {
} else if self.isLayoutPhoto {
self.collectionView?.collectionViewLayout = self.mediaLayout
}
self.titleCurrentFolder = self.getNavigationTitle()
self.setNavigationLeftItems()
self.dataSource.removeAll()
self.reloadDataSource()
self.reloadDataSourceNetwork()
self.getServerData()
}
}
}
override func viewWillAppear(_ animated: Bool) {
if isRoot {
serverUrl = utilityFileSystem.getHomeServer(urlBase: appDelegate.urlBase, userId: appDelegate.userId)
serverUrl = utilityFileSystem.getHomeServer(session: session)
titleCurrentFolder = getNavigationTitle()
}
super.viewWillAppear(animated)
if dataSource.metadatas.isEmpty {
reloadDataSource(withQueryDB: true)
reloadDataSource()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if !self.dataSource.isEmpty() {
self.blinkCell(fileName: self.fileNameBlink)
self.openFile(fileName: self.fileNameOpen)
self.fileNameBlink = nil
self.fileNameOpen = nil
}
if !isSearchingMode {
getServerData()
}
reloadDataSourceNetwork(withQueryDB: true)
}
override func viewDidDisappear(_ animated: Bool) {
@ -95,38 +117,36 @@ class NCFiles: NCCollectionViewCommon {
fileNameOpen = nil
}
// MARK: - DataSource + NC Endpoint
// MARK: - DataSource
override func queryDB() {
super.queryDB()
override func reloadDataSource() {
var predicate = self.defaultPredicate
let predicateDirectory = NSPredicate(format: "account == %@ AND serverUrl == %@", session.account, self.serverUrl)
let dataSourceMetadatas = self.dataSource.getMetadatas()
var metadatas: [tableMetadata] = []
if NCKeychain().getPersonalFilesOnly(account: self.appDelegate.account) {
metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (ownerId == %@ || ownerId == '') AND mountType == ''", self.appDelegate.account, self.serverUrl, self.appDelegate.userId))
} else {
metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
}
let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
if self.metadataFolder == nil {
self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId, serverUrl: self.serverUrl)
if NCKeychain().getPersonalFilesOnly(account: session.account) {
predicate = NSPredicate(format: "account == %@ AND serverUrl == %@ AND (ownerId == %@ || ownerId == '') AND mountType == '' AND NOT (status IN %@)", session.account, self.serverUrl, session.userId, global.metadataStatusHideInView)
}
self.richWorkspaceText = directory?.richWorkspace
self.dataSource = NCDataSource(metadatas: metadatas, account: self.appDelegate.account, layoutForView: layoutForView, providers: self.providers, searchResults: self.searchResults)
self.metadataFolder = database.getMetadataFolder(session: session, serverUrl: self.serverUrl)
self.richWorkspaceText = database.getTableDirectory(predicate: predicateDirectory)?.richWorkspace
let results = self.database.getResultsMetadatasPredicate(predicate, layoutForView: layoutForView)
self.dataSource = NCCollectionViewDataSource(results: results, layoutForView: layoutForView)
guard let results else {
return super.reloadDataSource()
}
let metadatas = Array(results.freeze())
override func reloadDataSource(withQueryDB: Bool = true) {
super.reloadDataSource(withQueryDB: withQueryDB)
if !self.dataSource.metadatas.isEmpty {
self.blinkCell(fileName: self.fileNameBlink)
self.openFile(fileName: self.fileNameOpen)
self.fileNameBlink = nil
self.fileNameOpen = nil
self.dataSource.caching(metadatas: metadatas, dataSourceMetadatas: dataSourceMetadatas) { updated in
if updated || self.isNumberOfItemsInAllSectionsNull || self.numberOfItemsInAllSections != metadatas.count {
super.reloadDataSource()
}
}
}
override func reloadDataSourceNetwork(withQueryDB: Bool = false) {
override func getServerData() {
if UIApplication.shared.applicationState == .background {
NextcloudKit.shared.nkCommonInstance.writeLog("[DEBUG] Files not reload datasource network with the application in background")
return
@ -136,103 +156,121 @@ class NCFiles: NCCollectionViewCommon {
}
func downloadMetadata(_ metadata: tableMetadata) -> Bool {
let fileSize = utilityFileSystem.fileProviderStorageSize(metadata.ocId, fileNameView: metadata.fileNameView)
guard fileSize > 0 else { return false }
if let localFile = NCManageDatabase.shared.getResultsTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))?.first {
if let localFile = database.getResultsTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId))?.first {
if localFile.etag != metadata.etag {
return true
}
}
return false
}
super.reloadDataSourceNetwork()
DispatchQueue.global().async {
self.networkReadFolder { metadatas, isChanged, error in
DispatchQueue.main.async {
self.refreshControl.endRefreshing()
if isChanged || self.isNumberOfItemsInAllSectionsNull {
self.reloadDataSource()
}
}
networkReadFolder { tableDirectory, metadatas, metadatasDifferentCount, metadatasModified, error in
DispatchQueue.global(qos: .userInteractive).async {
if error == .success {
for metadata in metadatas ?? [] where !metadata.directory && downloadMetadata(metadata) {
let metadatas: [tableMetadata] = metadatas ?? self.dataSource.getMetadatas()
for metadata in metadatas where !metadata.directory && downloadMetadata(metadata) {
if NCNetworking.shared.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty {
NCNetworking.shared.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile))
}
}
self.richWorkspaceText = tableDirectory?.richWorkspace
if metadatasDifferentCount != 0 || metadatasModified != 0 {
self.reloadDataSource()
} else {
self.reloadDataSource(withQueryDB: withQueryDB)
}
} else {
self.reloadDataSource(withQueryDB: withQueryDB)
}
}
}
}
private func networkReadFolder(completion: @escaping(_ tableDirectory: tableDirectory?, _ metadatas: [tableMetadata]?, _ metadatasDifferentCount: Int, _ metadatasModified: Int, _ error: NKError) -> Void) {
var tableDirectory: tableDirectory?
NCNetworking.shared.readFile(serverUrlFileName: serverUrl, account: appDelegate.account) { task in
private func networkReadFolder(completion: @escaping (_ metadatas: [tableMetadata]?, _ isDataChanged: Bool, _ error: NKError) -> Void) {
NCNetworking.shared.readFile(serverUrlFileName: serverUrl, account: session.account) { task in
self.dataSourceTask = task
if self.dataSource.isEmpty() {
self.collectionView.reloadData()
}
} completion: { account, metadata, error in
let isDirectoryE2EE = NCUtilityFileSystem().isDirectoryE2EE(session: self.session, serverUrl: self.serverUrl)
guard error == .success, let metadata else {
return completion(nil, nil, 0, 0, error)
return completion(nil, false, error)
}
/// Check change eTag or E2EE or DataSource empty
let tableDirectory = self.database.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadata.richWorkspace, account: account)
guard tableDirectory?.etag != metadata.etag || metadata.e2eEncrypted || self.dataSource.isEmpty() else {
return completion(nil, false, NKError())
}
/// Check Response DataC hanged
var checkResponseDataChanged = true
if tableDirectory?.etag.isEmpty ?? true || isDirectoryE2EE {
checkResponseDataChanged = false
}
tableDirectory = NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadata.richWorkspace, account: account)
// swiftlint:disable empty_string
let forceReplaceMetadatas = tableDirectory?.etag == ""
// swiftlint:enable empty_string
if tableDirectory?.etag != metadata.etag || metadata.e2eEncrypted {
NCNetworking.shared.readFolder(serverUrl: self.serverUrl,
account: self.appDelegate.account,
forceReplaceMetadatas: forceReplaceMetadatas) { task in
account: metadata.account,
checkResponseDataChanged: checkResponseDataChanged,
queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue) { task in
self.dataSourceTask = task
if self.dataSource.isEmpty() {
self.collectionView.reloadData()
} completion: { account, metadataFolder, metadatas, metadatasDifferentCount, metadatasModified, error in
guard account == self.appDelegate.account, error == .success else {
return completion(tableDirectory, nil, 0, 0, error)
}
} completion: { account, metadataFolder, metadatas, isDataChanged, error in
/// Error
guard error == .success else {
return completion(nil, false, error)
}
/// Updata folder
if let metadataFolder {
self.metadataFolder = metadataFolder
// E2EE
if let metadataFolder = metadataFolder,
metadataFolder.e2eEncrypted,
self.richWorkspaceText = metadataFolder.richWorkspace
}
/// check Response Data Changed
if !isDataChanged {
return completion(nil, false, error)
}
guard let metadataFolder,
isDirectoryE2EE,
NCKeychain().isEndToEndEnabled(account: account),
!NCNetworkingE2EE().isInUpload(account: account, serverUrl: self.serverUrl) {
let lock = NCManageDatabase.shared.getE2ETokenLock(account: account, serverUrl: self.serverUrl)
!NCNetworkingE2EE().isInUpload(account: account, serverUrl: self.serverUrl) else {
return completion(metadatas, true, error)
}
/// E2EE
let lock = self.database.getE2ETokenLock(account: account, serverUrl: self.serverUrl)
NCNetworkingE2EE().getMetadata(fileId: metadataFolder.ocId, e2eToken: lock?.e2eToken, account: account) { account, version, e2eMetadata, signature, _, error in
if account == self.appDelegate.account, error == .success, let e2eMetadata = e2eMetadata {
let error = NCEndToEndMetadata().decodeMetadata(e2eMetadata, signature: signature, serverUrl: self.serverUrl, account: account, urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId)
if error == .success, let e2eMetadata = e2eMetadata {
let error = NCEndToEndMetadata().decodeMetadata(e2eMetadata, signature: signature, serverUrl: self.serverUrl, session: self.session)
if error == .success {
if version == "v1", NCGlobal.shared.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20 {
if version == "v1", NCCapabilities.shared.getCapabilities(account: account).capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20 {
NextcloudKit.shared.nkCommonInstance.writeLog("[E2EE] Conversion v1 to v2")
NCActivityIndicator.shared.start()
Task {
let serverUrl = metadataFolder.serverUrl + "/" + metadataFolder.fileName
let error = await NCNetworkingE2EE().uploadMetadata(account: metadataFolder.account, serverUrl: serverUrl, userId: metadataFolder.userId, updateVersionV1V2: true)
let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, updateVersionV1V2: true, account: account)
if error != .success {
NCContentPresenter().showError(error: error)
}
NCActivityIndicator.shared.stop()
self.reloadDataSource()
}
} else {
self.reloadDataSource()
}
} else {
// Client Diagnostic
NCManageDatabase.shared.addDiagnostic(account: account, issue: NCGlobal.shared.diagnosticIssueE2eeErrors)
self.database.addDiagnostic(account: account, issue: NCGlobal.shared.diagnosticIssueE2eeErrors)
NCContentPresenter().showError(error: error)
}
} else if error.errorCode == NCGlobal.shared.errorResourceNotFound {
// no metadata found, send a new metadata
Task {
let serverUrl = metadataFolder.serverUrl + "/" + metadataFolder.fileName
let error = await NCNetworkingE2EE().uploadMetadata(account: metadataFolder.account, serverUrl: serverUrl, userId: metadataFolder.userId)
let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, account: account)
if error != .success {
NCContentPresenter().showError(error: error)
}
@ -240,21 +278,15 @@ class NCFiles: NCCollectionViewCommon {
} else {
NCContentPresenter().showError(error: NKError(errorCode: NCGlobal.shared.errorE2EEKeyDecodeMetadata, errorDescription: "_e2e_error_"))
}
completion(tableDirectory, metadatas, metadatasDifferentCount, metadatasModified, error)
completion(metadatas, true, error)
}
} else {
completion(tableDirectory, metadatas, metadatasDifferentCount, metadatasModified, error)
}
}
} else {
completion(tableDirectory, nil, 0, 0, NKError())
}
}
}
func blinkCell(fileName: String?) {
if let fileName = fileName, let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, self.serverUrl, fileName)) {
let (indexPath, _) = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId)
if let fileName = fileName, let metadata = database.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", session.account, self.serverUrl, fileName)) {
let indexPath = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId)
if let indexPath = indexPath {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
UIView.animate(withDuration: 0.3) {
@ -273,8 +305,8 @@ class NCFiles: NCCollectionViewCommon {
}
func openFile(fileName: String?) {
if let fileName = fileName, let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", self.appDelegate.account, self.serverUrl, fileName)) {
let (indexPath, _) = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId)
if let fileName = fileName, let metadata = database.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileName == %@", session.account, self.serverUrl, fileName)) {
let indexPath = self.dataSource.getIndexPathMetadata(ocId: metadata.ocId)
if let indexPath = indexPath {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.collectionView(self.collectionView, didSelectItemAt: indexPath)
@ -285,11 +317,12 @@ class NCFiles: NCCollectionViewCommon {
// MARK: - NCAccountSettingsModelDelegate
override func accountSettingsDidDismiss(tableAccount: tableAccount?) {
if NCManageDatabase.shared.getAllAccount().isEmpty {
appDelegate.openLogin(selector: NCGlobal.shared.introLogin, openLoginWeb: false)
} else if let account = tableAccount?.account, account != appDelegate.account {
appDelegate.changeAccount(account, userProfile: nil) { }
override func accountSettingsDidDismiss(tableAccount: tableAccount?, controller: NCMainTabBarController?) {
let currentAccount = session.account
if database.getAllTableAccount().isEmpty {
appDelegate.openLogin(selector: NCGlobal.shared.introLogin)
} else if let account = tableAccount?.account, account != currentAccount {
NCAccount().changeAccount(account, userProfile: nil, controller: controller) { }
} else if isRoot {
titleCurrentFolder = getNavigationTitle()
navigationItem.title = titleCurrentFolder

Просмотреть файл

@ -24,7 +24,6 @@
import SwiftUI
struct TextFieldClearButton: ViewModifier {
@Binding var text: String
func body(content: Content) -> some View {
@ -44,15 +43,15 @@ struct TextFieldClearButton: ViewModifier {
}
struct ButtonRounded: ButtonStyle {
var disabled = false
var account = ""
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(.horizontal, 40)
.padding(.vertical, 10)
.background(disabled ? Color(UIColor.placeholderText) : Color(NCBrandColor.shared.brandElement))
.foregroundColor(disabled ? Color(UIColor.placeholderText) : Color(NCBrandColor.shared.brandText))
.background(disabled ? Color(UIColor.placeholderText) : Color(NCBrandColor.shared.getElement(account: account)))
.foregroundColor(disabled ? Color(UIColor.placeholderText) : Color(NCBrandColor.shared.getText(account: account)))
.clipShape(Capsule())
.opacity(configuration.isPressed ? 0.5 : 1.0)
}

Просмотреть файл

@ -23,11 +23,11 @@
import SwiftUI
struct HUDView: View {
struct NCHUDView: View {
@Binding var showHUD: Bool
@State var textLabel: String
@State var image: String
@State var color: UIColor
var body: some View {
Button(action: {
@ -40,7 +40,7 @@ struct HUDView: View {
.padding(.horizontal, 10)
.padding(14)
.background(
Blur(style: .regular)
Blur(style: .regular, color: color)
.clipShape(Capsule())
.shadow(color: Color(.black).opacity(0.22), radius: 12, x: 0, y: 5)
)
@ -49,12 +49,12 @@ struct HUDView: View {
}
struct Blur: UIViewRepresentable {
var style: UIBlurEffect.Style
var color: UIColor
func makeUIView(context: Context) -> UIVisualEffectView {
let effectView = UIVisualEffectView(effect: UIBlurEffect(style: style))
effectView.backgroundColor = NCBrandColor.shared.brandElement
effectView.backgroundColor = color
return effectView
}
@ -64,8 +64,8 @@ struct Blur: UIViewRepresentable {
}
struct ContentView: View {
@State private var showHUD = false
@State var color: UIColor
@Namespace var hudAnimation
func dismissHUDAfterTime() {
@ -83,14 +83,10 @@ struct ContentView: View {
}
.navigationTitle("Content View")
}
HUDView(showHUD: $showHUD, textLabel: NSLocalizedString("_wait_", comment: ""), image: "doc.badge.arrow.up")
NCHUDView(showHUD: $showHUD, textLabel: NSLocalizedString("_wait_", comment: ""), image: "doc.badge.arrow.up", color: color)
.offset(y: showHUD ? (geo.size.height / 2) : -200)
.animation(.easeOut, value: showHUD)
}
}
}
}
#Preview {
ContentView()
}

131
iOSClient/GUI/NCHud.swift Normal file
Просмотреть файл

@ -0,0 +1,131 @@
//
// NCHud.swift
// Nextcloud
//
// Created by Marino Faggiana on 04/09/24.
// Copyright © 2024 Marino Faggiana. All rights reserved.
//
import Foundation
import UIKit
import JGProgressHUD
class NCHud: NSObject {
private let hud = JGProgressHUD()
private var view: UIView?
public init(_ view: UIView? = nil) {
if let view {
self.view = view
}
super.init()
}
func initHud(view: UIView? = nil, text: String? = nil, detailText: String? = nil) {
DispatchQueue.main.async {
if let view {
self.view = view
}
self.hud.indicatorView = JGProgressHUDIndicatorView()
self.hud.textLabel.text = text
self.hud.textLabel.textColor = NCBrandColor.shared.iconImageColor
self.hud.detailTextLabel.text = detailText
self.hud.detailTextLabel.textColor = NCBrandColor.shared.iconImageColor2
if let view = self.view {
self.hud.show(in: view)
}
}
}
func initHudRing(view: UIView? = nil, text: String? = nil, detailText: String? = nil, tapToCancelDetailText: Bool = false, tapOperation: (() -> Void)? = nil) {
DispatchQueue.main.async {
self.hud.tapOnHUDViewBlock = { hud in
if let tapOperation {
tapOperation()
hud.dismiss()
}
}
if let view {
self.view = view
}
self.hud.indicatorView = JGProgressHUDRingIndicatorView()
self.hud.progress = 0.0
let indicatorView = self.hud.indicatorView as? JGProgressHUDRingIndicatorView
indicatorView?.ringWidth = 1.5
indicatorView?.ringColor = NCBrandColor.shared.iconImageColor
self.hud.textLabel.text = text
self.hud.textLabel.textColor = NCBrandColor.shared.iconImageColor
if tapToCancelDetailText {
self.hud.detailTextLabel.text = NSLocalizedString("_tap_to_cancel_", comment: "")
} else {
self.hud.detailTextLabel.text = detailText
}
self.hud.detailTextLabel.textColor = NCBrandColor.shared.iconImageColor2
if let view = self.view {
self.hud.show(in: view)
}
}
}
func dismiss() {
DispatchQueue.main.async {
self.hud.dismiss()
}
}
func show() {
DispatchQueue.main.async {
if let view = self.view {
self.hud.show(in: view)
}
}
}
func progress(num: Float, total: Float) {
DispatchQueue.main.async {
self.hud.progress = num / total
}
}
func progress(_ progress: Double) {
DispatchQueue.main.async {
self.hud.progress = Float(progress)
}
}
func success() {
DispatchQueue.main.async {
self.hud.indicatorView = JGProgressHUDSuccessIndicatorView()
self.hud.indicatorView?.tintColor = .green
self.hud.textLabel.text = NSLocalizedString("_success_", comment: "")
self.hud.detailTextLabel.text = nil
self.hud.dismiss(afterDelay: 1.0)
}
}
func error(text: String?) {
DispatchQueue.main.async {
self.hud.indicatorView = JGProgressHUDErrorIndicatorView()
self.hud.indicatorView?.tintColor = .red
self.hud.textLabel.text = text
self.hud.dismiss(afterDelay: 2.0)
}
}
func setText(text: String?, detailText: String? = nil) {
DispatchQueue.main.async {
self.hud.textLabel.text = text
self.hud.detailTextLabel.text = detailText
}
}
}

Просмотреть файл

@ -23,6 +23,7 @@
import UIKit
import NextcloudKit
import RealmSwift
class NCGroupfolders: NCCollectionViewCommon {
@ -33,7 +34,7 @@ class NCGroupfolders: NCCollectionViewCommon {
layoutKey = NCGlobal.shared.layoutViewGroupfolders
enableSearchBar = false
headerRichWorkspaceDisable = true
emptyImage = utility.loadImage(named: "folder_group", colors: [NCBrandColor.shared.brandElement])
emptyImageName = "folder_group"
emptyTitle = "_files_no_files_"
emptyDescription = "_tutorial_groupfolders_view_"
}
@ -43,58 +44,59 @@ class NCGroupfolders: NCCollectionViewCommon {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if dataSource.metadatas.isEmpty {
reloadDataSource()
}
reloadDataSourceNetwork()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
getServerData()
}
// MARK: - DataSource + NC Endpoint
// MARK: - DataSource
override func queryDB() {
super.queryDB()
var metadatas: [tableMetadata] = []
override func reloadDataSource() {
var results: Results<tableMetadata>?
if self.serverUrl.isEmpty {
metadatas = NCManageDatabase.shared.getMetadatasFromGroupfolders(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId)
results = database.getResultsMetadatasFromGroupfolders(session: session)
} else {
metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl))
results = self.database.getResultsMetadatasPredicate(self.defaultPredicate, layoutForView: layoutForView)
}
self.dataSource = NCDataSource(metadatas: metadatas, account: self.appDelegate.account, layoutForView: layoutForView, providers: self.providers, searchResults: self.searchResults)
self.dataSource = NCCollectionViewDataSource(results: results, layoutForView: layoutForView)
super.reloadDataSource()
}
override func reloadDataSourceNetwork(withQueryDB: Bool = false) {
super.reloadDataSourceNetwork()
override func getServerData() {
let homeServerUrl = utilityFileSystem.getHomeServer(session: session)
let homeServerUrl = utilityFileSystem.getHomeServer(urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId)
NextcloudKit.shared.getGroupfolders(account: self.appDelegate.account, options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { task in
NextcloudKit.shared.getGroupfolders(account: session.account) { task in
self.dataSourceTask = task
if self.dataSource.isEmpty() {
self.collectionView.reloadData()
}
} completion: { account, results, _, error in
if error == .success, let groupfolders = results {
NCManageDatabase.shared.addGroupfolders(account: account, groupfolders: groupfolders)
self.database.addGroupfolders(account: account, groupfolders: groupfolders)
Task {
for groupfolder in groupfolders {
let mountPoint = groupfolder.mountPoint.hasPrefix("/") ? groupfolder.mountPoint : "/" + groupfolder.mountPoint
let serverUrlFileName = homeServerUrl + mountPoint
if NCManageDatabase.shared.getMetadataFromDirectory(account: self.appDelegate.account, serverUrl: serverUrlFileName) == nil {
let results = await NCNetworking.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0", showHiddenFiles: NCKeychain().showHiddenFiles, account: account)
if results.error == .success, let file = results.files.first {
if results.error == .success, let file = results.files?.first {
let isDirectoryE2EE = self.utilityFileSystem.isDirectoryE2EE(file: file)
let metadata = NCManageDatabase.shared.convertFileToMetadata(file, isDirectoryE2EE: isDirectoryE2EE)
NCManageDatabase.shared.addMetadata(metadata)
NCManageDatabase.shared.addDirectory(e2eEncrypted: isDirectoryE2EE, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, permissions: metadata.permissions, serverUrl: serverUrlFileName, account: metadata.account)
}
let metadata = self.database.convertFileToMetadata(file, isDirectoryE2EE: isDirectoryE2EE)
self.database.addMetadata(metadata)
self.database.addDirectory(e2eEncrypted: isDirectoryE2EE, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, permissions: metadata.permissions, serverUrl: serverUrlFileName, account: metadata.account)
}
}
self.reloadDataSource()
}
} else {
self.reloadDataSource(withQueryDB: withQueryDB)
}
}
self.refreshControl.endRefreshing()
}
}
}

Просмотреть файл

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23094" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_9" orientation="portrait" appearance="dark"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23084"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -13,18 +15,18 @@
<objects>
<viewController storyboardIdentifier="NCLogin" id="yj9-jo-WIn" customClass="NCLogin" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Bv6-g3-l0M">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<rect key="frame" x="0.0" y="0.0" width="440" height="956"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="BpI-xK-1SU">
<rect key="frame" x="87" y="226.5" width="240" height="120"/>
<rect key="frame" x="100" y="241.66666666666663" width="240" height="120"/>
<constraints>
<constraint firstAttribute="height" constant="120" id="E9d-5O-bto"/>
<constraint firstAttribute="width" constant="240" id="xwH-mh-yDU"/>
</constraints>
</imageView>
<textField opaque="NO" clipsSubviews="YES" tag="1" contentMode="scaleToFill" layoutMarginsFollowReadableWidth="YES" insetsLayoutMarginsFromSafeArea="NO" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder=" Server address https://…" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="szn-G7-5sK">
<rect key="frame" x="50" y="376.5" width="314" height="44"/>
<rect key="frame" x="50" y="391.66666666666669" width="340" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="I2v-Zr-IWf"/>
</constraints>
@ -33,7 +35,7 @@
<textInputTraits key="textInputTraits" autocorrectionType="no" keyboardType="URL" returnKeyType="done"/>
</textField>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HQd-pF-3cE">
<rect key="frame" x="324" y="378.5" width="40" height="40"/>
<rect key="frame" x="350" y="393.66666666666669" width="40" height="40"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="3yh-bo-Bzr"/>
@ -42,36 +44,35 @@
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<imageReference key="image" image="arrow.right" catalog="system" symbolScale="large"/>
</state>
<connections>
<action selector="actionButtonLogin:" destination="yj9-jo-WIn" eventType="touchUpInside" id="vFP-SJ-rFq"/>
</connections>
</button>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Al0-LA-Ndt">
<rect key="frame" x="334" y="388.5" width="20" height="20"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="IQA-ga-jx5"/>
<constraint firstAttribute="width" constant="20" id="hVA-N5-u88"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="The link to your Nextcloud web interface when you open it in the browser." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PJH-5i-Tkf">
<rect key="frame" x="60" y="438.5" width="294" height="29"/>
<rect key="frame" x="60" y="453.66666666666669" width="320" height="28.666666666666686"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6tp-bh-Z9k" userLabel="QRCode">
<rect key="frame" x="182" y="567.5" width="50" height="50"/>
<button contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6tp-bh-Z9k" userLabel="QRCode">
<rect key="frame" x="192.66666666666663" y="582.33333333333337" width="55.000000000000028" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="3hb-Ez-hOz"/>
<constraint firstAttribute="width" constant="55" id="3hb-Ez-hOz"/>
<constraint firstAttribute="height" constant="50" id="OLT-tb-4Qb"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<state key="normal">
<imageReference key="image" image="qrcode.viewfinder" catalog="system" symbolScale="default"/>
<preferredSymbolConfiguration key="preferredSymbolConfiguration" configurationType="pointSize" pointSize="50" scale="large"/>
</state>
<connections>
<action selector="actionQRCode:" destination="yj9-jo-WIn" eventType="touchUpInside" id="qwL-rG-ead"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5lM-dt-8fM">
<rect key="frame" x="182" y="667.5" width="50" height="50"/>
<rect key="frame" x="195" y="682.33333333333337" width="50" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="0RD-Gi-CTv"/>
<constraint firstAttribute="width" constant="50" id="NuK-Yo-LoT"/>
@ -80,9 +81,29 @@
<action selector="actionCertificate:" destination="yj9-jo-WIn" eventType="touchUpInside" id="Ibx-wC-iEY"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IXM-eK-wKA" userLabel="Choose Server">
<rect key="frame" x="50" y="391.66666666666669" width="290" height="44"/>
<color key="backgroundColor" white="1" alpha="0.40478847789115646" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="k9B-my-RAo"/>
</constraints>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="contentEdgeInsets" minX="0.0" minY="0.0" maxX="35" maxY="0.0"/>
<inset key="titleEdgeInsets" minX="10" minY="0.0" maxX="0.0" maxY="0.0"/>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="Name 1"/>
</button>
<imageView hidden="YES" opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="arrowtriangle.down.circle" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="rza-UC-nsA">
<rect key="frame" x="310" y="403.66666666666669" width="20" height="19.666666666666686"/>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="20" id="Y46-VP-7nh"/>
<constraint firstAttribute="height" constant="21" id="boa-1i-a6E"/>
</constraints>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="8lf-3Y-f5R"/>
<color key="backgroundColor" white="0.9023259132753424" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" systemColor="tintColor"/>
<constraints>
<constraint firstItem="8lf-3Y-f5R" firstAttribute="trailing" secondItem="szn-G7-5sK" secondAttribute="trailing" constant="50" id="24L-p4-zOF"/>
<constraint firstItem="PJH-5i-Tkf" firstAttribute="leading" secondItem="8lf-3Y-f5R" secondAttribute="leading" constant="60" id="3aW-cF-rdF"/>
@ -90,27 +111,33 @@
<constraint firstItem="6tp-bh-Z9k" firstAttribute="centerX" secondItem="8lf-3Y-f5R" secondAttribute="centerX" id="Apc-1U-CwU"/>
<constraint firstItem="BpI-xK-1SU" firstAttribute="top" secondItem="Bv6-g3-l0M" secondAttribute="centerY" multiplier="0.5" constant="2.5" id="Gkg-up-7eW"/>
<constraint firstItem="8lf-3Y-f5R" firstAttribute="centerX" secondItem="BpI-xK-1SU" secondAttribute="centerX" id="IxG-UI-0vq"/>
<constraint firstItem="rza-UC-nsA" firstAttribute="top" secondItem="BpI-xK-1SU" secondAttribute="bottom" constant="41.5" id="MS5-cH-8Ea"/>
<constraint firstItem="6tp-bh-Z9k" firstAttribute="top" secondItem="PJH-5i-Tkf" secondAttribute="bottom" constant="100" id="MZQ-GT-XSM"/>
<constraint firstItem="IXM-eK-wKA" firstAttribute="leading" secondItem="8lf-3Y-f5R" secondAttribute="leading" constant="50" id="SE6-52-VoG"/>
<constraint firstItem="PJH-5i-Tkf" firstAttribute="top" secondItem="szn-G7-5sK" secondAttribute="bottom" constant="18" id="Vfj-lG-7wT"/>
<constraint firstItem="Al0-LA-Ndt" firstAttribute="centerX" secondItem="HQd-pF-3cE" secondAttribute="centerX" id="Yll-3L-vuj"/>
<constraint firstItem="HQd-pF-3cE" firstAttribute="centerY" secondItem="szn-G7-5sK" secondAttribute="centerY" id="cG8-kL-pdu"/>
<constraint firstItem="Al0-LA-Ndt" firstAttribute="centerY" secondItem="HQd-pF-3cE" secondAttribute="centerY" id="eOF-06-PmZ"/>
<constraint firstItem="5lM-dt-8fM" firstAttribute="top" secondItem="6tp-bh-Z9k" secondAttribute="bottom" constant="50" id="i5K-Jt-epF"/>
<constraint firstItem="szn-G7-5sK" firstAttribute="top" secondItem="BpI-xK-1SU" secondAttribute="bottom" constant="30" id="lWz-Yy-NCO"/>
<constraint firstItem="5lM-dt-8fM" firstAttribute="centerX" secondItem="8lf-3Y-f5R" secondAttribute="centerX" id="mKe-Nn-9dd"/>
<constraint firstItem="HQd-pF-3cE" firstAttribute="leading" secondItem="IXM-eK-wKA" secondAttribute="trailing" constant="30" id="p5X-FY-AQg">
<variation key="widthClass=compact" constant="10"/>
</constraint>
<constraint firstItem="IXM-eK-wKA" firstAttribute="top" secondItem="BpI-xK-1SU" secondAttribute="bottom" constant="30" id="sBQ-Q7-GKc"/>
<constraint firstItem="szn-G7-5sK" firstAttribute="leading" secondItem="8lf-3Y-f5R" secondAttribute="leading" constant="50" id="uQw-dy-Ga4"/>
<constraint firstItem="IXM-eK-wKA" firstAttribute="trailing" secondItem="rza-UC-nsA" secondAttribute="trailing" constant="10" id="zD5-gc-sHh"/>
<constraint firstItem="8lf-3Y-f5R" firstAttribute="trailing" secondItem="PJH-5i-Tkf" secondAttribute="trailing" constant="60" id="zzV-UD-gRV"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="6v9-Gy-jiv"/>
<connections>
<outlet property="baseUrl" destination="szn-G7-5sK" id="rpO-mh-09O"/>
<outlet property="baseUrlTextField" destination="szn-G7-5sK" id="rpO-mh-09O"/>
<outlet property="certificate" destination="5lM-dt-8fM" id="vw6-cH-njm"/>
<outlet property="enforceServersButton" destination="IXM-eK-wKA" id="Ezu-3y-iDa"/>
<outlet property="enforceServersDropdownImage" destination="rza-UC-nsA" id="eWk-Ww-vJM"/>
<outlet property="imageBrand" destination="BpI-xK-1SU" id="0tB-69-RNs"/>
<outlet property="imageBrandConstraintY" destination="Gkg-up-7eW" id="RKw-pM-dZr"/>
<outlet property="loginAddressDetail" destination="PJH-5i-Tkf" id="wBQ-5P-HD4"/>
<outlet property="loginButton" destination="HQd-pF-3cE" id="XOc-dS-QZ8"/>
<outlet property="loginImage" destination="Al0-LA-Ndt" id="dT5-vu-5eD"/>
<outlet property="qrCode" destination="6tp-bh-Z9k" id="Tw3-op-BgR"/>
</connections>
</viewController>
@ -123,7 +150,7 @@
<objects>
<viewController storyboardIdentifier="NCLoginProvider" id="yEb-Ky-35s" customClass="NCLoginProvider" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="UX5-cJ-bY6">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<rect key="frame" x="0.0" y="0.0" width="440" height="956"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="vqz-4v-cZu"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@ -134,4 +161,12 @@
<point key="canvasLocation" x="5421.739130434783" y="-1210.0446428571429"/>
</scene>
</scenes>
<resources>
<image name="arrow.right" catalog="system" width="128" height="95"/>
<image name="arrowtriangle.down.circle" catalog="system" width="128" height="123"/>
<image name="qrcode.viewfinder" catalog="system" width="128" height="115"/>
<systemColor name="tintColor">
<color red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>

Просмотреть файл

@ -30,12 +30,13 @@ import SwiftUI
class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
@IBOutlet weak var imageBrand: UIImageView!
@IBOutlet weak var imageBrandConstraintY: NSLayoutConstraint!
@IBOutlet weak var baseUrl: UITextField!
@IBOutlet weak var baseUrlTextField: UITextField!
@IBOutlet weak var loginAddressDetail: UILabel!
@IBOutlet weak var loginButton: UIButton!
@IBOutlet weak var loginImage: UIImageView!
@IBOutlet weak var qrCode: UIButton!
@IBOutlet weak var certificate: UIButton!
@IBOutlet weak var enforceServersButton: UIButton!
@IBOutlet weak var enforceServersDropdownImage: UIImageView!
private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
private var textColor: UIColor = .white
@ -82,37 +83,31 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
imageBrand.image = UIImage(named: "logo")
// Url
baseUrl.textColor = textColor
baseUrl.tintColor = textColor
baseUrl.layer.cornerRadius = 10
baseUrl.layer.borderWidth = 1
baseUrl.layer.borderColor = textColor.cgColor
baseUrl.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: baseUrl.frame.height))
baseUrl.leftViewMode = .always
baseUrl.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 35, height: baseUrl.frame.height))
baseUrl.rightViewMode = .always
baseUrl.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("_login_url_", comment: ""), attributes: [NSAttributedString.Key.foregroundColor: textColor.withAlphaComponent(0.5)])
baseUrl.delegate = self
baseUrlTextField.textColor = textColor
baseUrlTextField.tintColor = textColor
baseUrlTextField.layer.cornerRadius = 10
baseUrlTextField.layer.borderWidth = 1
baseUrlTextField.layer.borderColor = textColor.cgColor
baseUrlTextField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: baseUrlTextField.frame.height))
baseUrlTextField.leftViewMode = .always
baseUrlTextField.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 35, height: baseUrlTextField.frame.height))
baseUrlTextField.rightViewMode = .always
baseUrlTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("_login_url_", comment: ""), attributes: [NSAttributedString.Key.foregroundColor: textColor.withAlphaComponent(0.5)])
baseUrlTextField.delegate = self
baseUrl.isEnabled = !NCBrandOptions.shared.disable_request_login_url
baseUrlTextField.isEnabled = !NCBrandOptions.shared.disable_request_login_url
// Login button
loginAddressDetail.textColor = textColor
loginAddressDetail.text = String.localizedStringWithFormat(NSLocalizedString("_login_address_detail_", comment: ""), NCBrandOptions.shared.brand)
// Login Image
loginImage.image = UIImage(named: "arrow.right")?.image(color: textColor, size: 100)
// brand
if NCBrandOptions.shared.disable_request_login_url {
baseUrl.isEnabled = false
baseUrl.isUserInteractionEnabled = false
baseUrl.alpha = 0.5
baseUrlTextField.isEnabled = false
baseUrlTextField.isUserInteractionEnabled = false
baseUrlTextField.alpha = 0.5
}
// qrcode
qrCode.setImage(UIImage(systemName: "qrcode.viewfinder")?.image(color: textColor, size: 100), for: .normal)
// certificate
certificate.setImage(UIImage(named: "certificate")?.image(color: textColor, size: 100), for: .normal)
certificate.isHidden = true
@ -129,7 +124,7 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
self.navigationController?.view.backgroundColor = NCBrandColor.shared.customer
self.navigationController?.navigationBar.tintColor = textColor
if !NCManageDatabase.shared.getAllAccount().isEmpty {
if !NCManageDatabase.shared.getAllTableAccount().isEmpty {
let navigationItemCancel = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(self.actionCancel))
navigationItemCancel.tintColor = textColor
navigationItem.leftBarButtonItem = navigationItemCancel
@ -137,14 +132,14 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
if let dirGroupApps = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.shared.capabilitiesGroupApps) {
// Nextcloud update share accounts
if let error = appDelegate.updateShareAccounts() {
if let error = NCAccount().updateAppsShareAccounts() {
NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Create share accounts \(error.localizedDescription)")
}
// Nextcloud get share accounts
if let shareAccounts = NKShareAccounts().getShareAccount(at: dirGroupApps, application: UIApplication.shared) {
var accountTemp = [NKShareAccounts.DataAccounts]()
for shareAccount in shareAccounts {
if NCManageDatabase.shared.getAccount(predicate: NSPredicate(format: "urlBase == %@ AND user == %@", shareAccount.url, shareAccount.user)) == nil {
if NCManageDatabase.shared.getTableAccount(predicate: NSPredicate(format: "urlBase == %@ AND user == %@", shareAccount.url, shareAccount.user)) == nil {
accountTemp.append(shareAccount)
}
}
@ -165,14 +160,40 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
handleLoginWithAppConfig()
baseUrl.text = urlBase
baseUrlTextField.text = urlBase
enforceServersButton.setTitle(NSLocalizedString("_select_server_", comment: ""), for: .normal)
let enforceServers = NCBrandOptions.shared.enforce_servers
if !enforceServers.isEmpty {
baseUrlTextField.isHidden = true
enforceServersDropdownImage.isHidden = false
enforceServersButton.isHidden = false
let actions = enforceServers.map { server in
UIAction(title: server.name, handler: { [self] _ in
enforceServersButton.setTitle(server.name, for: .normal)
baseUrlTextField.text = server.url
})
}
enforceServersButton.layer.cornerRadius = 10
enforceServersButton.menu = .init(title: NSLocalizedString("_servers_", comment: ""), children: actions)
enforceServersButton.showsMenuAsPrimaryAction = true
enforceServersButton.configuration?.titleTextAttributesTransformer =
UIConfigurationTextAttributesTransformer { incoming in
var outgoing = incoming
outgoing.font = UIFont.systemFont(ofSize: 13)
return outgoing
}
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
appDelegate.timerErrorNetworkingDisabled = true
if self.shareAccounts != nil, let image = UIImage(systemName: "person.badge.plus")?.withTintColor(.white, renderingMode: .alwaysOriginal), let backgroundColor = NCBrandColor.shared.brandElement.lighter(by: 10) {
if self.shareAccounts != nil, let image = UIImage(systemName: "person.badge.plus")?.withTintColor(.white, renderingMode: .alwaysOriginal), let backgroundColor = NCBrandColor.shared.customer.lighter(by: 10) {
let title = String(format: NSLocalizedString("_apps_nextcloud_detect_", comment: ""), NCBrandOptions.shared.brand)
let description = String(format: NSLocalizedString("_add_existing_account_", comment: ""), NCBrandOptions.shared.brand)
NCContentPresenter().alertAction(image: image, contentModeImage: .scaleAspectFit, sizeImage: CGSize(width: 45, height: 45), backgroundColor: backgroundColor, textColor: textColor, title: title, description: description, textCancelButton: "_cancel_", textOkButton: "_ok_", attributes: EKAttributes.topFloat) { identifier in
@ -183,11 +204,6 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
appDelegate.timerErrorNetworkingDisabled = false
}
private func handleLoginWithAppConfig() {
let accountCount = NCManageDatabase.shared.getAccounts()?.count ?? 0
@ -297,20 +313,20 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
// MARK: - Login
private func login() {
guard var url = baseUrl.text?.trimmingCharacters(in: .whitespacesAndNewlines) else { return }
guard var url = baseUrlTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) else { return }
if url.hasSuffix("/") { url = String(url.dropLast()) }
if url.isEmpty { return }
// Check whether baseUrl contain protocol. If not add https:// by default.
if url.hasPrefix("https") == false && url.hasPrefix("http") == false {
url = "https://" + url
}
self.baseUrl.text = url
self.baseUrlTextField.text = url
isUrlValid(url: url)
}
func isUrlValid(url: String, user: String? = nil) {
loginButton.isEnabled = false
NextcloudKit.shared.getServerStatus(serverUrl: url) { serverInfoResult in
NextcloudKit.shared.getServerStatus(serverUrl: url) { _, serverInfoResult in
switch serverInfoResult {
case .success(let serverInfo):
if let host = URL(string: url)?.host {
@ -369,9 +385,9 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
let user = valueArray[0].replacingOccurrences(of: "user:", with: "")
let password = valueArray[1].replacingOccurrences(of: "password:", with: "")
let urlBase = valueArray[2].replacingOccurrences(of: "server:", with: "")
let serverUrl = urlBase + "/" + NextcloudKit.shared.nkCommonInstance.dav
let serverUrl = urlBase + "/remote.php/dav"
loginButton.isEnabled = false
NextcloudKit.shared.checkServer(serverUrl: serverUrl) { error in
NextcloudKit.shared.checkServer(serverUrl: serverUrl) { _, error in
self.loginButton.isEnabled = true
if error == .success {
self.createAccount(urlBase: urlBase, user: user, password: password)
@ -397,16 +413,19 @@ class NCLogin: UIViewController, UITextFieldDelegate, NCLoginQRCodeDelegate {
}
private func createAccount(urlBase: String, user: String, password: String) {
let controller = UIApplication.shared.firstWindow?.rootViewController as? NCMainTabBarController
if let host = URL(string: urlBase)?.host {
NCNetworking.shared.writeCertificate(host: host)
}
self.appDelegate.createAccount(urlBase: urlBase, user: user, password: password) { error in
NCAccount().createAccount(urlBase: urlBase, user: user, password: password, controller: controller) { account, error in
if error == .success {
let window = UIApplication.shared.firstWindow
if window?.rootViewController is NCMainTabBarController {
if let controller = window?.rootViewController as? NCMainTabBarController {
controller.account = account
self.dismiss(animated: true)
} else {
if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController {
controller.account = account
controller.modalPresentationStyle = .fullScreen
controller.view.alpha = 0
window?.rootViewController = controller

Просмотреть файл

@ -67,17 +67,18 @@ struct NCLoginPoll: View {
.onChange(of: loginManager.pollFinished) { value in
if value {
let window = UIApplication.shared.firstWindow
if window?.rootViewController is NCMainTabBarController {
window?.rootViewController?.dismiss(animated: true, completion: nil)
if let controller = window?.rootViewController as? NCMainTabBarController {
controller.account = loginManager.account
controller.dismiss(animated: true, completion: nil)
} else {
if let mainTabBarController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController {
mainTabBarController.modalPresentationStyle = .fullScreen
mainTabBarController.view.alpha = 0
window?.rootViewController = mainTabBarController
if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController {
controller.account = loginManager.account
controller.modalPresentationStyle = .fullScreen
controller.view.alpha = 0
window?.rootViewController = controller
window?.makeKeyAndVisible()
UIView.animate(withDuration: 0.5) {
mainTabBarController.view.alpha = 1
controller.view.alpha = 1
}
}
}
@ -91,6 +92,9 @@ struct NCLoginPoll: View {
loginManager.openLoginInBrowser()
}
}
.onDisappear {
loginManager.onDisappear()
}
.interactiveDismissDisabled()
}
}
@ -100,41 +104,54 @@ struct NCLoginPoll: View {
}
private class LoginManager: ObservableObject {
private let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
var loginFlowV2Token = ""
var loginFlowV2Endpoint = ""
var loginFlowV2Login = ""
@Published var pollFinished = false
@Published var isLoading = false
@Published var account = ""
init() {
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidBecomeActive(_:)), name: UIApplication.didBecomeActiveNotification, object: nil)
}
@objc func applicationDidBecomeActive(_ notification: NSNotification) {
poll()
}
var timer: DispatchSourceTimer?
func configure(loginFlowV2Token: String, loginFlowV2Endpoint: String, loginFlowV2Login: String) {
self.loginFlowV2Token = loginFlowV2Token
self.loginFlowV2Endpoint = loginFlowV2Endpoint
self.loginFlowV2Login = loginFlowV2Login
poll()
}
func poll() {
let queue = DispatchQueue.global(qos: .background)
timer = DispatchSource.makeTimerSource(queue: queue)
guard let timer = timer else { return }
timer.schedule(deadline: .now(), repeating: .seconds(1), leeway: .seconds(1))
timer.setEventHandler(handler: {
DispatchQueue.main.async {
let controller = UIApplication.shared.firstWindow?.rootViewController as? NCMainTabBarController
NextcloudKit.shared.getLoginFlowV2Poll(token: self.loginFlowV2Token, endpoint: self.loginFlowV2Endpoint) { server, loginName, appPassword, _, error in
if error == .success, let urlBase = server, let user = loginName, let appPassword {
self.isLoading = true
self.appDelegate.createAccount(urlBase: urlBase, user: user, password: appPassword) { error in
NCAccount().createAccount(urlBase: urlBase, user: user, password: appPassword, controller: controller) { account, error in
if error == .success {
self.account = account
self.pollFinished = true
}
}
}
}
}
})
timer.resume()
}
func onDisappear() {
timer?.cancel()
}
func openLoginInBrowser() {
UIApplication.shared.open(URL(string: loginFlowV2Login)!)

Просмотреть файл

@ -22,13 +22,12 @@
//
import UIKit
import WebKit
@preconcurrency import WebKit
import NextcloudKit
import FloatingPanel
class NCLoginProvider: UIViewController {
var webView: WKWebView?
let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
let utility = NCUtility()
var titleView: String = ""
var urlBase = ""
@ -58,24 +57,17 @@ class NCLoginProvider: UIViewController {
if let host = URL(string: urlBase)?.host {
titleView = host
if let account = NCManageDatabase.shared.getActiveAccount(), NCKeychain().getPassword(account: account.account).isEmpty {
titleView = NSLocalizedString("_user_", comment: "") + " " + account.userId + " " + NSLocalizedString("_in_", comment: "") + " " + host
if let activeTableAccount = NCManageDatabase.shared.getActiveTableAccount(), NCKeychain().getPassword(account: activeTableAccount.account).isEmpty {
titleView = NSLocalizedString("_user_", comment: "") + " " + activeTableAccount.userId + " " + NSLocalizedString("_in_", comment: "") + " " + host
}
}
self.title = titleView
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Stop timer error network
appDelegate.timerErrorNetworkingDisabled = true
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NCActivityIndicator.shared.stop()
appDelegate.timerErrorNetworkingDisabled = false
}
func loadWebPage(webView: WKWebView, url: URL) {
@ -166,17 +158,27 @@ extension NCLoginProvider: WKNavigationDelegate {
let account: String = "\(username) \(urlBase)"
let user = username
NextcloudKit.shared.setup(account: account, user: user, userId: user, password: password, urlBase: urlBase)
NextcloudKit.shared.getUserProfile(account: account) { _, userProfile, _, error in
NextcloudKit.shared.getUserProfile(account: account) { account, userProfile, _, error in
if error == .success, let userProfile {
NCManageDatabase.shared.deleteAccount(account)
NextcloudKit.shared.appendSession(account: account,
urlBase: urlBase,
user: user,
userId: user,
password: password,
userAgent: userAgent,
nextcloudVersion: NCCapabilities.shared.getCapabilities(account: account).capabilityServerVersionMajor,
groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
NCSession.shared.appendSession(account: account, urlBase: urlBase, user: user, userId: userProfile.userId)
NCManageDatabase.shared.addAccount(account, urlBase: urlBase, user: user, userId: userProfile.userId, password: password)
self.appDelegate.changeAccount(account, userProfile: userProfile) { }
NCAccount().changeAccount(account, userProfile: userProfile, controller: nil) { }
let window = UIApplication.shared.firstWindow
if window?.rootViewController is NCMainTabBarController {
if let controller = window?.rootViewController as? NCMainTabBarController {
controller.account = account
self.dismiss(animated: true)
} else {
if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as? NCMainTabBarController {
controller.account = account
controller.modalPresentationStyle = .fullScreen
controller.view.alpha = 0
window?.rootViewController = controller

Просмотреть файл

@ -25,26 +25,32 @@ import UIKit
protocol NCCellProtocol {
var fileAvatarImageView: UIImageView? { get }
var fileObjectId: String? { get set }
var fileAccount: String? { get set }
var fileOcId: String? { get set }
var fileOcIdTransfer: String? { get set }
var filePreviewImageView: UIImageView? { get set }
var filePreviewImageBottom: NSLayoutConstraint? { get set }
var fileUser: String? { get set }
var fileTitleLabel: UILabel? { get set }
var fileInfoLabel: UILabel? { get set }
var fileSubinfoLabel: UILabel? { get set }
var fileProgressView: UIProgressView? { get set }
var fileStatusImage: UIImageView? { get set }
var fileLocalImage: UIImageView? { get set }
var fileFavoriteImage: UIImageView? { get set }
var fileSharedImage: UIImageView? { get set }
var fileMoreImage: UIImageView? { get set }
var cellSeparatorView: UIView? { get set }
var indexPath: IndexPath { get set }
func titleInfoTrailingDefault()
func titleInfoTrailingFull()
func writeInfoDateSize(date: NSDate, size: Int64)
func setButtonMore(named: String, image: UIImage)
func setButtonMore(image: UIImage)
func hideImageItem(_ status: Bool)
func hideImageFavorite(_ status: Bool)
func hideImageStatus(_ status: Bool)
func hideImageLocal(_ status: Bool)
func hideLabelTitle(_ status: Bool)
func hideLabelInfo(_ status: Bool)
func hideLabelSubinfo(_ status: Bool)
func hideButtonShare(_ status: Bool)
func hideButtonMore(_ status: Bool)
func selected(_ status: Bool, isEditMode: Bool)
@ -54,11 +60,18 @@ protocol NCCellProtocol {
}
extension NCCellProtocol {
var fileAvatarImageView: UIImageView? {
return nil
}
var fileObjectId: String? {
var fileAccount: String? {
get { return nil }
set {}
}
var fileOcId: String? {
get { return nil }
set {}
}
var fileOcIdTransfer: String? {
get { return nil }
set {}
}
@ -66,10 +79,6 @@ extension NCCellProtocol {
get { return nil }
set {}
}
var filePreviewImageBottom: NSLayoutConstraint? {
get { return nil }
set {}
}
var fileTitleLabel: UILabel? {
get { return nil }
set {}
@ -82,10 +91,6 @@ extension NCCellProtocol {
get { return nil }
set { }
}
var fileProgressView: UIProgressView? {
get { return nil }
set {}
}
var fileStatusImage: UIImageView? {
get { return nil }
set {}
@ -114,7 +119,14 @@ extension NCCellProtocol {
func titleInfoTrailingDefault() {}
func titleInfoTrailingFull() {}
func writeInfoDateSize(date: NSDate, size: Int64) {}
func setButtonMore(named: String, image: UIImage) {}
func setButtonMore(image: UIImage) {}
func hideImageItem(_ status: Bool) {}
func hideImageFavorite(_ status: Bool) {}
func hideImageStatus(_ status: Bool) {}
func hideImageLocal(_ status: Bool) {}
func hideLabelTitle(_ status: Bool) {}
func hideLabelInfo(_ status: Bool) {}
func hideLabelSubinfo(_ status: Bool) {}
func hideButtonShare(_ status: Bool) {}
func hideButtonMore(_ status: Bool) {}
func selected(_ status: Bool, isEditMode: Bool) {}

Просмотреть файл

@ -35,16 +35,20 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
@IBOutlet weak var buttonMore: UIButton!
@IBOutlet weak var imageVisualEffect: UIVisualEffectView!
var objectId = ""
var indexPath = IndexPath()
private var user = ""
var ocId = ""
var ocIdTransfer = ""
var account = ""
var user = ""
weak var gridCellDelegate: NCGridCellDelegate?
var namedButtonMore = ""
var fileObjectId: String? {
get { return objectId }
set { objectId = newValue ?? "" }
var fileOcId: String? {
get { return ocId }
set { ocId = newValue ?? "" }
}
var fileOcIdTransfer: String? {
get { return ocIdTransfer }
set { ocIdTransfer = newValue ?? "" }
}
var filePreviewImageView: UIImageView? {
get { return imageItem }
@ -95,25 +99,26 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
accessibilityValue = nil
isAccessibilityElement = true
imageItem.image = nil
imageItem.layer.cornerRadius = 6
imageItem.layer.masksToBounds = true
imageSelect.isHidden = true
imageSelect.image = NCImageCache.shared.getImageCheckedYes()
imageStatus.image = nil
imageFavorite.image = nil
imageLocal.image = nil
labelTitle.text = ""
labelInfo.text = ""
labelSubinfo.text = ""
imageVisualEffect.layer.cornerRadius = 6
imageVisualEffect.clipsToBounds = true
imageVisualEffect.alpha = 0.5
imageSelect.isHidden = true
imageSelect.image = NCImageCache.images.checkedYes
let longPressedGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPress(gestureRecognizer:)))
longPressedGesture.minimumPressDuration = 0.5
longPressedGesture.delegate = self
longPressedGesture.delaysTouchesBegan = true
self.addGestureRecognizer(longPressedGesture)
labelTitle.text = ""
labelInfo.text = ""
labelSubinfo.text = ""
}
override func snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? {
@ -121,30 +126,55 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
}
@IBAction func touchUpInsideMore(_ sender: Any) {
gridCellDelegate?.tapMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, image: imageItem.image, indexPath: indexPath, sender: sender)
gridCellDelegate?.tapMoreGridItem(with: ocId, ocIdTransfer: ocIdTransfer, image: imageItem.image, sender: sender)
}
@objc func longPress(gestureRecognizer: UILongPressGestureRecognizer) {
gridCellDelegate?.longPressGridItem(with: objectId, indexPath: indexPath, gestureRecognizer: gestureRecognizer)
gridCellDelegate?.longPressGridItem(with: ocId, ocIdTransfer: ocIdTransfer, gestureRecognizer: gestureRecognizer)
}
fileprivate func setA11yActions() {
let moreName = namedButtonMore == NCGlobal.shared.buttonMoreStop ? "_cancel_" : "_more_"
self.accessibilityCustomActions = [
UIAccessibilityCustomAction(
name: NSLocalizedString(moreName, comment: ""),
name: NSLocalizedString("_more_", comment: ""),
target: self,
selector: #selector(touchUpInsideMore))
]
}
func setButtonMore(named: String, image: UIImage) {
namedButtonMore = named
func setButtonMore(image: UIImage) {
buttonMore.setImage(image, for: .normal)
setA11yActions()
}
func hideImageItem(_ status: Bool) {
imageItem.isHidden = status
}
func hideImageFavorite(_ status: Bool) {
imageFavorite.isHidden = status
}
func hideImageStatus(_ status: Bool) {
imageStatus.isHidden = status
}
func hideImageLocal(_ status: Bool) {
imageLocal.isHidden = status
}
func hideLabelTitle(_ status: Bool) {
labelTitle.isHidden = status
}
func hideLabelInfo(_ status: Bool) {
labelInfo.isHidden = status
}
func hideLabelSubinfo(_ status: Bool) {
labelSubinfo.isHidden = status
}
func hideButtonMore(_ status: Bool) {
buttonMore.isHidden = status
}
@ -159,6 +189,7 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
}
if status {
imageSelect.isHidden = false
imageSelect.image = NCImageCache.shared.getImageCheckedYes()
imageVisualEffect.isHidden = false
} else {
imageSelect.isHidden = true
@ -191,8 +222,8 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
}
protocol NCGridCellDelegate: AnyObject {
func tapMoreGridItem(with objectId: String, namedButtonMore: String, image: UIImage?, indexPath: IndexPath, sender: Any)
func longPressGridItem(with objectId: String, indexPath: IndexPath, gestureRecognizer: UILongPressGestureRecognizer)
func tapMoreGridItem(with ocId: String, ocIdTransfer: String, image: UIImage?, sender: Any)
func longPressGridItem(with ocId: String, ocIdTransfer: String, gestureRecognizer: UILongPressGestureRecognizer)
}
// MARK: - Grid Layout

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше