Quellcode durchsuchen

Merge branch 'develop'

marinofaggiana vor 6 Jahren
Ursprung
Commit
107f827ec7
100 geänderte Dateien mit 1248 neuen und 494 gelöschten Zeilen
  1. 13 12
      Cartfile
  2. 2 1
      Cartfile.resolved
  3. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/CLI/CLIColor.h
  4. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/CLI/CLIColor.m
  5. 18 18
      Carthage/Checkouts/CocoaLumberjack/Classes/CocoaLumberjack.h
  6. 6 6
      Carthage/Checkouts/CocoaLumberjack/Classes/CocoaLumberjack.swift
  7. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.h
  8. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.m
  9. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogger.h
  10. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogger.m
  11. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h
  12. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.m
  13. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDAssertMacros.h
  14. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.h
  15. 39 23
      Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.m
  16. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLegacyMacros.h
  17. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLog+LOGV.h
  18. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.h
  19. 68 52
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.m
  20. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDLogMacros.h
  21. 14 2
      Carthage/Checkouts/CocoaLumberjack/Classes/DDOSLogger.h
  22. 55 17
      Carthage/Checkouts/CocoaLumberjack/Classes/DDOSLogger.m
  23. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.h
  24. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.m
  25. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.h
  26. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.m
  27. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.h
  28. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.m
  29. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.h
  30. 1 1
      Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.m
  31. 1 1
      Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec
  32. 1 1
      Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjack-Info.plist
  33. 1 1
      Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjack-Prefix.pch
  34. 1 1
      Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjackSwift-Info.plist
  35. 1 1
      Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjackSwift.h
  36. 1 1
      Carthage/Checkouts/CocoaLumberjack/Tests/Tests/DDBasicLoggingTests.m
  37. 1 1
      Carthage/Checkouts/CocoaLumberjack/Tests/Tests/DDLogMessageTests.m
  38. 1 1
      Carthage/Checkouts/CocoaLumberjack/Tests/Tests/DDLogTests.m
  39. 0 31
      Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPRequest.m
  40. 102 83
      Nextcloud.xcodeproj/project.pbxproj
  41. 28 29
      Notification Service Extension/NotificationService.swift
  42. 7 7
      Notification Service Extension/NotificationServiceExtension-Bridging-Header.h
  43. 198 62
      iOSClient/AppDelegate.m
  44. 2 2
      iOSClient/Brand/File_Provider_Extension.plist
  45. 7 0
      iOSClient/Brand/Intro/CCIntro.m
  46. 1 1
      iOSClient/Brand/NCBridgeSwift.h
  47. 2 2
      iOSClient/Brand/Notification_Service_Extension.plist
  48. 2 2
      iOSClient/Brand/Share.plist
  49. 3 2
      iOSClient/Brand/iOSClient.plist
  50. 1 0
      iOSClient/CCGlobal.h
  51. 10 0
      iOSClient/Database/NCManageDatabase.swift
  52. 2 0
      iOSClient/Favorites/CCFavorites.m
  53. 201 0
      iOSClient/Imagemeter/IMImagemeter.swift
  54. 46 0
      iOSClient/Imagemeter/IMImagemeterView.xib
  55. 15 0
      iOSClient/Images.xcassets/audioPlayFull.imageset/Contents.json
  56. BIN
      iOSClient/Images.xcassets/audioPlayFull.imageset/audioPlayFull.pdf
  57. 15 0
      iOSClient/Images.xcassets/imagemeter.imageset/Contents.json
  58. BIN
      iOSClient/Images.xcassets/imagemeter.imageset/imagemeter.png
  59. 4 1
      iOSClient/Library/OCCommunicationLib/OCWebDavClient/OCWebDAVClient.m
  60. 1 1
      iOSClient/Login/CCLogin.h
  61. 1 14
      iOSClient/Login/CCLogin.m
  62. 1 4
      iOSClient/Login/CCLoginWeb.swift
  63. 4 0
      iOSClient/Main/CCDetail.h
  64. 32 8
      iOSClient/Main/CCDetail.m
  65. 7 10
      iOSClient/Main/CCMain.m
  66. 1 4
      iOSClient/Main/CCMore.swift
  67. 3 3
      iOSClient/Main/CCSplit.m
  68. 148 5
      iOSClient/Main/NCMainCommon.swift
  69. 6 0
      iOSClient/Media/NCMedia.swift
  70. 1 1
      iOSClient/Networking/NCService.swift
  71. 3 2
      iOSClient/Networking/OCNetworking.h
  72. 73 7
      iOSClient/Networking/OCNetworking.m
  73. 3 0
      iOSClient/Offline/NCOffline.swift
  74. 1 0
      iOSClient/PeekPop/CCPeekPop.h
  75. 16 30
      iOSClient/PeekPop/CCPeekPop.m
  76. 1 4
      iOSClient/Security/NCPushNotificationEncryption.h
  77. 6 9
      iOSClient/Security/NCPushNotificationEncryption.m
  78. 5 6
      iOSClient/Settings/CCManageAccount.m
  79. 1 1
      iOSClient/Shares/NCShares.h
  80. 41 0
      iOSClient/Shares/NCShares.m
  81. BIN
      iOSClient/Supporting Files/ast.lproj/Localizable.strings
  82. BIN
      iOSClient/Supporting Files/ca.lproj/Localizable.strings
  83. BIN
      iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings
  84. BIN
      iOSClient/Supporting Files/da.lproj/Localizable.strings
  85. BIN
      iOSClient/Supporting Files/de.lproj/Localizable.strings
  86. BIN
      iOSClient/Supporting Files/el.lproj/Localizable.strings
  87. BIN
      iOSClient/Supporting Files/en-GB.lproj/Localizable.strings
  88. 2 2
      iOSClient/Supporting Files/en.lproj/Localizable.strings
  89. BIN
      iOSClient/Supporting Files/es-419.lproj/Localizable.strings
  90. BIN
      iOSClient/Supporting Files/es-AR.lproj/Localizable.strings
  91. BIN
      iOSClient/Supporting Files/es-CL.lproj/Localizable.strings
  92. BIN
      iOSClient/Supporting Files/es-CO.lproj/Localizable.strings
  93. BIN
      iOSClient/Supporting Files/es-CR.lproj/Localizable.strings
  94. BIN
      iOSClient/Supporting Files/es-DO.lproj/Localizable.strings
  95. BIN
      iOSClient/Supporting Files/es-EC.lproj/Localizable.strings
  96. BIN
      iOSClient/Supporting Files/es-GT.lproj/Localizable.strings
  97. BIN
      iOSClient/Supporting Files/es-HN.lproj/Localizable.strings
  98. BIN
      iOSClient/Supporting Files/es-MX.lproj/Localizable.strings
  99. BIN
      iOSClient/Supporting Files/es-NI.lproj/Localizable.strings
  100. BIN
      iOSClient/Supporting Files/es-PA.lproj/Localizable.strings

+ 13 - 12
Cartfile

@@ -1,16 +1,17 @@
-github "tilltue/TLPhotoPicker"
-github "kishikawakatsumi/UICKeyChainStore"
+github "tilltue/TLPhotoPicker" == 1.8.3
+github "kishikawakatsumi/UICKeyChainStore" == 2.1.2
 github "danielsaidi/Sheeeeeeeeet" == 1.2.2
-github "sgr-ksmt/PDFGenerator" ~> 2.1
-github "MortimerGoro/MGSwipeTableCell"
-github "dzenbot/DZNEmptyDataSet"
-github "ealeksandrov/EAIntroView"
-github "calimarkus/JDStatusBarNotification"
-github "ChangbaDevs/KTVHTTPCache" ~> 1.1.7
-github "jdg/MBProgressHUD" ~> 1.1.0
-github "realm/realm-cocoa"
-github "SVGKit/SVGKit" "2.x"
+github "sgr-ksmt/PDFGenerator" == 2.1
+github "MortimerGoro/MGSwipeTableCell" == 1.6.8
+github "dzenbot/DZNEmptyDataSet" == 1.8.1
+github "ealeksandrov/EAIntroView" == 2.12.0
+github "calimarkus/JDStatusBarNotification" == 1.6.0
+github "ChangbaDevs/KTVHTTPCache" == 2.0.0
+github "jdg/MBProgressHUD" == 1.1.0
+github "realm/realm-cocoa" == 3.13.1
+github "SVGKit/SVGKit" == 2.1.0
 github "WeTransfer/WeScan" == 0.9.1
-github "malcommac/SwiftRichString"
+github "malcommac/SwiftRichString" == 2.0.1
 github "https://github.com/marinofaggiana/FastScroll" "master"
 github "yannickl/QRCodeReader.swift" >= 10.0.0
+github "marmelroy/Zip"

+ 2 - 1
Cartfile.resolved

@@ -1,5 +1,5 @@
 github "ChangbaDevs/KTVHTTPCache" "1.1.7"
-github "CocoaLumberjack/CocoaLumberjack" "3.5.1"
+github "CocoaLumberjack/CocoaLumberjack" "3.5.2"
 github "MortimerGoro/MGSwipeTableCell" "1.6.8"
 github "SVGKit/SVGKit" "4b507e48da30711e25d1bcdd19580f25887a2267"
 github "WeTransfer/WeScan" "v0.9.1"
@@ -12,6 +12,7 @@ github "jdg/MBProgressHUD" "1.1.0"
 github "kishikawakatsumi/UICKeyChainStore" "v2.1.2"
 github "malcommac/SwiftRichString" "2.1.0"
 github "marinofaggiana/FastScroll" "81967c2309d29bc2c330d422da612160a30bade8"
+github "marmelroy/Zip" "1.1.0"
 github "realm/realm-cocoa" "v3.13.1"
 github "sgr-ksmt/PDFGenerator" "2.1.1"
 github "tilltue/TLPhotoPicker" "1.8.3"

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/CLI/CLIColor.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/CLI/CLIColor.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 18 - 18
Carthage/Checkouts/CocoaLumberjack/Classes/CocoaLumberjack.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,
@@ -71,33 +71,33 @@ FOUNDATION_EXPORT const unsigned char CocoaLumberjackVersionString[];
 #endif
 
 // Core
-#import "DDLog.h"
+#import <CocoaLumberjack/DDLog.h>
 
 // Main macros
-#import "DDLogMacros.h"
-#import "DDAssertMacros.h"
+#import <CocoaLumberjack/DDLogMacros.h>
+#import <CocoaLumberjack/DDAssertMacros.h>
 
 // Capture ASL
-#import "DDASLLogCapture.h"
+#import <CocoaLumberjack/DDASLLogCapture.h>
 
 // Loggers
-#import "DDLoggerNames.h"
+#import <CocoaLumberjack/DDLoggerNames.h>
 
-#import "DDTTYLogger.h"
-#import "DDASLLogger.h"
-#import "DDFileLogger.h"
-#import "DDOSLogger.h"
+#import <CocoaLumberjack/DDTTYLogger.h>
+#import <CocoaLumberjack/DDASLLogger.h>
+#import <CocoaLumberjack/DDFileLogger.h>
+#import <CocoaLumberjack/DDOSLogger.h>
 
 // Extensions
-#import "DDContextFilterLogFormatter.h"
-#import "DDDispatchQueueLogFormatter.h"
-#import "DDMultiFormatter.h"
-#import "DDFileLogger+Buffering.h"
+#import <CocoaLumberjack/DDContextFilterLogFormatter.h>
+#import <CocoaLumberjack/DDDispatchQueueLogFormatter.h>
+#import <CocoaLumberjack/DDMultiFormatter.h>
+#import <CocoaLumberjack/DDFileLogger+Buffering.h>
 
 // CLI
-#import "CLIColor.h"
+#import <CocoaLumberjack/CLIColor.h>
 
 // etc
-#import "DDAbstractDatabaseLogger.h"
-#import "DDLog+LOGV.h"
-#import "DDLegacyMacros.h"
+#import <CocoaLumberjack/DDAbstractDatabaseLogger.h>
+#import <CocoaLumberjack/DDLog+LOGV.h>
+#import <CocoaLumberjack/DDLegacyMacros.h>

+ 6 - 6
Carthage/Checkouts/CocoaLumberjack/Classes/CocoaLumberjack.swift

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,
@@ -111,7 +111,7 @@ public func DDLogDebug(_ message: @autoclosure () -> String,
                        tag: Any? = nil,
                        asynchronous async: Bool = asyncLoggingEnabled,
                        ddlog: DDLog = .sharedInstance) {
-    _DDLogMessage(message, level: level, flag: .debug, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
+    _DDLogMessage(message(), level: level, flag: .debug, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
 }
 
 @inlinable
@@ -124,7 +124,7 @@ public func DDLogInfo(_ message: @autoclosure () -> String,
                       tag: Any? = nil,
                       asynchronous async: Bool = asyncLoggingEnabled,
                       ddlog: DDLog = .sharedInstance) {
-    _DDLogMessage(message, level: level, flag: .info, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
+    _DDLogMessage(message(), level: level, flag: .info, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
 }
 
 @inlinable
@@ -137,7 +137,7 @@ public func DDLogWarn(_ message: @autoclosure () -> String,
                       tag: Any? = nil,
                       asynchronous async: Bool = asyncLoggingEnabled,
                       ddlog: DDLog = .sharedInstance) {
-    _DDLogMessage(message, level: level, flag: .warning, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
+    _DDLogMessage(message(), level: level, flag: .warning, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
 }
 
 @inlinable
@@ -150,7 +150,7 @@ public func DDLogVerbose(_ message: @autoclosure () -> String,
                          tag: Any? = nil,
                          asynchronous async: Bool = asyncLoggingEnabled,
                          ddlog: DDLog = .sharedInstance) {
-    _DDLogMessage(message, level: level, flag: .verbose, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
+    _DDLogMessage(message(), level: level, flag: .verbose, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
 }
 
 @inlinable
@@ -163,7 +163,7 @@ public func DDLogError(_ message: @autoclosure () -> String,
                        tag: Any? = nil,
                        asynchronous async: Bool = false,
                        ddlog: DDLog = .sharedInstance) {
-    _DDLogMessage(message, level: level, flag: .error, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
+    _DDLogMessage(message(), level: level, flag: .error, context: context, file: file, function: function, line: line, tag: tag, asynchronous: async, ddlog: ddlog)
 }
 
 /// Returns a String of the current filename, without full path or extension.

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogCapture.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogger.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDASLLogger.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDAbstractDatabaseLogger.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDAssertMacros.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 39 - 23
Carthage/Checkouts/CocoaLumberjack/Classes/DDFileLogger.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,
@@ -1007,39 +1007,55 @@ unsigned long long const kDDDefaultLogFilesDiskQuota   = 20 * 1024 * 1024; // 20
 - (DDLogFileInfo *)lt_currentLogFileInfo {
     NSAssert([self isOnInternalLoggerQueue], @"lt_ methods should be on logger queue.");
 
-    BOOL isResuming = _currentLogFileInfo == nil;
+    // Get the current log file info ivar (might be nil).
+    DDLogFileInfo *newCurrentLogFile = _currentLogFileInfo;
+
+    // Check if we're resuming and if so, get the first of the sorted log file infos.
+    BOOL isResuming = newCurrentLogFile == nil;
     if (isResuming) {
         NSArray *sortedLogFileInfos = [_logFileManager sortedLogFileInfos];
-        _currentLogFileInfo = sortedLogFileInfos.firstObject;
+        newCurrentLogFile = sortedLogFileInfos.firstObject;
     }
 
-    if (_currentLogFileInfo) {
-        BOOL isMostRecentLogArchived = _currentLogFileInfo.isArchived;
-        BOOL forceArchive = _doNotReuseLogFiles && isMostRecentLogArchived == NO;
-
-        if (forceArchive || [self lt_shouldLogFileBeArchived:_currentLogFileInfo]) {
-            _currentLogFileInfo.isArchived = YES;
-            NSString *archivedLogFilePath = [_currentLogFileInfo.fileName copy];
-            _currentLogFileInfo = nil;
-
-            if ([_logFileManager respondsToSelector:@selector(didArchiveLogFile:)]) {
-                dispatch_async(_completionQueue, ^{
-                    [self->_logFileManager didArchiveLogFile:archivedLogFilePath];
-                });
-            }
+    // Check if the file we've found is still valid. Otherwise create a new one.
+    if (newCurrentLogFile != nil && [self lt_shouldUseLogFile:newCurrentLogFile isResuming:isResuming]) {
+        if (isResuming) {
+            NSLogVerbose(@"DDFileLogger: Resuming logging with file %@", newCurrentLogFile.fileName);
         }
+        _currentLogFileInfo = newCurrentLogFile;
+    } else {
+        NSString *currentLogFilePath = [_logFileManager createNewLogFile];
+        _currentLogFileInfo = [[DDLogFileInfo alloc] initWithFilePath:currentLogFilePath];
     }
 
-    if (isResuming && _currentLogFileInfo) {
-        NSLogVerbose(@"DDFileLogger: Resuming logging with file %@", _currentLogFileInfo.fileName);
+    return _currentLogFileInfo;
+}
+
+- (BOOL)lt_shouldUseLogFile:(nonnull DDLogFileInfo *)logFileInfo isResuming:(BOOL)isResuming {
+    NSAssert([self isOnInternalLoggerQueue], @"lt_ methods should be on logger queue.");
+    NSParameterAssert(logFileInfo);
+
+    // Check if the log file is archived. We must not use archived log files.
+    if (logFileInfo.isArchived) {
+        return NO;
     }
 
-    if (!_currentLogFileInfo) {
-        NSString *currentLogFilePath = [_logFileManager createNewLogFile];
-        _currentLogFileInfo = [[DDLogFileInfo alloc] initWithFilePath:currentLogFilePath];
+    // If we're resuming, we need to check if the log file is allowed for reuse or needs to be archived.
+    if (isResuming && (_doNotReuseLogFiles || [self lt_shouldLogFileBeArchived:logFileInfo])) {
+        logFileInfo.isArchived = YES;
+        NSString *archivedLogFilePath = [logFileInfo.fileName copy];
+
+        if ([_logFileManager respondsToSelector:@selector(didArchiveLogFile:)]) {
+            dispatch_async(_completionQueue, ^{
+                [self->_logFileManager didArchiveLogFile:archivedLogFilePath];
+            });
+        }
+
+        return NO;
     }
 
-    return _currentLogFileInfo;
+    // All checks have passed. It's valid.
+    return YES;
 }
 
 - (void)lt_monitorCurrentLogFileForExternalChanges {

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDLegacyMacros.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDLog+LOGV.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 68 - 52
Carthage/Checkouts/CocoaLumberjack/Classes/DDLog.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,
@@ -127,12 +127,12 @@ static NSUInteger _numProcessors;
  */
 + (instancetype)sharedInstance {
     static id sharedInstance = nil;
-    
+
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
         sharedInstance = [[self alloc] init];
     });
-    
+
     return sharedInstance;
 }
 
@@ -146,23 +146,23 @@ static NSUInteger _numProcessors;
  **/
 + (void)initialize {
     static dispatch_once_t DDLogOnceToken;
-    
+
     dispatch_once(&DDLogOnceToken, ^{
         NSLogDebug(@"DDLog: Using grand central dispatch");
-        
+
         _loggingQueue = dispatch_queue_create("cocoa.lumberjack", NULL);
         _loggingGroup = dispatch_group_create();
-        
+
         void *nonNullValue = GlobalLoggingQueueIdentityKey; // Whatever, just not null
         dispatch_queue_set_specific(_loggingQueue, GlobalLoggingQueueIdentityKey, nonNullValue, NULL);
-        
+
         _queueSemaphore = dispatch_semaphore_create(DDLOG_MAX_QUEUE_SIZE);
-        
+
         // Figure out how many processors are available.
         // This may be used later for an optimization on uniprocessor machines.
-        
+
         _numProcessors = MAX([NSProcessInfo processInfo].processorCount, (NSUInteger) 1);
-        
+
         NSLogDebug(@"DDLog: numProcessors = %@", @(_numProcessors));
     });
 }
@@ -175,10 +175,10 @@ static NSUInteger _numProcessors;
  */
 - (id)init {
     self = [super init];
-    
+
     if (self) {
         self._loggers = [[NSMutableArray alloc] initWithCapacity:4];
-        
+
 #if TARGET_OS_IOS
         NSString *notificationName = UIApplicationWillTerminateNotification;
 #else
@@ -199,9 +199,9 @@ static NSUInteger _numProcessors;
                 [weakSelf applicationWillTerminate:nil];
             });
         }
-        
+
 #endif /* if TARGET_OS_IOS */
-        
+
         if (notificationName) {
             [[NSNotificationCenter defaultCenter] addObserver:self
                                                      selector:@selector(applicationWillTerminate:)
@@ -209,7 +209,7 @@ static NSUInteger _numProcessors;
                                                        object:nil];
         }
     }
-    
+
     return self;
 }
 
@@ -248,7 +248,7 @@ static NSUInteger _numProcessors;
     if (!logger) {
         return;
     }
-    
+
     dispatch_async(_loggingQueue, ^{ @autoreleasepool {
         [self lt_addLogger:logger level:level];
     } });
@@ -262,7 +262,7 @@ static NSUInteger _numProcessors;
     if (!logger) {
         return;
     }
-    
+
     dispatch_async(_loggingQueue, ^{ @autoreleasepool {
         [self lt_removeLogger:logger];
     } });
@@ -284,11 +284,11 @@ static NSUInteger _numProcessors;
 
 - (NSArray<id<DDLogger>> *)allLoggers {
     __block NSArray *theLoggers;
-    
+
     dispatch_sync(_loggingQueue, ^{ @autoreleasepool {
         theLoggers = [self lt_allLoggers];
     } });
-    
+
     return theLoggers;
 }
 
@@ -298,11 +298,11 @@ static NSUInteger _numProcessors;
 
 - (NSArray<DDLoggerInformation *> *)allLoggersWithLevel {
     __block NSArray *theLoggersWithLevel;
-    
+
     dispatch_sync(_loggingQueue, ^{ @autoreleasepool {
         theLoggersWithLevel = [self lt_allLoggersWithLevel];
     } });
-    
+
     return theLoggersWithLevel;
 }
 
@@ -378,16 +378,16 @@ static NSUInteger _numProcessors;
         tag:(id)tag
      format:(NSString *)format, ... {
     va_list args;
-    
+
     if (format) {
         va_start(args, format);
-        
+
         NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
-        
+
         va_end(args);
-        
+
         va_start(args, format);
-        
+
         [self log:asynchronous
           message:message
             level:level
@@ -397,7 +397,7 @@ static NSUInteger _numProcessors;
          function:function
              line:line
               tag:tag];
-        
+
         va_end(args);
     }
 }
@@ -412,16 +412,16 @@ static NSUInteger _numProcessors;
         tag:(id)tag
      format:(NSString *)format, ... {
     va_list args;
-    
+
     if (format) {
         va_start(args, format);
-        
+
         NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
-        
+
         va_end(args);
-        
+
         va_start(args, format);
-        
+
         [self log:asynchronous
           message:message
             level:level
@@ -431,7 +431,7 @@ static NSUInteger _numProcessors;
          function:function
              line:line
               tag:tag];
-        
+
         va_end(args);
     }
 }
@@ -504,7 +504,7 @@ static NSUInteger _numProcessors;
                                                                  tag:tag
                                                              options:(DDLogMessageOptions)0
                                                            timestamp:nil];
-    
+
     [self queueLogMessage:logMessage asynchronously:asynchronous];
 }
 
@@ -753,19 +753,19 @@ static NSUInteger _numProcessors;
             break;
         }
     }
-    
+
     if (loggerNode == nil) {
         NSLogDebug(@"DDLog: Request to remove logger which wasn't added");
         return;
     }
-    
+
     // Notify logger
     if ([logger respondsToSelector:@selector(willRemoveLogger)]) {
         dispatch_async(loggerNode->_loggerQueue, ^{ @autoreleasepool {
             [logger willRemoveLogger];
         } });
     }
-    
+
     // Remove from loggers array
     [self._loggers removeObject:loggerNode];
 }
@@ -773,7 +773,7 @@ static NSUInteger _numProcessors;
 - (void)lt_removeAllLoggers {
     NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey),
              @"This method should only be run on the logging thread/queue");
-    
+
     // Notify all loggers
     for (DDLoggerNode *loggerNode in self._loggers) {
         if ([loggerNode->_logger respondsToSelector:@selector(willRemoveLogger)]) {
@@ -782,7 +782,7 @@ static NSUInteger _numProcessors;
             } });
         }
     }
-    
+
     // Remove all loggers from array
 
     [self._loggers removeAllObjects];
@@ -804,14 +804,14 @@ static NSUInteger _numProcessors;
 - (NSArray *)lt_allLoggersWithLevel {
     NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey),
              @"This method should only be run on the logging thread/queue");
-    
+
     NSMutableArray *theLoggersWithLevel = [NSMutableArray new];
-    
+
     for (DDLoggerNode *loggerNode in self._loggers) {
         [theLoggersWithLevel addObject:[DDLoggerInformation informationWithLogger:loggerNode->_logger
                                                                          andLevel:loggerNode->_level]];
     }
-    
+
     return [theLoggersWithLevel copy];
 }
 
@@ -835,23 +835,39 @@ static NSUInteger _numProcessors;
             if (!(logMessage->_flag & loggerNode->_level)) {
                 continue;
             }
-            
+
             dispatch_group_async(_loggingGroup, loggerNode->_loggerQueue, ^{ @autoreleasepool {
                 [loggerNode->_logger logMessage:logMessage];
             } });
         }
-        
+
         dispatch_group_wait(_loggingGroup, DISPATCH_TIME_FOREVER);
     } else {
         // Execute each logger serially, each within its own queue.
-        
+
         for (DDLoggerNode *loggerNode in self._loggers) {
             // skip the loggers that shouldn't write this message based on the log level
 
             if (!(logMessage->_flag & loggerNode->_level)) {
                 continue;
             }
-            
+
+#if DD_DEBUG
+            // we must assure that we aren not on loggerNode->_loggerQueue.
+            if (loggerNode->_loggerQueue == NULL) {
+              // tell that we can't dispatch logger node on queue that is NULL.
+              NSLogDebug(@"DDLog: current node has loggerQueue == NULL");
+            }
+            else {
+              dispatch_async(loggerNode->_loggerQueue, ^{
+                if (dispatch_get_specific(GlobalLoggingQueueIdentityKey)) {
+                  // tell that we somehow on logging queue?
+                  NSLogDebug(@"DDLog: current node has loggerQueue == globalLoggingQueue");
+                }
+              });
+            }
+#endif
+            // next, we must check that node is OK.
             dispatch_sync(loggerNode->_loggerQueue, ^{ @autoreleasepool {
                 [loggerNode->_logger logMessage:logMessage];
             } });
@@ -880,10 +896,10 @@ static NSUInteger _numProcessors;
     //
     // Now we need to propagate the flush request to any loggers that implement the flush method.
     // This is designed for loggers that buffer IO.
-    
+
     NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey),
              @"This method should only be run on the logging thread/queue");
-    
+
     for (DDLoggerNode *loggerNode in self._loggers) {
         if ([loggerNode->_logger respondsToSelector:@selector(flush)]) {
             dispatch_group_async(_loggingGroup, loggerNode->_loggerQueue, ^{ @autoreleasepool {
@@ -891,7 +907,7 @@ static NSUInteger _numProcessors;
             } });
         }
     }
-    
+
     dispatch_group_wait(_loggingGroup, DISPATCH_TIME_FOREVER);
 }
 
@@ -1052,7 +1068,7 @@ NSString * __nullable DDExtractFileNameWithoutExtension(const char *filePath, BO
         {
             _fileName = [_fileName substringToIndex:dotLocation];
         }
-        
+
         // Try to get the current queue's label
         _queueLabel = [[NSString alloc] initWithFormat:@"%s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)];
     }
@@ -1061,7 +1077,7 @@ NSString * __nullable DDExtractFileNameWithoutExtension(const char *filePath, BO
 
 - (id)copyWithZone:(NSZone * __attribute__((unused)))zone {
     DDLogMessage *newMessage = [DDLogMessage new];
-    
+
     newMessage->_message = _message;
     newMessage->_level = _level;
     newMessage->_flag = _flag;
@@ -1216,7 +1232,7 @@ NSString * __nullable DDExtractFileNameWithoutExtension(const char *filePath, BO
                 }
 
                 self->_logFormatter = logFormatter;
- 
+
                 if ([self->_logFormatter respondsToSelector:@selector(didAddToLogger:inQueue:)]) {
                     [self->_logFormatter didAddToLogger:self inQueue:self->_loggerQueue];
                 } else if ([self->_logFormatter respondsToSelector:@selector(didAddToLogger:)]) {

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDLogMacros.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 14 - 2
Carthage/Checkouts/CocoaLumberjack/Classes/DDOSLogger.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,
@@ -31,8 +31,20 @@ API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
 /**
  *  Singleton method
  *
- *  @return the shared instance
+ *  @return the shared instance with OS_LOG_DEFAULT.
  */
 @property (class, readonly, strong) DDOSLogger *sharedInstance;
 
+/**
+ Designed initializer
+ 
+ @param subsystem Desired subsystem in log. Consider "org.example"
+ @param category Desired category in log. Consider "Point of interests."
+ @return New instance of DDOSLogger.
+ 
+ @discussion This method accepts parameters of type (String, String)?
+ If both parameters are nil, this method will return logger wrapper for `OS_LOG_DEFAULT`.
+ If both parameters are not nil, it will return logger wrapper for `os_log_create(subsystem, category)`
+ */
+- (instancetype)initWithSubsystem:(NSString *)subsystem category:(NSString *)category NS_DESIGNATED_INITIALIZER;
 @end

+ 55 - 17
Carthage/Checkouts/CocoaLumberjack/Classes/DDOSLogger.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,
@@ -17,10 +17,41 @@
 
 #import <os/log.h>
 
+@interface DDOSLogger () {
+    NSString *_subsystem;
+    NSString *_category;
+}
+@property (copy, nonatomic, readonly) NSString *subsystem;
+@property (copy, nonatomic, readonly) NSString *category;
+@property (strong, nonatomic, readwrite) os_log_t  logger;
+@end
+
 @implementation DDOSLogger
 
+@synthesize subsystem = _subsystem;
+@synthesize category = _category;
+
+#pragma mark - Initialization
+
+/**
+ * Assertion
+ * Swift: (String, String)?
+ */
+- (instancetype)initWithSubsystem:(NSString *)subsystem category:(NSString *)category {
+    NSAssert((subsystem == nil) == (category == nil), @"Either both subsystem and category or neither can be nil.");
+    if (self = [super init]) {
+        _subsystem = [subsystem copy];
+        _category = [category copy];
+    }
+    return self;
+}
+
 static DDOSLogger *sharedInstance;
 
+- (instancetype)init {
+    return [self initWithSubsystem:nil category:nil];
+}
+
 + (instancetype)sharedInstance {
     static dispatch_once_t DDOSLoggerOnceToken;
 
@@ -31,46 +62,54 @@ static DDOSLogger *sharedInstance;
     return sharedInstance;
 }
 
-- (instancetype)init {
-    if (sharedInstance != nil) {
-        return nil;
-    }
+#pragma mark - os_log
 
-    if (self = [super init]) {
-        return self;
+- (os_log_t)getLogger {
+    if (self.subsystem == nil || self.category == nil) {
+        return OS_LOG_DEFAULT;
     }
+    __auto_type subdomain = self.subsystem.UTF8String;
+    __auto_type category = self.category.UTF8String;
+    return os_log_create(subdomain, category);
+}
 
-    return nil;
+- (os_log_t)logger {
+    if (_logger == nil)  {
+        _logger = [self getLogger];
+    }
+    return _logger;
 }
 
+#pragma mark - DDLogger
+
 - (void)logMessage:(DDLogMessage *)logMessage {
     // Skip captured log messages
     if ([logMessage->_fileName isEqualToString:@"DDASLLogCapture"]) {
         return;
     }
-    
+
     if(@available(iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0, *)) {
-        
+
         NSString * message = _logFormatter ? [_logFormatter formatLogMessage:logMessage] : logMessage->_message;
-        if (message) {
+        if (message != nil) {
             const char *msg = [message UTF8String];
-            
+            __auto_type logger = [self logger];
             switch (logMessage->_flag) {
                 case DDLogFlagError     :
-                    os_log_error(OS_LOG_DEFAULT, "%{public}s", msg);
+                    os_log_error(logger, "%{public}s", msg);
                     break;
                 case DDLogFlagWarning   :
                 case DDLogFlagInfo      :
-                    os_log_info(OS_LOG_DEFAULT, "%{public}s", msg);
+                    os_log_info(logger, "%{public}s", msg);
                     break;
                 case DDLogFlagDebug     :
                 case DDLogFlagVerbose   :
                 default                 :
-                    os_log_debug(OS_LOG_DEFAULT, "%{public}s", msg);
+                    os_log_debug(logger, "%{public}s", msg);
                     break;
             }
         }
-        
+
     }
 
 }
@@ -78,5 +117,4 @@ static DDOSLogger *sharedInstance;
 - (DDLoggerName)loggerName {
     return DDLoggerNameOS;
 }
-
 @end

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/DDTTYLogger.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDContextFilterLogFormatter.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDDispatchQueueLogFormatter.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Classes/Extensions/DDMultiFormatter.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/CocoaLumberjack.podspec

@@ -2,7 +2,7 @@
 Pod::Spec.new do |s|
 
   s.name     = 'CocoaLumberjack'
-  s.version  = '3.5.1'
+  s.version  = '3.5.2'
   s.license  = 'BSD'
   s.summary  = 'A fast & simple, yet powerful & flexible logging framework for Mac and iOS.'
   s.homepage = 'https://github.com/CocoaLumberjack/CocoaLumberjack'

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjack-Info.plist

@@ -17,7 +17,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>3.5.1</string>
+	<string>3.5.2</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjack-Prefix.pch

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjackSwift-Info.plist

@@ -17,7 +17,7 @@
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
-	<string>3.5.1</string>
+	<string>3.5.2</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Framework/Lumberjack/CocoaLumberjackSwift.h

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Tests/Tests/DDBasicLoggingTests.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Tests/Tests/DDLogMessageTests.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 1 - 1
Carthage/Checkouts/CocoaLumberjack/Tests/Tests/DDLogTests.m

@@ -1,6 +1,6 @@
 // Software License Agreement (BSD License)
 //
-// Copyright (c) 2010-2018, Deusty, LLC
+// Copyright (c) 2010-2019, Deusty, LLC
 // All rights reserved.
 //
 // Redistribution and use of this software in source and binary forms,

+ 0 - 31
Carthage/Checkouts/KTVHTTPCache/KTVHTTPCache/Classes/KTVHCHTTPServer/KTVHCHTTPRequest.m

@@ -1,31 +0,0 @@
-//
-//  KTVHCHTTPRequest.m
-//  KTVHTTPCache
-//
-//  Created by Single on 2017/8/10.
-//  Copyright © 2017年 Single. All rights reserved.
-//
-
-#import "KTVHCHTTPRequest.h"
-#import "KTVHCLog.h"
-
-@implementation KTVHCHTTPRequest
-
-- (instancetype)initWithURL:(NSURL *)URL headers:(NSDictionary *)headers
-{
-    if (self = [super init])
-    {
-        KTVHCLogAlloc(self);
-        _URL = URL;
-        _headers = headers;
-        KTVHCLogHTTPRequest(@"%p, Create reqeust\nURL : %@\nHeaders : %@", self, self.URL, self.headers);
-    }
-    return self;
-}
-
-- (void)dealloc
-{
-    KTVHCLogDealloc(self);
-}
-
-@end

+ 102 - 83
Nextcloud.xcodeproj/project.pbxproj

@@ -113,18 +113,6 @@
 		F72D1001210B6638009C96B7 /* FirebaseCoreDiagnostics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F72D0FF8210B6638009C96B7 /* FirebaseCoreDiagnostics.framework */; };
 		F72D1003210B67CE009C96B7 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F72D1002210B67CE009C96B7 /* GoogleService-Info.plist */; };
 		F72D1007210B6882009C96B7 /* NCPushNotificationEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F72D1005210B6882009C96B7 /* NCPushNotificationEncryption.m */; };
-		F72D100F210B6B17009C96B7 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72D100E210B6B17009C96B7 /* NotificationService.swift */; };
-		F72D1013210B6B17009C96B7 /* Notification Service Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = F72D100C210B6B16009C96B7 /* Notification Service Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
-		F72D101A210B7473009C96B7 /* CCUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F7053E3D1C639DF500741EA5 /* CCUtility.m */; };
-		F72D103A210B769E009C96B7 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
-		F72D103B210B76A1009C96B7 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
-		F72D103C210B777F009C96B7 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
-		F72D103D210B7796009C96B7 /* OCSharedDto.m in Sources */ = {isa = PBXBuildFile; fileRef = F70022791EC4C9100080073F /* OCSharedDto.m */; };
-		F72D103E210B77A5009C96B7 /* OCActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = F70022671EC4C9100080073F /* OCActivity.m */; };
-		F72D103F210B77B8009C96B7 /* NCPushNotificationEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F72D1005210B6882009C96B7 /* NCPushNotificationEncryption.m */; };
-		F72D1040210B77EA009C96B7 /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F70A63061D5B3467004E2AA5 /* libcrypto.a */; };
-		F72D1041210B77ED009C96B7 /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F70A63071D5B3467004E2AA5 /* libssl.a */; };
-		F72D1042210B783D009C96B7 /* NCEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F70CAE391F8CF31A008125FD /* NCEndToEndEncryption.m */; };
 		F72E0B9D21AD60BC00898D7B /* WeScan.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F72E0B9C21AD60BC00898D7B /* WeScan.framework */; };
 		F732BA061D76CE1500E9878B /* CCNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F732BA041D76CE1500E9878B /* CCNetworking.m */; };
 		F732BA0B1D76DBA500E9878B /* CCNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F732BA041D76CE1500E9878B /* CCNetworking.m */; };
@@ -196,6 +184,19 @@
 		F73D71641F2674A400E233EB /* NCText.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F73D71631F2674A400E233EB /* NCText.storyboard */; };
 		F73F537F1E929C8500F8678D /* CCMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73F537E1E929C8500F8678D /* CCMore.swift */; };
 		F7417DB3216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7417DB2216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift */; };
+		F7425B2B224B846E009A3857 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7425B2A224B846E009A3857 /* NotificationService.swift */; };
+		F7425B2F224B846E009A3857 /* Notification Service Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = F7425B28224B846E009A3857 /* Notification Service Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
+		F7425B35224B871B009A3857 /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F70A63071D5B3467004E2AA5 /* libssl.a */; };
+		F7425B36224B872B009A3857 /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F70A63061D5B3467004E2AA5 /* libcrypto.a */; };
+		F7425B37224B89D2009A3857 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
+		F7425B38224B89D6009A3857 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
+		F7425B39224B89FE009A3857 /* CCUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = F7053E3D1C639DF500741EA5 /* CCUtility.m */; };
+		F7425B3A224B8A23009A3857 /* NCPushNotificationEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F72D1005210B6882009C96B7 /* NCPushNotificationEncryption.m */; };
+		F7425B3B224B8A9B009A3857 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
+		F7425B3C224B8CDD009A3857 /* NCEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F70CAE391F8CF31A008125FD /* NCEndToEndEncryption.m */; };
+		F7425B3D224B8D4D009A3857 /* NCRichDocumentTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7DF219C312D00680748 /* NCRichDocumentTemplate.m */; };
+		F7425B3E224B8D54009A3857 /* OCActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = F70022671EC4C9100080073F /* OCActivity.m */; };
+		F7425B43224B8D73009A3857 /* OCSharedDto.m in Sources */ = {isa = PBXBuildFile; fileRef = F70022791EC4C9100080073F /* OCSharedDto.m */; };
 		F7434B3420E23FD700417916 /* NCDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB41ED5A87C00B7EAD4 /* NCDatabase.swift */; };
 		F7434B3620E23FE000417916 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
 		F7434B3720E23FF200417916 /* NCUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70BFC7320E0FA7C00C67599 /* NCUtility.swift */; };
@@ -243,6 +244,7 @@
 		F745B251222D871800346520 /* QRCodeReader.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F745B250222D871800346520 /* QRCodeReader.framework */; };
 		F745B253222D88AE00346520 /* NCLoginQRCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F745B252222D88AE00346520 /* NCLoginQRCode.swift */; };
 		F747BA1F22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F747BA1E22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard */; };
+		F7499A1C2247AD3A00A7D630 /* IMImagemeterView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7499A1B2247AD3A00A7D630 /* IMImagemeterView.xib */; };
 		F749E4E91DC1FB38009BA2FD /* Share.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
 		F74E432620B5547700C2E54C /* NCNetworkingEndToEnd.m in Sources */ = {isa = PBXBuildFile; fileRef = F74E432520B5547700C2E54C /* NCNetworkingEndToEnd.m */; };
 		F74E432720B5547700C2E54C /* NCNetworkingEndToEnd.m in Sources */ = {isa = PBXBuildFile; fileRef = F74E432520B5547700C2E54C /* NCNetworkingEndToEnd.m */; };
@@ -353,6 +355,8 @@
 		F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
 		F76B3CCF1EAE01BD00921AC9 /* NCBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76B3CCD1EAE01BD00921AC9 /* NCBrand.swift */; };
 		F76C6F8E21943C8C0063591B /* NCActionSheetHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76C6F8D21943C8C0063591B /* NCActionSheetHeader.swift */; };
+		F76E71E52244DF6900690001 /* Zip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F76E71E42244DF6900690001 /* Zip.framework */; };
+		F76E71E72244F48400690001 /* NCViewerImagemeter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76E71E62244F48400690001 /* NCViewerImagemeter.swift */; };
 		F771E3D320E2392D00AFB62D /* FileProviderExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F771E3D220E2392D00AFB62D /* FileProviderExtension.swift */; };
 		F771E3D520E2392D00AFB62D /* FileProviderItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F771E3D420E2392D00AFB62D /* FileProviderItem.swift */; };
 		F771E3D720E2392D00AFB62D /* FileProviderEnumerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F771E3D620E2392D00AFB62D /* FileProviderEnumerator.swift */; };
@@ -544,10 +548,10 @@
 		F7D4238B1F0596C6009C9782 /* ThumbsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D423761F0596C6009C9782 /* ThumbsViewController.m */; };
 		F7D4238C1F0596C6009C9782 /* UIXToolbarView.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D423781F0596C6009C9782 /* UIXToolbarView.m */; };
 		F7D6650720FF341600BFBA9E /* NCMainCommon.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D6650620FF341600BFBA9E /* NCMainCommon.swift */; };
+		F7D7B0D42245271100E6FE36 /* IMImagemeter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7D7B0D32245271100E6FE36 /* IMImagemeter.swift */; };
 		F7DFB7E0219C312D00680748 /* NCRichDocumentTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7DF219C312D00680748 /* NCRichDocumentTemplate.m */; };
 		F7DFB7E1219C312D00680748 /* NCRichDocumentTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7DF219C312D00680748 /* NCRichDocumentTemplate.m */; };
 		F7DFB7E2219C312D00680748 /* NCRichDocumentTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7DF219C312D00680748 /* NCRichDocumentTemplate.m */; };
-		F7DFB7E3219C312D00680748 /* NCRichDocumentTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7DF219C312D00680748 /* NCRichDocumentTemplate.m */; };
 		F7DFB7EB219C5A2E00680748 /* NCCreateMenuAdd.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7EA219C5A2E00680748 /* NCCreateMenuAdd.swift */; };
 		F7DFB7F0219C5B8000680748 /* NCCreateFormUploadAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */; };
 		F7DFB7F2219C5C0000680748 /* NCCreateFormUploadFileText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7F1219C5C0000680748 /* NCCreateFormUploadFileText.swift */; };
@@ -616,11 +620,11 @@
 			remoteGlobalIDString = F71459B41D12E3B700CAFEEC;
 			remoteInfo = "Share Ext Nextcloud";
 		};
-		F72D1011210B6B17009C96B7 /* PBXContainerItemProxy */ = {
+		F7425B2D224B846E009A3857 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = F7F67BA01A24D27800EE80DA /* Project object */;
 			proxyType = 1;
-			remoteGlobalIDString = F72D100B210B6B16009C96B7;
+			remoteGlobalIDString = F7425B27224B846E009A3857;
 			remoteInfo = "Notification Service Extension";
 		};
 		F771E3E920E2392E00AFB62D /* PBXContainerItemProxy */ = {
@@ -651,7 +655,7 @@
 			files = (
 				F771E3EB20E2392E00AFB62D /* File Provider Extension.appex in Embed App Extensions */,
 				F749E4E91DC1FB38009BA2FD /* Share.appex in Embed App Extensions */,
-				F72D1013210B6B17009C96B7 /* Notification Service Extension.appex in Embed App Extensions */,
+				F7425B2F224B846E009A3857 /* Notification Service Extension.appex in Embed App Extensions */,
 			);
 			name = "Embed App Extensions";
 			runOnlyForDeploymentPostprocessing = 0;
@@ -785,9 +789,6 @@
 		F72D1004210B6835009C96B7 /* Firebase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Firebase.h; sourceTree = "<group>"; };
 		F72D1005210B6882009C96B7 /* NCPushNotificationEncryption.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NCPushNotificationEncryption.m; sourceTree = "<group>"; };
 		F72D1006210B6882009C96B7 /* NCPushNotificationEncryption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCPushNotificationEncryption.h; sourceTree = "<group>"; };
-		F72D100C210B6B16009C96B7 /* Notification Service Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Notification Service Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
-		F72D100E210B6B17009C96B7 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
-		F72D1019210B7394009C96B7 /* NotificationServiceExtension-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NotificationServiceExtension-Bridging-Header.h"; sourceTree = "<group>"; };
 		F72E0B9C21AD60BC00898D7B /* WeScan.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WeScan.framework; path = Carthage/Build/iOS/WeScan.framework; sourceTree = "<group>"; };
 		F73049B81CB567F000C7C320 /* NSString+TruncateToWidth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+TruncateToWidth.h"; sourceTree = "<group>"; };
 		F73049B91CB567F000C7C320 /* NSString+TruncateToWidth.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+TruncateToWidth.m"; sourceTree = "<group>"; };
@@ -888,6 +889,9 @@
 		F73D71631F2674A400E233EB /* NCText.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCText.storyboard; sourceTree = "<group>"; };
 		F73F537E1E929C8500F8678D /* CCMore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CCMore.swift; sourceTree = "<group>"; };
 		F7417DB2216CE925007D05F5 /* NCTrashSectionHeaderFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCTrashSectionHeaderFooter.swift; sourceTree = "<group>"; };
+		F7425B28224B846E009A3857 /* Notification Service Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Notification Service Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
+		F7425B2A224B846E009A3857 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
+		F7425B33224B84BA009A3857 /* NotificationServiceExtension-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NotificationServiceExtension-Bridging-Header.h"; sourceTree = "<group>"; };
 		F7434B5F20E2440600417916 /* FileProviderExtension-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FileProviderExtension-Bridging-Header.h"; sourceTree = "<group>"; };
 		F743B2C31C95BBE8006F5B4A /* CCShareInfoCMOC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCShareInfoCMOC.h; sourceTree = "<group>"; };
 		F743B2C41C95BBE8006F5B4A /* CCShareInfoCMOC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCShareInfoCMOC.m; sourceTree = "<group>"; };
@@ -896,6 +900,7 @@
 		F747BA1E22354D2000971601 /* NCCreateFormUploadVoiceNote.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCCreateFormUploadVoiceNote.storyboard; sourceTree = "<group>"; };
 		F7496B81208F5651004B299C /* iOSClient.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = iOSClient.plist; sourceTree = "<group>"; };
 		F7496B83208F5652004B299C /* Share.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Share.plist; sourceTree = "<group>"; };
+		F7499A1B2247AD3A00A7D630 /* IMImagemeterView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IMImagemeterView.xib; sourceTree = "<group>"; };
 		F74D3DBD1BAC1941000BAE4B /* OCNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCNetworking.h; sourceTree = "<group>"; };
 		F74D3DBE1BAC1941000BAE4B /* OCNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCNetworking.m; sourceTree = "<group>"; };
 		F74E432420B5547700C2E54C /* NCNetworkingEndToEnd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCNetworkingEndToEnd.h; sourceTree = "<group>"; };
@@ -1143,6 +1148,8 @@
 		F76C3B871C638A4C00DC4301 /* CCError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCError.h; sourceTree = "<group>"; };
 		F76C3B881C638A4C00DC4301 /* CCError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCError.m; sourceTree = "<group>"; };
 		F76C6F8D21943C8C0063591B /* NCActionSheetHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActionSheetHeader.swift; sourceTree = "<group>"; };
+		F76E71E42244DF6900690001 /* Zip.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Zip.framework; path = Carthage/Build/iOS/Zip.framework; sourceTree = "<group>"; };
+		F76E71E62244F48400690001 /* NCViewerImagemeter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerImagemeter.swift; sourceTree = "<group>"; };
 		F76F23321ED4600700C40023 /* Share-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Share-Bridging-Header.h"; sourceTree = "<group>"; };
 		F771E3D020E2392D00AFB62D /* File Provider Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "File Provider Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
 		F771E3D220E2392D00AFB62D /* FileProviderExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProviderExtension.swift; sourceTree = "<group>"; };
@@ -1389,6 +1396,7 @@
 		F7D5328F1F5D443B006568B1 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F7D532A41F5D4461006568B1 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F7D6650620FF341600BFBA9E /* NCMainCommon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMainCommon.swift; sourceTree = "<group>"; };
+		F7D7B0D32245271100E6FE36 /* IMImagemeter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IMImagemeter.swift; sourceTree = "<group>"; };
 		F7DE9AB01F482FA5008DFE10 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
 		F7DFB7DE219C312D00680748 /* NCRichDocumentTemplate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCRichDocumentTemplate.h; sourceTree = "<group>"; };
 		F7DFB7DF219C312D00680748 /* NCRichDocumentTemplate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCRichDocumentTemplate.m; sourceTree = "<group>"; };
@@ -1488,12 +1496,12 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		F72D1009210B6B16009C96B7 /* Frameworks */ = {
+		F7425B25224B846E009A3857 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				F72D1041210B77ED009C96B7 /* libssl.a in Frameworks */,
-				F72D1040210B77EA009C96B7 /* libcrypto.a in Frameworks */,
+				F7425B36224B872B009A3857 /* libcrypto.a in Frameworks */,
+				F7425B35224B871B009A3857 /* libssl.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1549,6 +1557,7 @@
 				F72D1001210B6638009C96B7 /* FirebaseCoreDiagnostics.framework in Frameworks */,
 				F72D0FFA210B6638009C96B7 /* FirebaseMessaging.framework in Frameworks */,
 				F72D0FFC210B6638009C96B7 /* FirebaseAnalytics.framework in Frameworks */,
+				F76E71E52244DF6900690001 /* Zip.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1832,15 +1841,6 @@
 			path = Analytics;
 			sourceTree = "<group>";
 		};
-		F72D100D210B6B17009C96B7 /* Notification Service Extension */ = {
-			isa = PBXGroup;
-			children = (
-				F72D100E210B6B17009C96B7 /* NotificationService.swift */,
-				F72D1019210B7394009C96B7 /* NotificationServiceExtension-Bridging-Header.h */,
-			);
-			path = "Notification Service Extension";
-			sourceTree = "<group>";
-		};
 		F7381ED9218218A4000B1560 /* Offline */ = {
 			isa = PBXGroup;
 			children = (
@@ -1961,6 +1961,15 @@
 			path = Text;
 			sourceTree = "<group>";
 		};
+		F7425B29224B846E009A3857 /* Notification Service Extension */ = {
+			isa = PBXGroup;
+			children = (
+				F7425B33224B84BA009A3857 /* NotificationServiceExtension-Bridging-Header.h */,
+				F7425B2A224B846E009A3857 /* NotificationService.swift */,
+			);
+			path = "Notification Service Extension";
+			sourceTree = "<group>";
+		};
 		F74D3DB81BAC1941000BAE4B /* Networking */ = {
 			isa = PBXGroup;
 			children = (
@@ -2420,6 +2429,7 @@
 			isa = PBXGroup;
 			children = (
 				F790110D21415BF600D7B136 /* NCViewerRichdocument.swift */,
+				F76E71E62244F48400690001 /* NCViewerImagemeter.swift */,
 				F7FB1D3D215E191D00D669EA /* NCViewerDocumentWeb.swift */,
 				F79630ED215527D40015EEA5 /* NCViewerMedia.swift */,
 			);
@@ -2780,6 +2790,15 @@
 			path = Sources;
 			sourceTree = "<group>";
 		};
+		F7D7B0D52245377800E6FE36 /* Imagemeter */ = {
+			isa = PBXGroup;
+			children = (
+				F7D7B0D32245271100E6FE36 /* IMImagemeter.swift */,
+				F7499A1B2247AD3A00A7D630 /* IMImagemeterView.xib */,
+			);
+			path = Imagemeter;
+			sourceTree = "<group>";
+		};
 		F7DFB7E9219C5A0500680748 /* Create cloud */ = {
 			isa = PBXGroup;
 			children = (
@@ -2910,13 +2929,13 @@
 			children = (
 				F7F67BAA1A24D27800EE80DA /* iOSClient */,
 				F7F67BAB1A24D27800EE80DA /* Supporting Files */,
-				F7C0F46D1C8880540059EC54 /* Share */,
 				F771E3D120E2392D00AFB62D /* File Provider Extension */,
-				F72D100D210B6B17009C96B7 /* Notification Service Extension */,
+				F7C0F46D1C8880540059EC54 /* Share */,
+				F7425B29224B846E009A3857 /* Notification Service Extension */,
 				F7FC7D651DC1F98700BB2C6A /* Products */,
 				F7FC7D541DC1F93700BB2C6A /* Frameworks */,
 				F771E3D020E2392D00AFB62D /* File Provider Extension.appex */,
-				F72D100C210B6B16009C96B7 /* Notification Service Extension.appex */,
+				F7425B28224B846E009A3857 /* Notification Service Extension.appex */,
 			);
 			sourceTree = "<group>";
 		};
@@ -2925,17 +2944,18 @@
 			children = (
 				F70F02A81C889183008DAB36 /* Libraries external */,
 				F70022561EC4C9100080073F /* OCCommunicationLib */,
+				F7C1CDD91E6DFC6F005D92BE /* Brand */,
+				F70211F31BAC56E9003FC03E /* Main */,
 				F7A582D71A24DAB500E903D7 /* AppDelegate.h */,
 				F7A582D61A24DAB500E903D7 /* AppDelegate.m */,
 				F7C8C1901B482CEA0048180E /* CCGlobal.h */,
 				F7F67BB81A24D27800EE80DA /* Images.xcassets */,
-				F70211F31BAC56E9003FC03E /* Main */,
-				F7C1CDD91E6DFC6F005D92BE /* Brand */,
-				F79630EC215526B60015EEA5 /* Viewer */,
-				F7B0C1701EE8397E0033AC24 /* AutoUpload */,
 				F7A321621E9E37960069AD1B /* Activity */,
+				F7E0E1DA22327885006B0911 /* AudioRecorder */,
+				F7B0C1701EE8397E0033AC24 /* AutoUpload */,
 				F7BAAD951ED5A63D00B7EAD4 /* Database */,
 				F7A3214D1E9E2A070069AD1B /* Favorites */,
+				F7D7B0D52245377800E6FE36 /* Imagemeter */,
 				F7F54CAC1E5B143100E19C62 /* Library */,
 				F7BFFA621A24D7300044ED85 /* Login */,
 				F7BFCCBD1B68C21900548E76 /* ManageLocation+ManageAsset */,
@@ -2946,19 +2966,19 @@
 				F7C5259A1E3B441D00FFE02C /* Notification */,
 				F7381ED9218218A4000B1560 /* Offline */,
 				F7FCFFD51D70798C000E6E29 /* PeekPop */,
+				F758B41E212C516300515F55 /* Scan */,
 				F7FE125B1BAC03FB0041924B /* Security */,
 				F79A65C12191D8DC00FF6DCC /* Select */,
 				F7ACE4281BAC0268006C0017 /* Settings */,
 				F728CE741BF6322C00E69702 /* Share */,
-				F758B41E212C516300515F55 /* Scan */,
 				F7169A161EE590930086BD69 /* Shares */,
 				F7B0C0CA1EE7E7750033AC24 /* Synchronize */,
 				F73D71561F26739100E233EB /* Text */,
-				F78F74322163753B00C2ADAD /* Trash */,
 				F7E9C41320F4CA870040CF18 /* Transfers */,
+				F78F74322163753B00C2ADAD /* Trash */,
 				F70784811A2C8A0D00AC9FFF /* UploadFromOtherUpp */,
-				F7E0E1DA22327885006B0911 /* AudioRecorder */,
 				F7BFFA991A24D7BB0044ED85 /* Utility */,
+				F79630EC215526B60015EEA5 /* Viewer */,
 			);
 			path = iOSClient;
 			sourceTree = "<group>";
@@ -2996,6 +3016,7 @@
 		F7FC7D541DC1F93700BB2C6A /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				F76E71E42244DF6900690001 /* Zip.framework */,
 				F745B250222D871800346520 /* QRCodeReader.framework */,
 				F75153232226920200323DDC /* FastScroll.framework */,
 				F78AA20521F783E900D0F205 /* SwiftRichString.framework */,
@@ -3084,13 +3105,13 @@
 			productReference = F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */;
 			productType = "com.apple.product-type.app-extension";
 		};
-		F72D100B210B6B16009C96B7 /* Notification Service Extension */ = {
+		F7425B27224B846E009A3857 /* Notification Service Extension */ = {
 			isa = PBXNativeTarget;
-			buildConfigurationList = F72D1014210B6B17009C96B7 /* Build configuration list for PBXNativeTarget "Notification Service Extension" */;
+			buildConfigurationList = F7425B32224B846E009A3857 /* Build configuration list for PBXNativeTarget "Notification Service Extension" */;
 			buildPhases = (
-				F72D1008210B6B16009C96B7 /* Sources */,
-				F72D1009210B6B16009C96B7 /* Frameworks */,
-				F72D100A210B6B16009C96B7 /* Resources */,
+				F7425B24224B846E009A3857 /* Sources */,
+				F7425B25224B846E009A3857 /* Frameworks */,
+				F7425B26224B846E009A3857 /* Resources */,
 			);
 			buildRules = (
 			);
@@ -3098,7 +3119,7 @@
 			);
 			name = "Notification Service Extension";
 			productName = "Notification Service Extension";
-			productReference = F72D100C210B6B16009C96B7 /* Notification Service Extension.appex */;
+			productReference = F7425B28224B846E009A3857 /* Notification Service Extension.appex */;
 			productType = "com.apple.product-type.app-extension";
 		};
 		F771E3CF20E2392D00AFB62D /* File Provider Extension */ = {
@@ -3136,7 +3157,7 @@
 			dependencies = (
 				F7145A321D12E65F00CAFEEC /* PBXTargetDependency */,
 				F771E3EA20E2392E00AFB62D /* PBXTargetDependency */,
-				F72D1012210B6B17009C96B7 /* PBXTargetDependency */,
+				F7425B2E224B846E009A3857 /* PBXTargetDependency */,
 			);
 			name = Nextcloud;
 			productName = "Crypto Cloud";
@@ -3149,7 +3170,7 @@
 		F7F67BA01A24D27800EE80DA /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastSwiftUpdateCheck = 0940;
+				LastSwiftUpdateCheck = 1010;
 				LastUpgradeCheck = 1010;
 				ORGANIZATIONNAME = TWS;
 				TargetAttributes = {
@@ -3165,10 +3186,9 @@
 							};
 						};
 					};
-					F72D100B210B6B16009C96B7 = {
-						CreatedOnToolsVersion = 9.4.1;
+					F7425B27224B846E009A3857 = {
+						CreatedOnToolsVersion = 10.1;
 						DevelopmentTeam = 6JLRKY9ZV7;
-						LastSwiftMigration = 1000;
 						ProvisioningStyle = Automatic;
 						SystemCapabilities = {
 							com.apple.ApplicationGroups.iOS = {
@@ -3255,7 +3275,7 @@
 				F77B0DEB1D118A16002130FE /* Nextcloud */,
 				F71459B41D12E3B700CAFEEC /* Share */,
 				F771E3CF20E2392D00AFB62D /* File Provider Extension */,
-				F72D100B210B6B16009C96B7 /* Notification Service Extension */,
+				F7425B27224B846E009A3857 /* Notification Service Extension */,
 			);
 		};
 /* End PBXProject section */
@@ -3274,7 +3294,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		F72D100A210B6B16009C96B7 /* Resources */ = {
+		F7425B26224B846E009A3857 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
@@ -3388,6 +3408,7 @@
 				F7F54CFB1E5B14C700E19C62 /* UIBarButtonItemArrowLeft@2x.png in Resources */,
 				F7C525A21E3B6DA800FFE02C /* CCNotification.storyboard in Resources */,
 				F7F54CEB1E5B14C700E19C62 /* ImageSelectedOn.png in Resources */,
+				F7499A1C2247AD3A00A7D630 /* IMImagemeterView.xib in Resources */,
 				F72D1003210B67CE009C96B7 /* GoogleService-Info.plist in Resources */,
 				F762CB951EACB84400B38484 /* icon-error.png in Resources */,
 				F7F54CF01E5B14C700E19C62 /* ImageSelectedSmallOff@3x.png in Resources */,
@@ -3470,6 +3491,7 @@
 				"$(SRCROOT)/Carthage/Build/iOS/SwiftRichString.framework",
 				"$(SRCROOT)/Carthage/Build/iOS/FastScroll.framework",
 				"$(SRCROOT)/Carthage/Build/iOS/QRCodeReader.framework",
+				"$(SRCROOT)/Carthage/Build/iOS/Zip.framework",
 			);
 			outputPaths = (
 			);
@@ -3562,20 +3584,20 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		F72D1008210B6B16009C96B7 /* Sources */ = {
+		F7425B24224B846E009A3857 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				F72D103C210B777F009C96B7 /* NCBrand.swift in Sources */,
-				F7DFB7E3219C312D00680748 /* NCRichDocumentTemplate.m in Sources */,
-				F72D101A210B7473009C96B7 /* CCUtility.m in Sources */,
-				F72D100F210B6B17009C96B7 /* NotificationService.swift in Sources */,
-				F72D103A210B769E009C96B7 /* NCDatabase.swift in Sources */,
-				F72D103D210B7796009C96B7 /* OCSharedDto.m in Sources */,
-				F72D103F210B77B8009C96B7 /* NCPushNotificationEncryption.m in Sources */,
-				F72D103E210B77A5009C96B7 /* OCActivity.m in Sources */,
-				F72D1042210B783D009C96B7 /* NCEndToEndEncryption.m in Sources */,
-				F72D103B210B76A1009C96B7 /* NCManageDatabase.swift in Sources */,
+				F7425B3B224B8A9B009A3857 /* NCBrand.swift in Sources */,
+				F7425B3D224B8D4D009A3857 /* NCRichDocumentTemplate.m in Sources */,
+				F7425B39224B89FE009A3857 /* CCUtility.m in Sources */,
+				F7425B2B224B846E009A3857 /* NotificationService.swift in Sources */,
+				F7425B37224B89D2009A3857 /* NCDatabase.swift in Sources */,
+				F7425B43224B8D73009A3857 /* OCSharedDto.m in Sources */,
+				F7425B3A224B8A23009A3857 /* NCPushNotificationEncryption.m in Sources */,
+				F7425B3E224B8D54009A3857 /* OCActivity.m in Sources */,
+				F7425B3C224B8CDD009A3857 /* NCEndToEndEncryption.m in Sources */,
+				F7425B38224B89D6009A3857 /* NCManageDatabase.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3700,6 +3722,7 @@
 				F7DFB7F0219C5B8000680748 /* NCCreateFormUploadAssets.swift in Sources */,
 				F762CB0C1EACB66200B38484 /* XLFormSectionDescriptor.m in Sources */,
 				F760F79421F21F61006B1A73 /* ResizeControl.swift in Sources */,
+				F76E71E72244F48400690001 /* NCViewerImagemeter.swift in Sources */,
 				F77B0E131D118A16002130FE /* AppDelegate.m in Sources */,
 				F7DFB7F2219C5C0000680748 /* NCCreateFormUploadFileText.swift in Sources */,
 				F762CB861EACB81000B38484 /* RECommonFunctions.m in Sources */,
@@ -3859,6 +3882,7 @@
 				F760F78A21F21F61006B1A73 /* UIImage+Size.swift in Sources */,
 				F70022B31EC4C9100080073F /* OCActivity.m in Sources */,
 				F734A8BF21B59137009DE2E8 /* WKCookieWebView.swift in Sources */,
+				F7D7B0D42245271100E6FE36 /* IMImagemeter.swift in Sources */,
 				F70022D41EC4C9100080073F /* NSDate+ISO8601.m in Sources */,
 				F762CB151EACB66200B38484 /* XLFormRowNavigationAccessoryView.m in Sources */,
 				F762CB0A1EACB66200B38484 /* XLFormDescriptor.m in Sources */,
@@ -3936,10 +3960,10 @@
 			target = F71459B41D12E3B700CAFEEC /* Share */;
 			targetProxy = F7145A311D12E65F00CAFEEC /* PBXContainerItemProxy */;
 		};
-		F72D1012210B6B17009C96B7 /* PBXTargetDependency */ = {
+		F7425B2E224B846E009A3857 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
-			target = F72D100B210B6B16009C96B7 /* Notification Service Extension */;
-			targetProxy = F72D1011210B6B17009C96B7 /* PBXContainerItemProxy */;
+			target = F7425B27224B846E009A3857 /* Notification Service Extension */;
+			targetProxy = F7425B2D224B846E009A3857 /* PBXContainerItemProxy */;
 		};
 		F771E3EA20E2392E00AFB62D /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
@@ -4091,7 +4115,7 @@
 			};
 			name = Release;
 		};
-		F72D1015210B6B17009C96B7 /* Debug */ = {
+		F7425B30224B846E009A3857 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
@@ -4127,11 +4151,9 @@
 				INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/Notification_Service_Extension.plist";
 				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
-				LIBRARY_SEARCH_PATHS = (
-					"$(inherited)",
-					"\"Libraries external\"/**",
-				);
-				OTHER_LDFLAGS = "-ObjC";
+				LIBRARY_SEARCH_PATHS = "\"Libraries external\"/**";
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SKIP_INSTALL = YES;
@@ -4143,7 +4165,7 @@
 			};
 			name = Debug;
 		};
-		F72D1016210B6B17009C96B7 /* Release */ = {
+		F7425B31224B846E009A3857 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
@@ -4178,11 +4200,8 @@
 				INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/Notification_Service_Extension.plist";
 				IPHONEOS_DEPLOYMENT_TARGET = 10.0;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
-				LIBRARY_SEARCH_PATHS = (
-					"$(inherited)",
-					"\"Libraries external\"/**",
-				);
-				OTHER_LDFLAGS = "-ObjC";
+				LIBRARY_SEARCH_PATHS = "\"Libraries external\"/**";
+				MTL_FAST_MATH = YES;
 				PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SKIP_INSTALL = YES;
@@ -4502,11 +4521,11 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		F72D1014210B6B17009C96B7 /* Build configuration list for PBXNativeTarget "Notification Service Extension" */ = {
+		F7425B32224B846E009A3857 /* Build configuration list for PBXNativeTarget "Notification Service Extension" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
-				F72D1015210B6B17009C96B7 /* Debug */,
-				F72D1016210B6B17009C96B7 /* Release */,
+				F7425B30224B846E009A3857 /* Debug */,
+				F7425B31224B846E009A3857 /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;

+ 28 - 29
Notification Service Extension/NotificationService.swift

@@ -25,7 +25,6 @@ import UserNotifications
 
 class NotificationService: UNNotificationServiceExtension {
 
-    let privateKey = CCUtility.getPushNotificationPrivateKey()
     var contentHandler: ((UNNotificationContent) -> Void)?
     var bestAttemptContent: UNMutableNotificationContent?
 
@@ -39,39 +38,40 @@ class NotificationService: UNNotificationServiceExtension {
             bestAttemptContent.title = ""
             bestAttemptContent.body = "Nextcloud notification"
             
-            let message = bestAttemptContent.userInfo["subject"] as! String
-            
-            guard let privateKey = CCUtility.getPushNotificationPrivateKey() else {
-                contentHandler(bestAttemptContent)
-                return
-            }
-            
-            guard let decryptedMessage = NCPushNotificationEncryption.sharedInstance().decryptPushNotification(message, withDevicePrivateKey: privateKey) else {
-                contentHandler(bestAttemptContent)
-                return
-            }
-            
-            guard let data = decryptedMessage.data(using: .utf8) else {
+            guard let message = bestAttemptContent.userInfo["subject"] else {
                 contentHandler(bestAttemptContent)
                 return
             }
             
-            do {
-                let json = try JSONSerialization.jsonObject(with: data) as! [String:AnyObject]
-                if let app = json["app"] as? String {
-                    if app == "spreed" {
-                        bestAttemptContent.title = "Nextcloud Talk"
-                    } else {
-                        bestAttemptContent.title = app.capitalized
-                    }
+            for result in NCManageDatabase.sharedInstance.getAllAccount() {
+                guard let privateKey = CCUtility.getPushNotificationPrivateKey(result.account) else {
+                    continue
+                }
+                guard let decryptedMessage = NCPushNotificationEncryption.sharedInstance()?.decryptPushNotification(message as? String, withDevicePrivateKey: privateKey) else {
+                    continue
                 }
-                if let subject = json["subject"] as? String {
-                    bestAttemptContent.body = subject
+                guard let data = decryptedMessage.data(using: .utf8) else {
+                    contentHandler(bestAttemptContent)
+                    return
+                }
+                
+                do {
+                    let json = try JSONSerialization.jsonObject(with: data) as! [String:AnyObject]
+                    if let app = json["app"] as? String {
+                        if app == "spreed" {
+                            bestAttemptContent.title = "Nextcloud Talk"
+                        } else {
+                            bestAttemptContent.title = app.capitalized
+                        }
+                    }
+                    if let subject = json["subject"] as? String {
+                        bestAttemptContent.body = subject
+                    }
+                } catch let error as NSError {
+                    print("Failed : \(error.localizedDescription)")
                 }
-            } catch let error as NSError {
-                print("Failed : \(error.localizedDescription)")
             }
-          
+            
             contentHandler(bestAttemptContent)
         }
     }
@@ -81,10 +81,9 @@ class NotificationService: UNNotificationServiceExtension {
         if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
             
             bestAttemptContent.title = ""
-            bestAttemptContent.body = "Nextcloud notification"
+            bestAttemptContent.body = "Nextcloud"
             
             contentHandler(bestAttemptContent)
         }
     }
-
 }

+ 7 - 7
Notification Service Extension/NotificationServiceExtension-Bridging-Header.h

@@ -23,6 +23,7 @@
 
 #import <Foundation/Foundation.h>
 #import <UserNotifications/UserNotifications.h>
+#import <PushKit/PushKit.h>
 
 #import "BKPasscodeLockScreenManager.h"
 #import "REMenu.h"
@@ -40,7 +41,7 @@
 @class CCMore;
 @class NCMedia;
 
-@interface AppDelegate : UIResponder <UIApplicationDelegate, BKPasscodeLockScreenManagerDelegate, BKPasscodeViewControllerDelegate, TWMessageBarStyleSheet, CCNetworkingDelegate>
+@interface AppDelegate : UIResponder <UIApplicationDelegate, BKPasscodeLockScreenManagerDelegate, BKPasscodeViewControllerDelegate, TWMessageBarStyleSheet, CCNetworkingDelegate, PKPushRegistryDelegate>
 
 // Timer Process
 @property (nonatomic, strong) NSTimer *timerProcessAutoDownloadUpload;
@@ -82,6 +83,9 @@
 @property (nonatomic, strong) AVPlayer *player;
 @property (nonatomic, strong) AVPlayerViewController *playerController;
 
+// Push Norification Token
+@property (nonatomic, strong) NSString *pushKitToken;
+
 // Remenu
 @property (nonatomic, strong) REMenu *reMainMenu;
 @property (nonatomic, strong) REMenuItem *selezionaItem;
@@ -127,10 +131,6 @@
 
 @property (nonatomic, strong) NSMutableArray *sessionPendingStatusInUpload;
 
-@property (nonatomic, strong) NSString *pnDeviceIdentifier;
-@property (nonatomic, strong) NSString *pnDeviceIdentifierSignature;
-@property (nonatomic, strong) NSString *pnPublicKey;
-
 // Maintenance Mode
 @property BOOL maintenanceMode;
 
@@ -160,8 +160,8 @@
 - (NSString *)getTabBarControllerActiveServerUrl;
 
 // Push Notification
-- (void)subscribingNextcloudServerPushNotification;
-- (void)unsubscribingNextcloudServerPushNotification;
+- (void)pushNotification;
+- (void)unsubscribingNextcloudServerPushNotification:(NSString *)account url:(NSString *)url withSubscribing:(BOOL)subscribing;
 
 // Theming Color
 - (void)settingThemingColorBrand;

+ 198 - 62
iOSClient/AppDelegate.m

@@ -38,7 +38,9 @@
 #import "NCPushNotificationEncryption.h"
 
 @interface AppDelegate () <UNUserNotificationCenterDelegate, FIRMessagingDelegate>
-
+{
+PKPushRegistry *pushRegistry;
+}
 @end
 
 @implementation AppDelegate
@@ -147,12 +149,19 @@
     self.listProgressMetadata = [[NSMutableDictionary alloc] init];
     self.listMainVC = [[NSMutableDictionary alloc] init];
     
+    /*
     // Firebase - Push Notification
     @try {
         [FIRApp configure];
     } @catch (NSException *exception) {
         NSLog(@"[LOG] Something went wrong while configuring Firebase");
     }
+    */
+    
+    // Push Notification
+    pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
+    pushRegistry.delegate = self;
+    pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
     
     // Display notification (sent via APNS)
     [UNUserNotificationCenter currentNotificationCenter].delegate = self;
@@ -178,10 +187,11 @@
     // [[AVAudioSession sharedInstance] setActive:YES error:nil];
     [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
     
-    // How to hide UINavigationBar 1px bottom line < iOS 11
+    // APPEARANCE: How to hide UINavigationBar 1px bottom line < iOS 11
     [[UINavigationBar appearance] setBackgroundImage:[[UIImage alloc] init] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
     [[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];
-    
+    [UINavigationBar appearance].translucent = NO;
+
     // passcode
     [[BKPasscodeLockScreenManager sharedManager] setDelegate:self];
     
@@ -392,32 +402,50 @@
 }
 
 #pragma --------------------------------------------------------------------------------------------
-#pragma mark ===== Push Notification =====
+#pragma mark ===== PushNotification & PushKit Delegate =====
 #pragma --------------------------------------------------------------------------------------------
 
-- (void)subscribingNextcloudServerPushNotification
+- (void)pushNotification
 {
     // test
-    if (self.activeAccount.length == 0 || self.maintenanceMode)
+    if (self.activeAccount.length == 0 || self.maintenanceMode || self.pushKitToken.length == 0)
         return;
     
-    [[NCPushNotificationEncryption sharedInstance] generatePushNotificationsKeyPair];
+    NSString *token = [CCUtility getPushNotificationToken:self.activeAccount];
+    
+    if (![token isEqualToString:self.pushKitToken]) {
+        if (token != nil) {
+            // unsubscribing + subscribing
+            [self unsubscribingNextcloudServerPushNotification:self.activeAccount url:self.activeUrl withSubscribing:true];
+        } else {
+            [self subscribingNextcloudServerPushNotification:self.activeAccount url:self.activeUrl];
+        }
+    }
+}
 
-    NSString *pushToken = [CCUtility getPushNotificationToken];
-    NSString *pushTokenHash = [[NCEndToEndEncryption sharedManager] createSHA512:pushToken];
-    NSString *devicePublicKey = [[NSString alloc] initWithData:[NCPushNotificationEncryption sharedInstance].ncPNPublicKey encoding:NSUTF8StringEncoding];
+- (void)subscribingNextcloudServerPushNotification:(NSString *)account url:(NSString *)url
+{
+    // test
+    if (self.activeAccount.length == 0 || self.maintenanceMode || self.pushKitToken.length == 0)
+        return;
     
-    self.pnDeviceIdentifier = nil;
-    self.pnDeviceIdentifierSignature = nil;
-    self.pnPublicKey = nil;
+    [[NCPushNotificationEncryption sharedInstance] generatePushNotificationsKeyPair:account];
 
-    [[OCNetworking sharedManager] subscribingPushNotificationWithAccount:self.activeAccount url:self.activeUrl pushToken:pushToken Hash:pushTokenHash devicePublicKey:devicePublicKey completion:^(NSString *account, NSString *deviceIdentifier, NSString *deviceIdentifierSignature, NSString *publicKey, NSString *message, NSInteger errorCode) {
+    NSString *pushTokenHash = [[NCEndToEndEncryption sharedManager] createSHA512:self.pushKitToken];
+    NSData *pushPublicKey = [CCUtility getPushNotificationPublicKey:account];
+    NSString *pushDevicePublicKey = [[NSString alloc] initWithData:pushPublicKey encoding:NSUTF8StringEncoding];
+    
+    [[OCNetworking sharedManager] subscribingPushNotificationWithAccount:account url:url pushToken:self.pushKitToken Hash:pushTokenHash devicePublicKey:pushDevicePublicKey completion:^(NSString *accountCompletion, NSString *deviceIdentifier, NSString *deviceIdentifierSignature, NSString *publicKey, NSString *message, NSInteger errorCode) {
         
-        if (errorCode == 0 && [account isEqualToString:self.activeAccount]) {
+        if (errorCode == 0 && [accountCompletion isEqualToString:account]) {
+            
             NSLog(@"[LOG] Subscribed to Push Notification server & proxy successfully.");
-            self.pnDeviceIdentifier = deviceIdentifier;
-            self.pnDeviceIdentifierSignature = deviceIdentifierSignature;
-            self.pnPublicKey = publicKey;
+            
+            [CCUtility setPushNotificationToken:account token:self.pushKitToken];
+            [CCUtility setPushNotificationDeviceIdentifier:account deviceIdentifier:deviceIdentifier];
+            [CCUtility setPushNotificationDeviceIdentifierSignature:account deviceIdentifierSignature:deviceIdentifierSignature];
+            [CCUtility setPushNotificationSubscribingPublicKey:account publicKey:publicKey];
+            
         } else if (errorCode != 0) {
             NSLog(@"[LOG] Subscribed to Push Notification server & proxy error.");
         } else {
@@ -426,16 +454,33 @@
     }];
 }
 
-- (void)unsubscribingNextcloudServerPushNotification
+- (void)unsubscribingNextcloudServerPushNotification:(NSString *)account url:(NSString *)url withSubscribing:(BOOL)subscribing
 {
     // test
     if (self.activeAccount.length == 0 || self.maintenanceMode)
         return;
     
-    [[OCNetworking sharedManager] unsubscribingPushNotificationWithAccount:self.activeAccount url:self.activeUrl deviceIdentifier:self.pnDeviceIdentifier deviceIdentifierSignature:self.pnDeviceIdentifierSignature publicKey:self.pnPublicKey completion:^(NSString *account, NSString *message, NSInteger errorCode) {
+    NSString *deviceIdentifier = [CCUtility getPushNotificationDeviceIdentifier:account];
+    NSString *deviceIdentifierSignature = [CCUtility getPushNotificationDeviceIdentifierSignature:account];
+    NSString *publicKey = [CCUtility getPushNotificationSubscribingPublicKey:account];
+
+    [[OCNetworking sharedManager] unsubscribingPushNotificationWithAccount:account url:url deviceIdentifier:deviceIdentifier deviceIdentifierSignature:deviceIdentifierSignature publicKey:publicKey completion:^(NSString *account, NSString *message, NSInteger errorCode) {
        
         if (errorCode == 0) {
+            
             NSLog(@"[LOG] Unsubscribed to Push Notification server & proxy successfully.");
+            
+            [CCUtility setPushNotificationPublicKey:account data:nil];
+            [CCUtility setPushNotificationSubscribingPublicKey:account publicKey:nil];
+            [CCUtility setPushNotificationPrivateKey:account data:nil];
+            [CCUtility setPushNotificationToken:account token:nil];
+            [CCUtility setPushNotificationDeviceIdentifier:account deviceIdentifier:nil];
+            [CCUtility setPushNotificationDeviceIdentifierSignature:account deviceIdentifierSignature:nil];
+            
+            if (self.pushKitToken != nil && subscribing) {
+                [self subscribingNextcloudServerPushNotification:account url:url];
+            }
+            
         } else if (errorCode != 0) {
             NSLog(@"[LOG] Unsubscribed to Push Notification server & proxy error.");
         } else {
@@ -452,68 +497,159 @@
 
 -(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response withCompletionHandler:(nonnull void (^)(void))completionHandler
 {
-    /*
-    NSString *message = [response.notification.request.content.userInfo objectForKey:@"subject"];
+    completionHandler();
+}
+
+/*
+- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
+{
+    NSLog(@"Push notification: %@", userInfo);
     
-    if (message && [NCPushNotificationEncryption sharedInstance].ncPNPrivateKey) {
-        
-        NSData *privateKey = [CCUtility getPushNotificationPrivateKey];
-        NSString *decryptedMessage = [[NCPushNotificationEncryption sharedInstance] decryptPushNotification:message withDevicePrivateKey:privateKey];
-        if (decryptedMessage) {
-           
-            NSData *data = [decryptedMessage dataUsingEncoding:NSUTF8StringEncoding];
-            NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
-            NSString *app = [json objectForKey:@"app"];
-            
-            if ([app isEqualToString:@"spreed"] == NO) {
-                
-                UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
-                UINavigationController *navigationControllerMore;
-                UITabBarController *tabBarController;
-                
-                if (splitViewController.isCollapsed) {
+    NSUInteger fetchResult = UIBackgroundFetchResultNoData;
+    NSString *message = [userInfo objectForKey:@"subject"];
+    
+    if (message) {
+        for (tableAccount *result in  [[NCManageDatabase sharedInstance] getAllAccount]) {
+            if ([CCUtility getPushNotificationPrivateKey:result.account]) {
+                NSString *decryptedMessage = [[NCPushNotificationEncryption sharedInstance] decryptPushNotification:message withDevicePrivateKey: [CCUtility getPushNotificationPrivateKey:result.account]];
+                if (decryptedMessage) {
                     
-                    tabBarController = splitViewController.viewControllers.firstObject;
-                    for (UINavigationController *nvc in tabBarController.viewControllers) {
-                        
-                        if ([nvc.topViewController isKindOfClass:[CCDetail class]])
-                            [nvc popToRootViewControllerAnimated:NO];
-                        
-                        if ([nvc.topViewController isKindOfClass:[CCMore class]])
-                            navigationControllerMore = nvc;
+                    UNMutableNotificationContent *content = [UNMutableNotificationContent new];
+                    
+                    NSData *data = [decryptedMessage dataUsingEncoding:NSUTF8StringEncoding];
+                    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
+                    
+                    NSString *app = [json objectForKey:@"app"];
+                    NSString *subject = [json objectForKey:@"subject"];
+                    NSInteger notificationId = [[json objectForKey:@"nid"] integerValue];
+                    
+                    if ([app isEqualToString:@"spreed"]) {
+                        content.title = @"Nextcloud Talk";
+                    } else {
+                        content.title = app.capitalizedString;
                     }
+                    content.title = [NSString stringWithFormat:@"%@ (%@)", content.title, result.account];
                     
-                } else {
+                    if (subject) {
+                        content.body = subject;
+                    } else {
+                        content.body = @"Nextcloud notification";
+                    }
                     
-                    UINavigationController *nvcDetail = splitViewController.viewControllers.lastObject;
-                    [nvcDetail popToRootViewControllerAnimated:NO];
+                    [[OCNetworking sharedManager] getServerNotification:result.url notificationId:notificationId completion:^(NSDictionary *json, NSString *message, NSInteger errorCode) {
+                        //
+                    }];
                     
-                    tabBarController = splitViewController.viewControllers.firstObject;
+                    content.sound = [UNNotificationSound defaultSound];
+                    
+                    NSString *identifier = [NSString stringWithFormat:@"Notification-%@", [NSDate new]];
+                    
+                    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.1 repeats:NO];
+                    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
+                    
+                    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];
+                    
+                    fetchResult = UIBackgroundFetchResultNewData;
+                    break;
                 }
-                
-                if (tabBarController)
-                    [tabBarController setSelectedIndex: k_tabBarApplicationIndexMore];
-                if (navigationControllerMore)
-                    [navigationControllerMore performSegueWithIdentifier:@"segueActivity" sender:navigationControllerMore];
             }
         }
     }
-    */
-    completionHandler();
+    
+    completionHandler(fetchResult);
 }
 
-#pragma FIREBASE
-
 - (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken
 {
+
     // test
     if (self.activeAccount.length == 0 || self.maintenanceMode)
         return;
     
     NSLog(@"FCM registration token: %@", fcmToken);
-    [CCUtility setPushNotificationToken:fcmToken];
     
-    [self subscribingNextcloudServerPushNotification];
+    NSString *token = [CCUtility getPushNotificationToken:self.activeAccount];
+    if (![token isEqualToString:fcmToken]) {
+        if (token != nil) {
+            // unsubscribing + subscribing
+            [self unsubscribingNextcloudServerPushNotification:self.activeAccount url:self.activeUrl token:fcmToken];
+        } else {
+            [self subscribingNextcloudServerPushNotification:self.activeAccount url:self.activeUrl token:fcmToken];
+        }
+    }
+}
+*/
+
+- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type
+{
+    self.pushKitToken = [self stringWithDeviceToken:credentials.token];
+
+    [self pushNotification];
+}
+
+- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type
+{
+    NSString *message = [payload.dictionaryPayload objectForKey:@"subject"];
+    
+    if (message) {
+        for (tableAccount *result in  [[NCManageDatabase sharedInstance] getAllAccount]) {
+            if ([CCUtility getPushNotificationPrivateKey:result.account]) {
+                NSString *decryptedMessage = [[NCPushNotificationEncryption sharedInstance] decryptPushNotification:message withDevicePrivateKey: [CCUtility getPushNotificationPrivateKey:result.account]];
+                if (decryptedMessage) {
+                    
+                    UNMutableNotificationContent *content = [UNMutableNotificationContent new];
+                    
+                    NSData *data = [decryptedMessage dataUsingEncoding:NSUTF8StringEncoding];
+                    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
+                    
+                    NSString *app = [json objectForKey:@"app"];
+                    NSString *subject = [json objectForKey:@"subject"];
+                    NSInteger notificationId = [[json objectForKey:@"nid"] integerValue];
+                    
+                    NSURL *url = [NSURL URLWithString:result.url];
+                    NSString *domain = [url host];
+                    
+                    if ([app isEqualToString:@"spreed"]) {
+                        content.title = @"Nextcloud Talk";
+                    } else {
+                        content.title = app.capitalizedString;
+                    }
+                    content.title = [NSString stringWithFormat:@"%@ - %@ (%@)", content.title, result.displayName, domain];
+                    if (subject) {
+                        content.body = subject;
+                    } else {
+                        content.body = @"Nextcloud notification";
+                    }
+                    content.sound = [UNNotificationSound defaultSound];
+
+                    [[OCNetworking sharedManager] getServerNotification:result.url notificationId:notificationId completion:^(NSDictionary *json, NSString *message, NSInteger errorCode) {
+                        //
+                    }];
+                                        
+                    NSString *identifier = [NSString stringWithFormat:@"Notification-%@", [NSDate new]];
+                    
+                    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.1 repeats:NO];
+                    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
+                    
+                    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];
+                    
+                    break;
+                }
+            }
+        }
+    }
+}
+
+- (NSString *)stringWithDeviceToken:(NSData *)deviceToken
+{
+    const char *data = [deviceToken bytes];
+    NSMutableString *token = [NSMutableString string];
+    
+    for (NSUInteger i = 0; i < [deviceToken length]; i++) {
+        [token appendFormat:@"%02.2hhX", data[i]];
+    }
+    
+    return [token copy];
 }
 
 #pragma --------------------------------------------------------------------------------------------

+ 2 - 2
iOSClient/Brand/File_Provider_Extension.plist

@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>XPC!</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.23.2</string>
+	<string>2.23.3</string>
 	<key>CFBundleVersion</key>
-	<string>10</string>
+	<string>4</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionFileProviderDocumentGroup</key>

+ 7 - 0
iOSClient/Brand/Intro/CCIntro.m

@@ -138,6 +138,13 @@
     
     // Pages
     
+    /*
+    EAIntroPage *page1 = [EAIntroPage pageWithCustomViewFromNibNamed:@"NCIntroPage1"];
+    page1.customView.backgroundColor = [[NCBrandColor sharedInstance] customer];
+    UILabel *titlePage1 = (UILabel *)[page1.customView viewWithTag:1];
+    titlePage1.text = NSLocalizedString(@"_intro_1_title_", nil);
+    */
+    
     EAIntroPage *page1 = [EAIntroPage page];
 
     page1.titleIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"intro1"]];

+ 1 - 1
iOSClient/Brand/NCBridgeSwift.h

@@ -51,6 +51,6 @@
 // Nextcloud Notification Service Extension
 #if defined(EXTENSION_NOTIFICATION_SERVICE)
 
-    #import "Notification_Service_Extension-Swift.h"
+#import "Notification_Service_Extension-Swift.h"
 
 #endif

+ 2 - 2
iOSClient/Brand/Notification_Service_Extension.plist

@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>XPC!</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.23.2</string>
+	<string>2.23.3</string>
 	<key>CFBundleVersion</key>
-	<string>10</string>
+	<string>4</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionPointIdentifier</key>

+ 2 - 2
iOSClient/Brand/Share.plist

@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>XPC!</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.23.2</string>
+	<string>2.23.3</string>
 	<key>CFBundleVersion</key>
-	<string>10</string>
+	<string>4</string>
 	<key>NSAppTransportSecurity</key>
 	<dict>
 		<key>NSAllowsArbitraryLoads</key>

+ 3 - 2
iOSClient/Brand/iOSClient.plist

@@ -46,11 +46,11 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>2.23.2</string>
+	<string>2.23.3</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>10</string>
+	<string>4</string>
 	<key>FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED</key>
 	<true/>
 	<key>Fabric</key>
@@ -107,6 +107,7 @@
 		<string>audio</string>
 		<string>fetch</string>
 		<string>remote-notification</string>
+		<string>voip</string>
 	</array>
 	<key>UIFileSharingEnabled</key>
 	<true/>

+ 1 - 0
iOSClient/CCGlobal.h

@@ -216,6 +216,7 @@
 #define k_metadataTypeFile_image                        @"image"
 #define k_metadataTypeFile_unknown                      @"unknow"
 #define k_metadataTypeFile_video                        @"video"
+#define k_metadataTypeFile_imagemeter                   @"imagemeter"
 
 // TabBar button
 #define k_tabBarApplicationIndexFile                    0

+ 10 - 0
iOSClient/Database/NCManageDatabase.swift

@@ -322,6 +322,16 @@ class NCManageDatabase: NSObject {
         return nil
     }
     
+    @objc func getAllAccount() -> [tableAccount] {
+        
+        let realm = try! Realm()
+        realm.refresh()
+        
+        let results = realm.objects(tableAccount.self)
+        
+        return Array(results.map { tableAccount.init(value:$0) })
+    }
+    
     @objc func getAccountAutoUploadFileName() -> String {
         
         let realm = try! Realm()

+ 2 - 0
iOSClient/Favorites/CCFavorites.m

@@ -339,6 +339,8 @@
         
         viewController.metadata = metadata;
         viewController.imageFile = cell.file.image;
+        viewController.showOpenIn = true;
+        viewController.showShare = false;
         
         return viewController;
     }

+ 201 - 0
iOSClient/Imagemeter/IMImagemeter.swift

@@ -0,0 +1,201 @@
+//
+//  IMImagemeter.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 22/03/2019.
+//  Copyright © 2019 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import Foundation
+
+class IMImagemeterCodable: NSObject {
+    
+    struct imagemeterAnnotation: Codable {
+        
+        struct coordinates: Codable {
+            let x: CGFloat
+            let y: CGFloat
+        }
+        
+        struct color: Codable {
+            let rgba: [Int]
+        }
+        
+        struct end_pt: Codable {
+            let end_pt: coordinates
+            
+            enum CodingKeys : String, CodingKey {
+                case end_pt = "end-pt"
+            }
+        }
+        
+        struct style: Codable {
+            let color: color?
+            let line_width: CGFloat?
+            let text_outline_width: CGFloat?
+            let font_base_size: CGFloat?
+            let font_magnification: CGFloat?
+            
+            enum CodingKeys : String, CodingKey {
+                case color
+                case line_width = "line-width"
+                case text_outline_width = "text-outline-width"
+                case font_base_size = "font-base-size"
+                case font_magnification = "font-magnification"
+            }
+        }
+        
+        struct audio_recording: Codable {
+            let recording_filename: String
+            let recording_duration_msecs: Int
+            
+            enum CodingKeys : String, CodingKey {
+                case recording_filename = "recording-filename"
+                case recording_duration_msecs = "recording-duration-msecs"
+            }
+        }
+        
+        struct capture_timestamp: Codable {
+            let year: Int
+            let month: Int
+            let day: Int
+            let hour: Int
+            let minutes: Int
+            let seconds: Int
+        }
+        
+        struct image: Codable {
+            let title: String
+            let filename: String
+            let annotated_image_filename: String
+            let rotation: Int
+            
+            enum CodingKeys : String, CodingKey {
+                case title
+                case filename
+                case annotated_image_filename = "annotated-image-filename"
+                case rotation
+            }
+        }
+        
+        struct export_image_cache: Codable {
+            let width: CGFloat
+            let height: CGFloat
+            let file_format: String
+            let with_hardware_antialiasing: Bool
+            let with_watermark: Bool
+            let with_image_title: Bool
+            
+            enum CodingKeys : String, CodingKey {
+                case width
+                case height
+                case file_format = "file-format"
+                case with_hardware_antialiasing = "with-hardware-antialiasing"
+                case with_watermark = "with-watermark"
+                case with_image_title = "with-image-title"
+            }
+        }
+        
+        struct elements: Codable {
+            let id: Int
+            let class_: String
+            let center: coordinates
+            let width: CGFloat?
+            let arrows: [end_pt]?
+            let text: String?
+            let audio_recording: audio_recording?
+            let show_border: Bool?
+            let show_arrows: Bool?
+            let fill_background: Bool?
+            let style: style?
+            
+            enum CodingKeys : String, CodingKey {
+                case id
+                case class_ = "class"
+                case center
+                case width
+                case arrows
+                case text
+                case audio_recording = "audio-recording"
+                case show_border = "show-border"
+                case show_arrows = "show-arrows"
+                case fill_background = "fill-background"
+                case style
+            }
+        }
+        
+        struct thumbnails: Codable {
+            let filename: String
+            let width: CGFloat
+            let height: CGFloat
+        }
+        
+        let is_example_image: Bool
+        let version: Int
+        let capture_timestamp: capture_timestamp
+        let image: image
+        let export_image_cache: [export_image_cache]
+        let elements: [elements]?
+        let id: String
+        let thumbnails: [thumbnails]
+        let last_modification: Int
+        
+        enum CodingKeys : String, CodingKey {
+            case is_example_image = "is-example-image"
+            case version
+            case capture_timestamp = "capture-timestamp"
+            case image
+            case export_image_cache = "export-image-cache"
+            case elements
+            case id
+            case thumbnails
+            case last_modification = "last-modification"
+        }
+    }
+    
+    @objc static let sharedInstance: IMImagemeterCodable = {
+        let instance = IMImagemeterCodable()
+        return instance
+    }()
+    
+    func decoderAnnotetion(_ annotation: Data) -> imagemeterAnnotation? {
+        
+        let jsonDecoder = JSONDecoder.init()
+        
+        do {
+            
+            let decode = try jsonDecoder.decode(imagemeterAnnotation.self, from: annotation)
+            return decode
+            
+        } catch let error {
+            
+            print("Serious internal error in decoding metadata ("+error.localizedDescription+")")
+            return nil
+        }
+    }
+    
+    func convertCoordinate(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) -> (x: CGFloat, y: CGFloat) {
+        
+        let factor = sqrt(width * height / (1024*768))
+        
+        let factorX = factor * x + width/2
+        let factorY = factor * y + height/2
+        
+        return(factorX, factorY)
+    }
+}

+ 46 - 0
iOSClient/Imagemeter/IMImagemeterView.xib

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="IMImagemeterView" customModule="Nextcloud" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="1ij-2s-LYq">
+                    <rect key="frame" x="0.0" y="215.5" width="375" height="256"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="256" id="LfB-Mf-Syk"/>
+                    </constraints>
+                </imageView>
+                <progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="6f5-Kb-BAR">
+                    <rect key="frame" x="0.0" y="471.5" width="375" height="2"/>
+                </progressView>
+            </subviews>
+            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="6f5-Kb-BAR" secondAttribute="trailing" id="OPB-z2-8ro"/>
+                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="1ij-2s-LYq" secondAttribute="trailing" id="dgH-RG-ZfA"/>
+                <constraint firstItem="6f5-Kb-BAR" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="mQc-Fk-9H5"/>
+                <constraint firstItem="1ij-2s-LYq" firstAttribute="centerY" secondItem="vUN-kp-3ea" secondAttribute="centerY" id="rw2-di-c3M"/>
+                <constraint firstItem="6f5-Kb-BAR" firstAttribute="top" secondItem="1ij-2s-LYq" secondAttribute="bottom" id="svd-nV-djc"/>
+                <constraint firstItem="1ij-2s-LYq" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="xtT-oj-SZN"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
+            <connections>
+                <outlet property="image" destination="1ij-2s-LYq" id="iez-qY-Pih"/>
+                <outlet property="imageHeightConstraint" destination="LfB-Mf-Syk" id="0Og-Mt-xU1"/>
+                <outlet property="progressView" destination="6f5-Kb-BAR" id="nc5-MB-GOs"/>
+            </connections>
+        </view>
+    </objects>
+</document>

+ 15 - 0
iOSClient/Images.xcassets/audioPlayFull.imageset/Contents.json

@@ -0,0 +1,15 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "audioPlayFull.pdf"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  },
+  "properties" : {
+    "preserves-vector-representation" : true
+  }
+}

BIN
iOSClient/Images.xcassets/audioPlayFull.imageset/audioPlayFull.pdf


+ 15 - 0
iOSClient/Images.xcassets/imagemeter.imageset/Contents.json

@@ -0,0 +1,15 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "imagemeter.png"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  },
+  "properties" : {
+    "preserves-vector-representation" : true
+  }
+}

BIN
iOSClient/Images.xcassets/imagemeter.imageset/imagemeter.png


+ 4 - 1
iOSClient/Library/OCCommunicationLib/OCWebDavClient/OCWebDAVClient.m

@@ -914,7 +914,10 @@ NSString const *OCWebDAVModificationDateKey	= @"modificationdate";
     NSMutableURLRequest *request = [self sharedRequestWithMethod:_requestMethod path:serverPath parameters:nil timeout:k_timeout_webdav];
     
     [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
-    
+    NSString *userAgent = [request valueForHTTPHeaderField:@"User-Agent"];
+    //[request setValue:[userAgent stringByAppendingString:@" (SilentPush)"] forHTTPHeaderField:@"User-Agent"];
+    [request setValue:[userAgent stringByAppendingString:@" (PushKit)"] forHTTPHeaderField:@"User-Agent"];
+
     OCHTTPRequestOperation *operation = [self mr_operationWithRequest:request onCommunication:sharedOCCommunication success:success failure:failure];
     [self setRedirectionBlockOnDatataskWithOCCommunication:sharedOCCommunication andSessionManager:sharedOCCommunication.networkSessionManager];
     [operation resume];

+ 1 - 1
iOSClient/Login/CCLogin.h

@@ -36,7 +36,7 @@
 
 @end
 
-@interface CCLogin : UIViewController <UITextFieldDelegate, NSURLSessionTaskDelegate, CCCertificateDelegate>
+@interface CCLogin : UIViewController <UITextFieldDelegate, CCCertificateDelegate>
 
 @property (nonatomic, weak) id <CCLoginDelegate> delegate;
 

+ 1 - 14
iOSClient/Login/CCLogin.m

@@ -169,7 +169,7 @@
     if ([self.baseUrl.text hasSuffix:@"/"])
         self.baseUrl.text = [self.baseUrl.text substringToIndex:[self.baseUrl.text length] - 1];
     
-    [[OCNetworking sharedManager] serverStatusUrl:self.baseUrl.text delegate:self completion:^(NSString *serverProductName, NSInteger versionMajor, NSInteger versionMicro, NSInteger versionMinor, NSString *message, NSInteger errorCode) {
+    [[OCNetworking sharedManager] serverStatusUrl:self.baseUrl.text completion:^(NSString *serverProductName, NSInteger versionMajor, NSInteger versionMicro, NSInteger versionMinor, NSString *message, NSInteger errorCode) {
         
         if (errorCode == 0) {
             
@@ -359,9 +359,6 @@
                     // STOP Intro
                     [CCUtility setIntro:YES];
                     
-                    // LOGOUT
-                    [appDelegate unsubscribingNextcloudServerPushNotification];
-                    
                     [[NCManageDatabase sharedInstance] deleteAccount:account];
                     [[NCManageDatabase sharedInstance] addAccount:account url:url user:user password:password loginFlow:false];
                     
@@ -442,14 +439,4 @@
     [qrCode scan];
 }
 
--(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
-{
-    // The pinnning check
-    if ([[CCCertificate sharedManager] checkTrustedChallenge:challenge]) {
-        completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
-    } else {
-        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
-    }
-}
-
 @end

+ 1 - 4
iOSClient/Login/CCLoginWeb.swift

@@ -123,10 +123,7 @@ extension CCLoginWeb: SwiftModalWebVCDelegate {
                         
                         // STOP Intro
                         CCUtility.setIntro(true)
-                        
-                        // LOGOUT
-                        appDelegate.unsubscribingNextcloudServerPushNotification()
-                        
+                                                
                         // Add new account
                         NCManageDatabase.sharedInstance.deleteAccount(account)
                         NCManageDatabase.sharedInstance.addAccount(account, url: serverUrl, user: username, password: password, loginFlow: true)

+ 4 - 0
iOSClient/Main/CCDetail.h

@@ -32,6 +32,7 @@
 #import "CCGraphics.h"
 
 @class tableMetadata;
+@class NCViewerImagemeter;
 
 @interface CCDetail : UIViewController <MWPhotoBrowserDelegate, ReaderViewControllerDelegate>
 
@@ -57,6 +58,9 @@
 @property (nonatomic, strong) ReaderViewController *readerPDFViewController;
 @property (nonatomic, strong) NSString *passwordPDF;
 
+// IM
+@property (nonatomic, strong) NCViewerImagemeter *imagemeter;
+
 @property(nonatomic, weak) IBOutlet UIImageView *imageBackground;
 
 - (void)changeToDisplayMode;

+ 32 - 8
iOSClient/Main/CCDetail.m

@@ -98,13 +98,6 @@
     // TabBar
     self.tabBarController.tabBar.hidden = YES;
     self.tabBarController.tabBar.translucent = YES;
-    
-    // Open View
-    if ([self.metadataDetail.fileNameView length] > 0 || [self.metadataDetail.serverUrl length] > 0 || [self.metadataDetail.fileID length] > 0) {
-    
-        // open view
-        [self viewFile];
-    }
 }
 
 - (void)viewWillAppear:(BOOL)animated
@@ -113,6 +106,13 @@
     
     self.tabBarController.tabBar.hidden = YES;
     self.tabBarController.tabBar.translucent = YES;
+    
+    // Open View
+    if ([self.metadataDetail.fileNameView length] > 0 || [self.metadataDetail.serverUrl length] > 0 || [self.metadataDetail.fileID length] > 0) {
+        
+        // open view
+        [self viewFile];
+    }
 }
 
 - (void)viewWillDisappear:(BOOL)animated
@@ -140,6 +140,18 @@
     }
 }
 
+- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
+{
+    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+    
+    [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+        
+        if (self.imagemeter) {
+            [self.imagemeter viewImagemeter];
+        }
+    }];
+}
+
 - (void)changeTheming
 {
     [appDelegate changeTheming:self];
@@ -152,8 +164,12 @@
 
 - (void)changeToDisplayMode
 {
-    if (_readerPDFViewController)
+    if (_readerPDFViewController) {
         [self.readerPDFViewController updateContentViews];
+    }
+    if (self.imagemeter) {
+        [self.imagemeter viewImagemeter];
+    }
 }
 
 #pragma --------------------------------------------------------------------------------------------
@@ -248,6 +264,14 @@
         [self createToolbar];
         [[NCViewerDocumentWeb sharedInstance] viewDocumentWebAt:self.metadataDetail detail:self];
     }
+    
+    // IMI File
+    if ([self.metadataDetail.typeFile isEqualToString: k_metadataTypeFile_imagemeter]) {
+        
+        self.imagemeter = [[NCViewerImagemeter alloc] initWithMetadata:self.metadataDetail detail:self];
+        [self.imagemeter viewImagemeter];
+        [self createToolbar];
+    }
 }
 
 #pragma --------------------------------------------------------------------------------------------

+ 7 - 10
iOSClient/Main/CCMain.m

@@ -142,8 +142,7 @@
     [self createRefreshControl];
     
     // Register for 3D Touch Previewing if available
-    if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] && (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable))
-    {
+    if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] && (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)) {
         [self registerForPreviewingWithDelegate:self sourceView:self.view];
     }
 
@@ -376,6 +375,9 @@
         // reload datasource
         [[NCMainCommon sharedInstance] reloadDatasourceWithServerUrl:_serverUrl fileID:nil action:k_action_NULL];
     }
+    
+    // Registered push notification
+    [appDelegate pushNotification];
 }
 
 #pragma --------------------------------------------------------------------------------------------
@@ -916,9 +918,7 @@
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
         // go to home sweet home
         [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"initializeMain" object:nil userInfo:nil];
-    });
-    
-    [appDelegate subscribingNextcloudServerPushNotification];
+    });    
 }
 
 #pragma mark -
@@ -940,6 +940,7 @@
             
         viewController.metadata = metadata;
         viewController.imageFile = cell.file.image;
+        viewController.showOpenIn = true;
         viewController.showShare = true;
         
         return viewController;
@@ -2287,9 +2288,7 @@
 - (void)changeDefaultAccount:(CCMenuItem *)sender
 {
     // LOGOUT
-        
-    [appDelegate unsubscribingNextcloudServerPushNotification];
-        
+    
     tableAccount *tableAccount = [[NCManageDatabase sharedInstance] setAccountActive:[sender argument]];
     if (tableAccount) {
             
@@ -2299,8 +2298,6 @@
     
         // go to home sweet home
         [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"initializeMain" object:nil userInfo:nil];
-            
-        [appDelegate subscribingNextcloudServerPushNotification];
     }
 }
 

+ 1 - 4
iOSClient/Main/CCMore.swift

@@ -51,7 +51,6 @@ class CCMore: UIViewController, UITableViewDelegate, UITableViewDataSource, CCLo
     }
     
     override func viewDidLoad() {
-        
         super.viewDidLoad()
         
         tableView.delegate = self
@@ -475,9 +474,7 @@ class CCMore: UIViewController, UITableViewDelegate, UITableViewDataSource, CCLo
         
         NotificationCenter.default.post(name: NSNotification.Name(rawValue: "initializeMain"), object: nil, userInfo: nil)
         
-        appDelegate.selectedTabBarController(Int(k_tabBarApplicationIndexFile))
-        
-        appDelegate.subscribingNextcloudServerPushNotification()
+        appDelegate.selectedTabBarController(Int(k_tabBarApplicationIndexFile))        
     }
 }
 

+ 3 - 3
iOSClient/Main/CCSplit.m

@@ -55,6 +55,8 @@
 {
     [super viewDidLoad];
 
+    self.delegate = self;
+    
     // Display mode SPLIT
     self.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
     //self.maximumPrimaryColumnWidth = 400;
@@ -179,9 +181,7 @@
 
 - (void)loginSuccess:(NSInteger)loginType
 {
-    [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"initializeMain" object:nil userInfo:nil];
-    
-    [appDelegate subscribingNextcloudServerPushNotification];
+    [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"initializeMain" object:nil userInfo:nil];    
 }
 
 #pragma --------------------------------------------------------------------------------------------

+ 148 - 5
iOSClient/Main/NCMainCommon.swift

@@ -23,6 +23,9 @@
 
 import Foundation
 import TLPhotoPicker
+import Zip
+
+//MARK: - Main Common
 
 class NCMainCommon: NSObject, PhotoEditorDelegate, NCAudioRecorderViewControllerDelegate, UIDocumentInteractionControllerDelegate {
     
@@ -1076,7 +1079,7 @@ class NCMainCommon: NSObject, PhotoEditorDelegate, NCAudioRecorderViewController
     }
 }
     
-//MARK: -
+//MARK: - Main TabBarController
 
 class CCMainTabBarController : UITabBarController, UITabBarControllerDelegate {
         
@@ -1156,7 +1159,7 @@ extension UITabBar {
     }
 }
 
-//MARK: -
+//MARK: - Networking Main
 
 class NCNetworkingMain: NSObject, CCNetworkingDelegate {
 
@@ -1165,6 +1168,13 @@ class NCNetworkingMain: NSObject, CCNetworkingDelegate {
         return instance
     }()
     
+    lazy var operationQueueNetworkingMain: OperationQueue = {
+        let queue = OperationQueue()
+        queue.name = "com.nextcloud.operationQueueNetworkingMain"
+        queue.maxConcurrentOperationCount = 1
+        return queue
+    }()
+    
     let appDelegate = UIApplication.shared.delegate as! AppDelegate
 
     // DOWNLOAD
@@ -1211,6 +1221,40 @@ class NCNetworkingMain: NSObject, CCNetworkingDelegate {
                     metadata.typeFile = k_metadataTypeFile_unknown
                 }
                 
+                if metadata.typeFile == k_metadataTypeFile_imagemeter {
+                    
+                    do {
+                        Zip.addCustomFileExtension("imi")
+                        
+                        let source = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageFileID(metadata.fileID, fileNameView: metadata.fileNameView))
+                        let destination =  URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageFileID(metadata.fileID))
+                        
+                        try Zip.unzipFile(source, destination: destination, overwrite: true, password: nil)
+                        
+                        let nameArchiveImagemeter = (metadata.fileNameView as NSString).deletingPathExtension
+                        let pathArchiveImagemeter = CCUtility.getDirectoryProviderStorageFileID(metadata.fileID) + "/" + nameArchiveImagemeter
+                        let annoPath = (pathArchiveImagemeter + "/anno-" + nameArchiveImagemeter + ".imm")
+                        
+                        if let fileHandle = FileHandle(forReadingAtPath: annoPath) {
+                            let data = fileHandle.readData(ofLength: 4)
+                            if data.starts(with: [0x50, 0x4b, 0x03, 0x04]) {
+                                Zip.addCustomFileExtension("imm")
+                                do {
+                                    try Zip.unzipFile(annoPath.url, destination: pathArchiveImagemeter.url, overwrite: true, password: nil)
+                                } catch {
+                                    appDelegate.messageNotification("_error_", description: "_error_decompressing_", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
+                                    return
+                                }
+                            }
+                            fileHandle.closeFile()
+                        }
+                        
+                    } catch {
+                        appDelegate.messageNotification("_error_", description: "_error_decompressing_", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
+                        return
+                    }
+                }
+                
                 if metadata.typeFile == k_metadataTypeFile_compress || metadata.typeFile == k_metadataTypeFile_unknown {
 
                     NCMainCommon.sharedInstance.openIn(metadata: metadata)
@@ -1318,13 +1362,17 @@ class NCNetworkingMain: NSObject, CCNetworkingDelegate {
     }
     
     @objc func downloadThumbnail(with metadata: tableMetadata, view: Any, indexPath: IndexPath) {
+        operationQueueNetworkingMain.addOperation(NCOperationNetworkingMain.init(metadata: metadata, view: view, indexPath: indexPath, networkingFunc: "downloadThumbnail"))
+    }
+    
+    func downloadThumbnail(with metadata: tableMetadata, view: Any, indexPath: IndexPath, closure: @escaping () -> ()) {
         
         if !metadata.isInvalidated && metadata.hasPreview == 1 && (!CCUtility.fileProviderStorageIconExists(metadata.fileID, fileNameView: metadata.fileName) || metadata.typeFile == k_metadataTypeFile_document) {
             
             let width = NCUtility.sharedInstance.getScreenWidthForPreview()
             let height = NCUtility.sharedInstance.getScreenHeightForPreview()
             
-            OCNetworking.sharedManager().downloadPreview(withAccount: appDelegate.activeAccount, metadata: metadata, withWidth: width, andHeight: height, completion: { (account, image, message, errorCode) in
+            OCNetworking.sharedManager().downloadPreview(withAccount: metadata.account, metadata: metadata, withWidth: width, andHeight: height, completion: { (account, image, message, errorCode) in
                 
                 if errorCode == 0 && account == self.appDelegate.activeAccount && !metadata.isInvalidated && CCUtility.fileProviderStorageIconExists(metadata.fileID, fileNameView: metadata.fileName) {
                     
@@ -1350,12 +1398,108 @@ class NCNetworkingMain: NSObject, CCNetworkingDelegate {
                         }
                     }
                 }
+                
+                return closure()
             })
         }
+        
+        return closure()
+    }
+}
+
+//MARK: - Operation Networking Main
+
+class NCOperationNetworkingMain: Operation {
+    
+    private var _executing : Bool = false
+    override var isExecuting : Bool {
+        get { return _executing }
+        set {
+            guard _executing != newValue else { return }
+            willChangeValue(forKey: "isExecuting")
+            _executing = newValue
+            didChangeValue(forKey: "isExecuting")
+        }
+    }
+
+    private var _finished : Bool = false
+    override var isFinished : Bool {
+        get { return _finished }
+        set {
+            guard _finished != newValue else { return }
+            willChangeValue(forKey: "isFinished")
+            _finished = newValue
+            didChangeValue(forKey: "isFinished")
+        }
+    }
+    
+    private var metadata: tableMetadata?
+    private var view: Any?
+    private var indexPath: IndexPath?
+    private var networkingFunc: String = ""
+
+    init(metadata: tableMetadata?, view: Any?, indexPath: IndexPath?, networkingFunc: String) {
+        super.init()
+        
+        if metadata != nil { self.metadata = metadata! }
+        if view != nil { self.view = view! }
+        if indexPath != nil { self.indexPath = indexPath! }
+        
+        self.networkingFunc = networkingFunc
+    }
+    
+    override func start() {
+        if !Thread.isMainThread {
+            
+            self.performSelector(onMainThread:#selector(start), with: nil, waitUntilDone: false)
+            
+        } else {
+        
+            isExecuting = true
+        
+            if isCancelled {
+                finish()
+            } else {
+                poolNetworking()
+            }
+        }
+    }
+    
+    func finish() {
+        isExecuting = false
+        isFinished = true
+    }
+    
+    override func cancel() {
+        super.cancel()
+        
+        if isExecuting {
+            complete()
+        }
+    }
+    
+    func complete() {
+        finish()
+        
+        UIApplication.shared.isNetworkActivityIndicatorVisible = false
+    }
+    
+    func poolNetworking() {
+        UIApplication.shared.isNetworkActivityIndicatorVisible = true
+        
+        switch networkingFunc {
+        case "downloadThumbnail":
+            NCNetworkingMain.sharedInstance.downloadThumbnail(with: metadata!, view: view!, indexPath: indexPath!) {
+                self.complete()
+            }
+        default:
+            print("error")
+        }
     }
 }
 
-//MARK: -
+
+//MARK: - Function Main
 
 class NCFunctionMain: NSObject {
     
@@ -1384,7 +1528,6 @@ class NCFunctionMain: NSObject {
                 CCSynchronize.shared()?.readFile(metadata.fileID, fileName: metadata.fileName, serverUrl: metadata.serverUrl, selector: selectorReadFileWithDownload, account: appDelegate.activeAccount)
             }
         }
-    
     }
 }
 

+ 6 - 0
iOSClient/Media/NCMedia.swift

@@ -370,6 +370,8 @@ extension NCMedia: UIViewControllerPreviewingDelegate {
         previewingContext.sourceRect = cell.frame
         viewController.metadata = metadata
         viewController.imageFile = cell.imageItem.image
+        viewController.showOpenIn = true
+        viewController.showShare = false
 
         return viewController
     }
@@ -721,6 +723,10 @@ extension NCMedia: UIScrollViewDelegate {
     func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
         collectionView.scrollViewDidEndDragging(scrollView, willDecelerate: decelerate)
     }
+    
+    func scrollViewDidScrollToTop(_ scrollView: UIScrollView) {
+        selectSearchSections()
+    }
 }
 
 extension NCMedia: FastScrollCollectionViewDelegate {

+ 1 - 1
iOSClient/Networking/NCService.swift

@@ -298,7 +298,7 @@ class NCService: NSObject {
     
     private func requestServerStatus() {
 
-        OCNetworking.sharedManager().serverStatusUrl(appDelegate.activeUrl, delegate: self, completion: { (serverProductName, versionMajor, versionMicro, versionMinor, message, errorCode) in
+        OCNetworking.sharedManager().serverStatusUrl(appDelegate.activeUrl, completion: { (serverProductName, versionMajor, versionMicro, versionMinor, message, errorCode) in
             if errorCode == 0 {
                 if serverProductName == "owncloud" {
                     self.appDelegate.messageNotification("_warning_", description: "_warning_owncloud_", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.info, errorCode: Int(k_CCErrorInternalError))

+ 3 - 2
iOSClient/Networking/OCNetworking.h

@@ -26,7 +26,7 @@
 #import "AFURLSessionManager.h"
 #import "CCNetworking.h"
 
-@interface OCNetworking : NSObject <NSURLSessionDelegate>
+@interface OCNetworking : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate>
 
 + (OCNetworking *)sharedManager;
 
@@ -38,7 +38,7 @@
 #pragma mark ===== Server =====
 
 - (void)checkServerUrl:(NSString *)serverUrl user:(NSString *)user userID:(NSString *)userID password:(NSString *)password completion:(void (^)(NSString *message, NSInteger errorCode))completion;
-- (void)serverStatusUrl:(NSString *)serverUrl delegate:(id)delegate completion:(void(^)(NSString *serverProductName, NSInteger versionMajor, NSInteger versionMicro, NSInteger versionMinor, NSString *message, NSInteger errorCode))completion;
+- (void)serverStatusUrl:(NSString *)serverUrl completion:(void(^)(NSString *serverProductName, NSInteger versionMajor, NSInteger versionMicro, NSInteger versionMinor, NSString *message, NSInteger errorCode))completion;
 
 #pragma mark ===== Download / Upload =====
 
@@ -89,6 +89,7 @@
 
 - (void)subscribingPushNotificationWithAccount:(NSString *)account url:(NSString *)url pushToken:(NSString *)pushToken Hash:(NSString *)pushTokenHash devicePublicKey:(NSString *)devicePublicKey completion:(void(^)(NSString *account, NSString *deviceIdentifier, NSString *deviceIdentifierSignature, NSString *publicKey, NSString *message, NSInteger errorCode))completion;
 - (void)unsubscribingPushNotificationWithAccount:(NSString *)account url:(NSString *)url deviceIdentifier:(NSString *)deviceIdentifier deviceIdentifierSignature:(NSString *)deviceIdentifierSignature publicKey:(NSString *)publicKey completion:(void (^)(NSString *account ,NSString *message, NSInteger errorCode))completion;
+- (void)getServerNotification:(NSString *)serverUrl notificationId:(NSInteger)notificationId completion:(void(^)(NSDictionary*jsongParsed, NSString *message, NSInteger errorCode))completion;
 
 #pragma mark ===== Manage Mobile Editor OCS API =====
 

+ 73 - 7
iOSClient/Networking/OCNetworking.m

@@ -165,7 +165,7 @@
     }];
 }
 
-- (void)serverStatusUrl:(NSString *)serverUrl delegate:(id)delegate completion:(void(^)(NSString *serverProductName, NSInteger versionMajor, NSInteger versionMicro, NSInteger versionMinor, NSString *message, NSInteger errorCode))completion
+- (void)serverStatusUrl:(NSString *)serverUrl completion:(void(^)(NSString *serverProductName, NSInteger versionMajor, NSInteger versionMicro, NSInteger versionMinor, NSString *message, NSInteger errorCode))completion
 {
     NSString *urlTest = [serverUrl stringByAppendingString:k_serverStatus];
     
@@ -181,7 +181,7 @@
     [request addValue:@"true" forHTTPHeaderField:@"OCS-APIRequest"];
     
     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
-    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:delegate delegateQueue:nil];
+    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
     
     NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {
         
@@ -1585,18 +1585,22 @@
     }
     
     devicePublicKey = [CCUtility URLEncodeStringFromString:devicePublicKey];
-
+    NSString *proxyServerPath = [NCBrandOptions sharedInstance].pushNotificationServerProxy;
+    //proxyServerPath = @"http://127.0.0.1:8088";
+    NSString *proxyServer = [NCBrandOptions sharedInstance].pushNotificationServerProxy;
+    //proxyServer = @"https://10.132.0.37:8443/pushnotifications";
+    
     OCCommunication *communication = [OCNetworking sharedManager].sharedOCCommunication;
     
     [communication setCredentialsWithUser:tableAccount.user andUserID:tableAccount.userID andPassword:tableAccount.password];
     [communication setUserAgent:[CCUtility getUserAgent]];
-    [communication subscribingNextcloudServerPush:url pushTokenHash:pushTokenHash devicePublicKey:devicePublicKey proxyServerPath: [NCBrandOptions sharedInstance].pushNotificationServerProxy onCommunication:communication successRequest:^(NSHTTPURLResponse *response, NSString *publicKey, NSString *deviceIdentifier, NSString *signature, NSString *redirectedServer) {
+    [communication subscribingNextcloudServerPush:url pushTokenHash:pushTokenHash devicePublicKey:devicePublicKey proxyServerPath: proxyServerPath onCommunication:communication successRequest:^(NSHTTPURLResponse *response, NSString *publicKey, NSString *deviceIdentifier, NSString *signature, NSString *redirectedServer) {
         
         deviceIdentifier = [CCUtility URLEncodeStringFromString:deviceIdentifier];
         signature = [CCUtility URLEncodeStringFromString:signature];
         publicKey = [CCUtility URLEncodeStringFromString:publicKey];
         
-        [communication subscribingPushProxy:[NCBrandOptions sharedInstance].pushNotificationServerProxy pushToken:pushToken deviceIdentifier:deviceIdentifier deviceIdentifierSignature:signature publicKey:publicKey onCommunication:communication successRequest:^(NSHTTPURLResponse *response, NSString *redirectedServer) {
+        [communication subscribingPushProxy:proxyServer pushToken:pushToken deviceIdentifier:deviceIdentifier deviceIdentifierSignature:signature publicKey:publicKey onCommunication:communication successRequest:^(NSHTTPURLResponse *response, NSString *redirectedServer) {
             
             completion(account, deviceIdentifier, signature, publicKey, nil, 0);
             
@@ -1640,13 +1644,16 @@
         completion(account, NSLocalizedString(@"_error_user_not_available_", nil), k_CCErrorUserNotAvailble);
     }
     
+    NSString *proxyServer = [NCBrandOptions sharedInstance].pushNotificationServerProxy;
+    //proxyServer = @"https://10.132.0.37:8443/pushnotifications";
+    
     OCCommunication *communication = [OCNetworking sharedManager].sharedOCCommunication;
 
     [communication setCredentialsWithUser:tableAccount.user andUserID:tableAccount.userID andPassword:tableAccount.password];
     [communication setUserAgent:[CCUtility getUserAgent]];
     [communication unsubscribingNextcloudServerPush:url onCommunication:communication successRequest:^(NSHTTPURLResponse *response, NSString *redirectedServer) {
 
-        [communication unsubscribingPushProxy:[NCBrandOptions sharedInstance].pushNotificationServerProxy deviceIdentifier:deviceIdentifier deviceIdentifierSignature:deviceIdentifierSignature publicKey:publicKey onCommunication:communication successRequest:^(NSHTTPURLResponse *response, NSString *redirectedServer) {
+        [communication unsubscribingPushProxy:proxyServer deviceIdentifier:deviceIdentifier deviceIdentifierSignature:deviceIdentifierSignature publicKey:publicKey onCommunication:communication successRequest:^(NSHTTPURLResponse *response, NSString *redirectedServer) {
             
             completion(account, nil, 0);
             
@@ -1683,6 +1690,49 @@
     }];
 }
 
+- (void)getServerNotification:(NSString *)serverUrl notificationId:(NSInteger)notificationId completion:(void(^)(NSDictionary*jsongParsed, NSString *message, NSInteger errorCode))completion
+{
+    NSString *URLString = [NSString stringWithFormat:@"%@/ocs/v2.php/apps/notifications/api/v2/notifications/%ld?format=json", serverUrl, (long)notificationId];
+
+    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString] cachePolicy:0 timeoutInterval:20.0];
+    [request addValue:[CCUtility getUserAgent] forHTTPHeaderField:@"User-Agent"];
+    [request addValue:@"true" forHTTPHeaderField:@"OCS-APIRequest"];
+
+    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
+    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
+
+    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) {
+
+        if (error) {
+            
+            NSString *message;
+            NSInteger errorCode;
+            
+            NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
+            errorCode = httpResponse.statusCode;
+            
+            if (errorCode == 0 || (errorCode >= 200 && errorCode < 300))
+                errorCode = error.code;
+            
+            // Error
+            if (errorCode == 503)
+                message = NSLocalizedString(@"_server_error_retry_", nil);
+            else
+                message = [error.userInfo valueForKey:@"NSLocalizedDescription"];
+            
+            completion(nil, message, errorCode);
+            
+        } else {
+            
+            NSDictionary *jsongParsed = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
+
+            completion(jsongParsed, nil, 0);
+        }
+    }];
+    
+    [task resume];
+}
+
 #pragma --------------------------------------------------------------------------------------------
 #pragma mark ===== Manage Mobile Editor OCS API =====
 #pragma --------------------------------------------------------------------------------------------
@@ -1864,7 +1914,9 @@
                     trash.directory = itemDto.isDirectory;
                     trash.fileID = itemDto.ocId;
                     trash.fileName = itemDto.fileName;
-                    trash.filePath = itemDto.filePath;
+                    NSArray *array = [itemDto.filePath componentsSeparatedByString:path];
+                    long len = [[array objectAtIndex:0] length];
+                    trash.filePath = [itemDto.filePath substringFromIndex:len];
                     trash.size = itemDto.size;
                     trash.trashbinFileName = itemDto.trashbinFileName;
                     trash.trashbinOriginalLocation = itemDto.trashbinOriginalLocation;
@@ -1931,6 +1983,20 @@
     }];
 }
 
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark =====  didReceiveChallenge =====
+#pragma --------------------------------------------------------------------------------------------
+
+-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
+{
+    // The pinnning check
+    if ([[CCCertificate sharedManager] checkTrustedChallenge:challenge]) {
+        completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
+    } else {
+        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
+    }
+}
+
 @end
 
 #pragma --------------------------------------------------------------------------------------------

+ 3 - 0
iOSClient/Offline/NCOffline.swift

@@ -520,6 +520,9 @@ extension NCOffline: UIViewControllerPreviewingDelegate {
             viewController.imageFile = cell.imageItem.image
         }
         
+        viewController.showOpenIn = true
+        viewController.showShare = false
+        
         return viewController
     }
     

+ 1 - 0
iOSClient/PeekPop/CCPeekPop.h

@@ -31,6 +31,7 @@
 @property (nonatomic, strong) tableMetadata *metadata;
 @property (nonatomic, strong) UIImage *imageFile;
 @property BOOL showShare;
+@property BOOL showOpenIn;
 
 @property (nonatomic, weak) IBOutlet UILabel *fileName;
 @property (nonatomic, weak) IBOutlet UIImageView *imagePreview;

+ 16 - 30
iOSClient/PeekPop/CCPeekPop.m

@@ -36,12 +36,6 @@
 
 @implementation CCPeekPop
 
-- (void)setMetadata:(tableMetadata *)newMetadata
-{
-    if (_metadata != newMetadata)
-        _metadata = newMetadata;
-}
-
 - (void)viewDidLoad
 {
     [super viewDidLoad];
@@ -71,33 +65,25 @@
     self.preferredContentSize = CGSizeMake(self.imagePreview.image.size.width,  self.imagePreview.image.size.height + highLabelFileName);
 }
 
-- (void)viewWillAppear:(BOOL)animated
-{
-    [super viewWillAppear:animated];
-}
-
-- (void)didReceiveMemoryWarning
-{
-    [super didReceiveMemoryWarning];
-}
-
 - (NSArray<id<UIPreviewActionItem>> *)previewActionItems
 {
-    UIPreviewAction *openIn = [UIPreviewAction actionWithTitle:NSLocalizedString(@"_open_in_", nil) style:UIPreviewActionStyleDefault handler:^(UIPreviewAction *action,  UIViewController *previewViewController){
-        
-        [[NCMainCommon sharedInstance] downloadOpenInMetadata:_metadata];
-    }];
-    
-    UIPreviewAction *share = [UIPreviewAction actionWithTitle:NSLocalizedString(@"_share_", nil) style:UIPreviewActionStyleDefault handler:^(UIPreviewAction *action,  UIViewController *previewViewController){
-        
-        [appDelegate.activeMain readShareWithAccount:appDelegate.activeAccount openWindow:YES metadata:self.metadata];
-    }];
+    NSMutableArray *items = [NSMutableArray new];
+ 
+    if (self.showOpenIn && !self.metadata.directory) {
+        UIPreviewAction *openIn = [UIPreviewAction actionWithTitle:NSLocalizedString(@"_open_in_", nil) style:UIPreviewActionStyleDefault handler:^(UIPreviewAction *action,  UIViewController *previewViewController){
+            [[NCMainCommon sharedInstance] downloadOpenInMetadata:self.metadata];
+        }];
+        [items addObject:openIn];
+    }
     
-    if (self.showShare == true) {
-        return @[openIn, share];
-    } else {
-        return @[openIn];
+    if (self.showShare) {
+        UIPreviewAction *share = [UIPreviewAction actionWithTitle:NSLocalizedString(@"_share_", nil) style:UIPreviewActionStyleDefault handler:^(UIPreviewAction *action,  UIViewController *previewViewController){
+            [appDelegate.activeMain readShareWithAccount:appDelegate.activeAccount openWindow:YES metadata:self.metadata];
+        }];
+        [items addObject:share];
     }
+    
+    return items;
 }
 
 #pragma --------------------------------------------------------------------------------------------
@@ -109,7 +95,7 @@
     CGFloat width = [[NCUtility sharedInstance] getScreenWidthForPreview];
     CGFloat height = [[NCUtility sharedInstance] getScreenHeightForPreview];
     
-    [[OCNetworking sharedManager] downloadPreviewWithAccount:appDelegate.activeAccount metadata:_metadata withWidth:width andHeight:height completion:^(NSString *account, UIImage *image, NSString *message, NSInteger errorCode) {
+    [[OCNetworking sharedManager] downloadPreviewWithAccount:appDelegate.activeAccount metadata:self.metadata withWidth:width andHeight:height completion:^(NSString *account, UIImage *image, NSString *message, NSInteger errorCode) {
      
         if (errorCode == 0 && [account isEqualToString:appDelegate.activeAccount]) {
             self.imagePreview.image = [CCGraphics scaleImage:image toSize:CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height) isAspectRation:true];

+ 1 - 4
iOSClient/Security/NCPushNotificationEncryption.h

@@ -27,11 +27,8 @@
 
 @interface NCPushNotificationEncryption : NSObject
 
-@property (nonatomic, copy) NSData *ncPNPublicKey;
-@property (nonatomic, copy) NSData *ncPNPrivateKey;
-
 + (NCPushNotificationEncryption *)sharedInstance;
-- (BOOL)generatePushNotificationsKeyPair;
+- (BOOL)generatePushNotificationsKeyPair:(NSString *)account;
 - (NSString *)decryptPushNotification:(NSString *)message withDevicePrivateKey:(NSData *)privateKey;
 
 @end

+ 6 - 9
iOSClient/Security/NCPushNotificationEncryption.m

@@ -54,13 +54,11 @@
     self = [super init];
     if (self) {
        
-        self.ncPNPublicKey = [CCUtility getPushNotificationPublicKey];
-        self.ncPNPrivateKey = [CCUtility getPushNotificationPrivateKey];
     }
     return self;
 }
 
-- (BOOL)generatePushNotificationsKeyPair
+- (BOOL)generatePushNotificationsKeyPair:(NSString *)account
 {
     EVP_PKEY *pkey;
     NSError *keyError;
@@ -81,9 +79,9 @@
     keyBytes  = malloc(len);
     
     BIO_read(publicKeyBIO, keyBytes, len);
-    _ncPNPublicKey = [NSData dataWithBytes:keyBytes length:len];
-    [CCUtility setPushNotificationPublicKey:_ncPNPublicKey];
-    NSLog(@"Push Notifications Key Pair generated: \n%@", [[NSString alloc] initWithData:_ncPNPublicKey encoding:NSUTF8StringEncoding]);
+    NSData *ncPNPublicKey = [NSData dataWithBytes:keyBytes length:len];
+    [CCUtility setPushNotificationPublicKey:account data:ncPNPublicKey];
+    NSLog(@"Push Notifications Key Pair generated: \n%@", [[NSString alloc] initWithData:ncPNPublicKey encoding:NSUTF8StringEncoding]);
     
     // PrivateKey
     BIO *privateKeyBIO = BIO_new(BIO_s_mem());
@@ -93,8 +91,8 @@
     keyBytes = malloc(len);
     
     BIO_read(privateKeyBIO, keyBytes, len);
-    _ncPNPrivateKey = [NSData dataWithBytes:keyBytes length:len];
-    [CCUtility setPushNotificationPrivateKey:_ncPNPrivateKey];
+    NSData *ncPNPrivateKey = [NSData dataWithBytes:keyBytes length:len];
+    [CCUtility setPushNotificationPrivateKey:account data:ncPNPrivateKey];
     
     EVP_PKEY_free(pkey);
     
@@ -137,5 +135,4 @@
     return decryptString;
 }
 
-
 @end

+ 5 - 6
iOSClient/Settings/CCManageAccount.m

@@ -203,8 +203,6 @@
 - (void)loginSuccess:(NSInteger)loginType
 {
     [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"initializeMain" object:nil userInfo:nil];
-    
-    [appDelegate subscribingNextcloudServerPushNotification];
 }
 
 
@@ -236,7 +234,10 @@
 
 - (void)deleteAccount:(NSString *)account
 {
-    [appDelegate unsubscribingNextcloudServerPushNotification];
+    tableAccount *tableAccount = [[NCManageDatabase sharedInstance] getAccountWithPredicate:[NSPredicate predicateWithFormat:@"account == %@", account]];
+    if (tableAccount) {
+        [appDelegate unsubscribingNextcloudServerPushNotification:tableAccount.account url:tableAccount.url withSubscribing:false];
+    }
     
     [[NCManageDatabase sharedInstance] clearTable:[tableAccount class] account:account];
     [[NCManageDatabase sharedInstance] clearTable:[tableActivity class] account:account];
@@ -302,9 +303,7 @@
         // Init home
         [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadName:@"initializeMain" object:nil userInfo:nil];
             
-        [self UpdateForm];
-            
-        [appDelegate subscribingNextcloudServerPushNotification];
+        [self UpdateForm];            
     }
 }
 

+ 1 - 1
iOSClient/Shares/NCShares.h

@@ -24,7 +24,7 @@
 #import <UIKit/UIKit.h>
 #import <DZNEmptyDataSet/UIScrollView+EmptyDataSet.h>
 
-@interface NCShares : UIViewController <UITableViewDataSource, UITableViewDelegate, DZNEmptyDataSetDelegate , DZNEmptyDataSetSource>
+@interface NCShares : UIViewController <UITableViewDataSource, UITableViewDelegate, DZNEmptyDataSetDelegate , DZNEmptyDataSetSource, UIViewControllerPreviewingDelegate>
 
 @property (nonatomic, weak) IBOutlet UITableView *tableView;
 

+ 41 - 0
iOSClient/Shares/NCShares.m

@@ -70,6 +70,11 @@
     
     // Title
     self.title = NSLocalizedString(@"_list_shares_", nil);
+    
+    // Register for 3D Touch Previewing if available
+    if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] && (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)) {
+        [self registerForPreviewingWithDelegate:self sourceView:self.view];
+    }
 }
 
 // Apparirà
@@ -132,6 +137,42 @@
     return [[NSAttributedString alloc] initWithString:text attributes:attributes];
 }
 
+#pragma mark -
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Peek & Pop  =====
+#pragma --------------------------------------------------------------------------------------------
+
+- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
+{
+    CGPoint convertedLocation = [self.view convertPoint:location toView:self.tableView];
+    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:convertedLocation];
+    tableShare *table = [_dataSource objectAtIndex:indexPath.row];
+    tableMetadata *metadata = [[NCManageDatabase sharedInstance] getMetadataWithPredicate:[NSPredicate predicateWithFormat:@"account == %@ AND serverUrl == %@ AND fileName == %@", appDelegate.activeAccount, table.serverUrl, table.fileName]];
+    
+    NCSharesCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
+    
+    if (cell) {
+        previewingContext.sourceRect = cell.frame;
+        CCPeekPop *viewController = [[UIStoryboard storyboardWithName:@"CCPeekPop" bundle:nil] instantiateViewControllerWithIdentifier:@"PeekPopImagePreview"];
+        
+        viewController.metadata = metadata;
+        viewController.imageFile = cell.fileImageView.image;
+        viewController.showOpenIn = false;
+        viewController.showShare = false;
+        
+        return viewController;
+    }
+    
+    return nil;
+}
+
+- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit
+{
+    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:previewingContext.sourceRect.origin];
+    
+    [self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
+}
+
 #pragma --------------------------------------------------------------------------------------------
 #pragma mark ==== unShare <Delegate> ====
 #pragma --------------------------------------------------------------------------------------------

BIN
iOSClient/Supporting Files/ast.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/ca.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/da.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/de.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/el.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/en-GB.lproj/Localizable.strings


+ 2 - 2
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -570,8 +570,7 @@
 "_e2e_error_create_encrypted_"      = "Could not create encrypted file";
 "_e2e_error_update_metadata_"       = "Update metadata error";
 "_e2e_error_store_metadata_"        = "Could not save metadata";
-"_e2e_error_send_metadata_"         = "Could not send metadata";
-"_e2e_error_delete_metadata_"       = "Could not delete metadata";
+"_e2e_error_send_metadata_"         = "Could not send metadata";"_e2e_error_delete_metadata_"       = "Could not delete metadata";
 "_e2e_error_get_metadata_"          = "Could not fetch metadata";
 "_e2e_error_not_enabled_"           = "Serious internal error. End-to-end encryption not enabled";
 "_e2e_error_record_not_found_"      = "Serious internal error. Records not found";
@@ -678,6 +677,7 @@
 "_error_user_not_available_"            = "The user is no longer available";
 "_server_response_error_"               = "Server response content error";
 "_no_nextcloud_found_"                  = "Nextcloud server not found";
+"_error_decompressing_"                 = "Error during decompressing. Unknown compression method or the file is corrupt";
 
 // BKPasscode
 

BIN
iOSClient/Supporting Files/es-419.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-AR.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-CL.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-CO.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-CR.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-DO.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-EC.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-GT.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-HN.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-MX.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-NI.lproj/Localizable.strings


BIN
iOSClient/Supporting Files/es-PA.lproj/Localizable.strings


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.