Skip to content

Commit f7147b3

Browse files
committed
Merge branch 'master' of https://github.com/nextcloud/ios into mtls
2 parents 9b42a3d + b52ce91 commit f7147b3

File tree

122 files changed

+300
-146
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+300
-146
lines changed

Nextcloud.xcodeproj/project.pbxproj

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,10 @@
843843
F7B769AD2B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B769A72B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift */; };
844844
F7B769AE2B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B769A72B7A0B2000C1AAEB /* NCManageDatabase+Metadata+Session.swift */; };
845845
F7B8B83025681C3400967775 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F7B8B82F25681C3400967775 /* GoogleService-Info.plist */; };
846+
F7B8F6142EAB64AD006A70D6 /* JDStatusBarNotification in Frameworks */ = {isa = PBXBuildFile; productRef = F7B8F6132EAB64AD006A70D6 /* JDStatusBarNotification */; };
847+
F7B8F6162EAB7503006A70D6 /* JDStatusBarNotification in Frameworks */ = {isa = PBXBuildFile; productRef = F7B8F6152EAB7503006A70D6 /* JDStatusBarNotification */; };
848+
F7B8F6182EAB7516006A70D6 /* JDStatusBarNotification in Frameworks */ = {isa = PBXBuildFile; productRef = F7B8F6172EAB7516006A70D6 /* JDStatusBarNotification */; };
849+
F7B8F61A2EAB7521006A70D6 /* JDStatusBarNotification in Frameworks */ = {isa = PBXBuildFile; productRef = F7B8F6192EAB7521006A70D6 /* JDStatusBarNotification */; };
846850
F7B934FE2BDCFE1E002B2FC9 /* NCDragDrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B934FD2BDCFE1E002B2FC9 /* NCDragDrop.swift */; };
847851
F7BAADCB1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
848852
F7BAADCC1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7BAADB51ED5A87C00B7EAD4 /* NCManageDatabase.swift */; };
@@ -1010,6 +1014,7 @@
10101014
F7EF2AEC2E43157B0081B2C9 /* NCNotification.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7EF2AE82E43157B0081B2C9 /* NCNotification.storyboard */; };
10111015
F7EFA47825ADBA500083159A /* NCViewerProviderContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFA47725ADBA500083159A /* NCViewerProviderContextMenu.swift */; };
10121016
F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */; };
1017+
F7F0691D2EAB9DA300B3B13B /* NotificationPresenterUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F0691C2EAB9DA200B3B13B /* NotificationPresenterUI.swift */; };
10131018
F7F1FB9D2E27CE7200C79E20 /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; };
10141019
F7F1FB9E2E27CE7200C79E20 /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; };
10151020
F7F1FB9F2E27CE7200C79E20 /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; };
@@ -1914,6 +1919,7 @@
19141919
F7EF2AE92E43157B0081B2C9 /* NCNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNotification.swift; sourceTree = "<group>"; };
19151920
F7EFA47725ADBA500083159A /* NCViewerProviderContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCViewerProviderContextMenu.swift; sourceTree = "<group>"; };
19161921
F7EFC0CC256BF8DD00461AAD /* NCUserStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUserStatus.swift; sourceTree = "<group>"; };
1922+
F7F0691C2EAB9DA200B3B13B /* NotificationPresenterUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPresenterUI.swift; sourceTree = "<group>"; };
19171923
F7F3E58A2D3BB65000A32B14 /* NCNetworking+Recommendations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCNetworking+Recommendations.swift"; sourceTree = "<group>"; };
19181924
F7F4F0FD27ECDBDB008676F9 /* Inconsolata-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-SemiBold.ttf"; sourceTree = "<group>"; };
19191925
F7F4F0FE27ECDBDB008676F9 /* Inconsolata-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Inconsolata-Medium.ttf"; sourceTree = "<group>"; };
@@ -2029,6 +2035,7 @@
20292035
F711A4EF2AF932B900095DD8 /* SVGKitSwift in Frameworks */,
20302036
F710FC80277B7D2700AA9FBF /* RealmSwift in Frameworks */,
20312037
F74C863D2AEFBFD9009A1D4A /* LRUCache in Frameworks */,
2038+
F7B8F6182EAB7516006A70D6 /* JDStatusBarNotification in Frameworks */,
20322039
F72AD70F28C24BA1006CB92D /* NextcloudKit in Frameworks */,
20332040
F33EE6E72BF4C02600CA1A51 /* NIOSSL in Frameworks */,
20342041
F72CD01227A7E92400E59476 /* JGProgressHUD in Frameworks */,
@@ -2052,6 +2059,7 @@
20522059
F7160A7D2BE931DE0034DCB3 /* RealmSwift in Frameworks */,
20532060
F760DE052AE66EBE0027D78A /* KeychainAccess in Frameworks */,
20542061
F7A560462AE15D3D00BE8FD6 /* Queuer in Frameworks */,
2062+
F7B8F6162EAB7503006A70D6 /* JDStatusBarNotification in Frameworks */,
20552063
F783030D28B4C59A00B84583 /* SwiftEntryKit in Frameworks */,
20562064
F75379222AE2ADA100C0250E /* JGProgressHUD in Frameworks */,
20572065
);
@@ -2066,6 +2074,7 @@
20662074
F73ADD2426554FE20069EA0D /* SwiftEntryKit in Frameworks */,
20672075
F710FC84277B7D3500AA9FBF /* RealmSwift in Frameworks */,
20682076
F75379202AE2AD9400C0250E /* JGProgressHUD in Frameworks */,
2077+
F7B8F61A2EAB7521006A70D6 /* JDStatusBarNotification in Frameworks */,
20692078
F33EE6E92BF4C02D00CA1A51 /* NIOSSL in Frameworks */,
20702079
F72AD71328C24BCC006CB92D /* NextcloudKit in Frameworks */,
20712080
);
@@ -2081,6 +2090,7 @@
20812090
F788ECC7263AAAFA00ADC67F /* MarkdownKit in Frameworks */,
20822091
F3374AF02D78B01B002A38F9 /* BitCollections in Frameworks */,
20832092
F77BC3EB293E5268005F2B08 /* Swifter in Frameworks */,
2093+
F7B8F6142EAB64AD006A70D6 /* JDStatusBarNotification in Frameworks */,
20842094
F7BB7E4727A18C56009B9F29 /* Parchment in Frameworks */,
20852095
F33EE6E12BF4BDA500CA1A51 /* NIOSSL in Frameworks */,
20862096
F734B06628E75C0100E180D5 /* TLPhotoPicker in Frameworks */,
@@ -2757,6 +2767,7 @@
27572767
children = (
27582768
F769CA182966EA3C00039397 /* ComponentView.swift */,
27592769
F768823D2C0DD304001CF441 /* LazyView.swift */,
2770+
F7F0691C2EAB9DA200B3B13B /* NotificationPresenterUI.swift */,
27602771
F768823F2C0DD30B001CF441 /* ViewOnAppear.swift */,
27612772
F7BFFD272C8846020029A201 /* NCHud.swift */,
27622773
F75CA1462962F13700B01130 /* NCHUDView.swift */,
@@ -3654,6 +3665,7 @@
36543665
F74C863C2AEFBFD9009A1D4A /* LRUCache */,
36553666
F711A4EE2AF932B900095DD8 /* SVGKitSwift */,
36563667
F33EE6E62BF4C02600CA1A51 /* NIOSSL */,
3668+
F7B8F6172EAB7516006A70D6 /* JDStatusBarNotification */,
36573669
);
36583670
productName = "Share Ext";
36593671
productReference = F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */;
@@ -3682,6 +3694,7 @@
36823694
F760DE042AE66EBE0027D78A /* KeychainAccess */,
36833695
F7160A7C2BE931DE0034DCB3 /* RealmSwift */,
36843696
F33EE6E22BF4C00700CA1A51 /* NIOSSL */,
3697+
F7B8F6152EAB7503006A70D6 /* JDStatusBarNotification */,
36853698
);
36863699
productName = DashboardWidgetExtension;
36873700
productReference = F7346E1028B0EF5B006CE2D2 /* Widget.appex */;
@@ -3709,6 +3722,7 @@
37093722
F753791F2AE2AD9400C0250E /* JGProgressHUD */,
37103723
F760DE0A2AE66ED80027D78A /* KeychainAccess */,
37113724
F33EE6E82BF4C02D00CA1A51 /* NIOSSL */,
3725+
F7B8F6192EAB7521006A70D6 /* JDStatusBarNotification */,
37123726
);
37133727
productName = "File Provider Extension";
37143728
productReference = F771E3D020E2392D00AFB62D /* File Provider Extension.appex */;
@@ -3769,6 +3783,7 @@
37693783
F3374AF32D78B01B002A38F9 /* DequeModule */,
37703784
F3374AF52D78B01B002A38F9 /* HashTreeCollections */,
37713785
F3374AF72D78B01B002A38F9 /* HeapModule */,
3786+
F7B8F6132EAB64AD006A70D6 /* JDStatusBarNotification */,
37723787
);
37733788
productName = "Crypto Cloud";
37743789
productReference = F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */;
@@ -3952,6 +3967,7 @@
39523967
F33EE6EE2BF4C0FF00CA1A51 /* XCRemoteSwiftPackageReference "swift-nio" */,
39533968
F7D4BF4E2CA2ECCB00A5E746 /* XCRemoteSwiftPackageReference "vlckit-spm" */,
39543969
F3374AEE2D78B01B002A38F9 /* XCRemoteSwiftPackageReference "swift-collections" */,
3970+
F7B8F6122EAB64AD006A70D6 /* XCRemoteSwiftPackageReference "JDStatusBarNotification" */,
39553971
);
39563972
productRefGroup = F7F67B9F1A24D27800EE80DA;
39573973
projectDirPath = "";
@@ -4937,6 +4953,7 @@
49374953
F7CF06802E0FF3990063AD04 /* NCAppStateManager.swift in Sources */,
49384954
F7BAADCB1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */,
49394955
F768822A2C0DD1E7001CF441 /* NCSettingsModel.swift in Sources */,
4956+
F7F0691D2EAB9DA300B3B13B /* NotificationPresenterUI.swift in Sources */,
49404957
F737DA9D2B7B893C0063BAFC /* NCPasscode.swift in Sources */,
49414958
F77C97392953131000FDDD09 /* NCCameraRoll.swift in Sources */,
49424959
F7CADEFD2EA159210057849E /* NCMetadataTranfersSuccess.swift in Sources */,
@@ -6020,7 +6037,7 @@
60206037
CLANG_WARN_UNREACHABLE_CODE = YES;
60216038
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
60226039
COPY_PHASE_STRIP = NO;
6023-
CURRENT_PROJECT_VERSION = 7;
6040+
CURRENT_PROJECT_VERSION = 8;
60246041
DEBUG_INFORMATION_FORMAT = dwarf;
60256042
DEVELOPMENT_TEAM = NKUJUXUJ3B;
60266043
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -6086,7 +6103,7 @@
60866103
CLANG_WARN_UNREACHABLE_CODE = YES;
60876104
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
60886105
COPY_PHASE_STRIP = NO;
6089-
CURRENT_PROJECT_VERSION = 7;
6106+
CURRENT_PROJECT_VERSION = 8;
60906107
DEVELOPMENT_TEAM = NKUJUXUJ3B;
60916108
ENABLE_STRICT_OBJC_MSGSEND = YES;
60926109
ENABLE_TESTABILITY = YES;
@@ -6411,6 +6428,14 @@
64116428
minimumVersion = 1.0.0;
64126429
};
64136430
};
6431+
F7B8F6122EAB64AD006A70D6 /* XCRemoteSwiftPackageReference "JDStatusBarNotification" */ = {
6432+
isa = XCRemoteSwiftPackageReference;
6433+
repositoryURL = "https://github.com/calimarkus/JDStatusBarNotification";
6434+
requirement = {
6435+
kind = upToNextMajorVersion;
6436+
minimumVersion = 2.2.4;
6437+
};
6438+
};
64146439
F7BB7E4527A18C56009B9F29 /* XCRemoteSwiftPackageReference "Parchment" */ = {
64156440
isa = XCRemoteSwiftPackageReference;
64166441
repositoryURL = "https://github.com/rechsteiner/Parchment";
@@ -6929,6 +6954,26 @@
69296954
package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */;
69306955
productName = RealmSwift;
69316956
};
6957+
F7B8F6132EAB64AD006A70D6 /* JDStatusBarNotification */ = {
6958+
isa = XCSwiftPackageProductDependency;
6959+
package = F7B8F6122EAB64AD006A70D6 /* XCRemoteSwiftPackageReference "JDStatusBarNotification" */;
6960+
productName = JDStatusBarNotification;
6961+
};
6962+
F7B8F6152EAB7503006A70D6 /* JDStatusBarNotification */ = {
6963+
isa = XCSwiftPackageProductDependency;
6964+
package = F7B8F6122EAB64AD006A70D6 /* XCRemoteSwiftPackageReference "JDStatusBarNotification" */;
6965+
productName = JDStatusBarNotification;
6966+
};
6967+
F7B8F6172EAB7516006A70D6 /* JDStatusBarNotification */ = {
6968+
isa = XCSwiftPackageProductDependency;
6969+
package = F7B8F6122EAB64AD006A70D6 /* XCRemoteSwiftPackageReference "JDStatusBarNotification" */;
6970+
productName = JDStatusBarNotification;
6971+
};
6972+
F7B8F6192EAB7521006A70D6 /* JDStatusBarNotification */ = {
6973+
isa = XCSwiftPackageProductDependency;
6974+
package = F7B8F6122EAB64AD006A70D6 /* XCRemoteSwiftPackageReference "JDStatusBarNotification" */;
6975+
productName = JDStatusBarNotification;
6976+
};
69326977
F7BB7E4627A18C56009B9F29 /* Parchment */ = {
69336978
isa = XCSwiftPackageProductDependency;
69346979
package = F7BB7E4527A18C56009B9F29 /* XCRemoteSwiftPackageReference "Parchment" */;

Share/NCShareExtension.swift

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,33 @@ extension NCShareExtension {
411411
if metadata.isDirectoryE2EE {
412412
error = await NCNetworkingE2EEUpload().upload(metadata: metadata, session: session, controller: self)
413413
} else if metadata.chunk > 0 {
414-
let results = await NCNetworking.shared.uploadChunk(metadata: metadata, hud: hud)
414+
var numChunks = 0
415+
var countUpload: Int = 0
416+
var taskHandler: URLSessionTask?
417+
418+
hud.pieProgress(text: NSLocalizedString("_wait_file_preparation_", comment: ""), tapToCancelDetailText: true) {
419+
NotificationCenter.default.postOnMainThread(name: NextcloudKit.shared.nkCommonInstance.notificationCenterChunkedFileStop.rawValue)
420+
}
421+
422+
let results = await NCNetworking.shared.uploadChunkFile(metadata: metadata) { num in
423+
numChunks = num
424+
} counterChunk: { counter in
425+
self.hud.progress(num: Float(counter), total: Float(numChunks))
426+
} startFilesChunk: { _ in
427+
self.hud.pieProgress(text: NSLocalizedString("_keep_active_for_upload_", comment: ""), tapToCancelDetailText: true) {
428+
taskHandler?.cancel()
429+
}
430+
} requestHandler: { _ in
431+
self.hud.progress(num: Float(countUpload), total: Float(numChunks))
432+
countUpload += 1
433+
} taskHandler: { task in
434+
taskHandler = task
435+
} assembling: {
436+
self.hud.setText(NSLocalizedString("_wait_", comment: ""))
437+
}
438+
439+
hud.dismiss()
440+
415441
error = results.error
416442
} else {
417443
let fileNameLocalPath = utilityFileSystem.getDirectoryProviderStorageOcId(metadata.ocId,

iOSClient/AppDelegate.swift

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -240,16 +240,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
240240

241241
// Transfer success flush
242242
await NCNetworking.shared.metadataTranfersSuccess.flush()
243-
guard !expired else {
244-
return
245-
}
243+
guard !expired else { return }
246244

247245
// Discover new items for Auto Upload
248246
let numAutoUpload = await NCAutoUpload.shared.initAutoUpload()
249247
nkLog(tag: self.global.logTagBgSync, emoji: .start, message: "Auto upload found \(numAutoUpload) new items")
250-
guard !expired else {
251-
return
252-
}
248+
guard !expired else { return }
253249

254250
// Fetch METADATAS
255251
let metadatas = await NCManageDatabase.shared.getMetadataProcess()
@@ -264,9 +260,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
264260
}
265261

266262
for metadata in pendingCreateFolders {
267-
guard !expired else {
268-
return
269-
}
263+
guard !expired else { return }
264+
270265
let err = await NCNetworking.shared.createFolderForAutoUpload(
271266
serverUrlFileName: metadata.serverUrlFileName,
272267
account: metadata.account
@@ -283,7 +278,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
283278
let uploading = metadatas.lazy.filter { $0.status == self.global.metadataStatusUploading }.count
284279
let availableProcess = max(0, NCBrandOptions.shared.numMaximumProcess - (downloading + uploading))
285280

286-
// Start Auto Uploads (cap by available slots)
281+
// Start Auto Uploads
287282
let metadatasToUpload = Array(
288283
metadatas.lazy.filter {
289284
$0.status == self.global.metadataStatusWaitUpload &&
@@ -294,12 +289,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
294289
)
295290

296291
let cameraRoll = NCCameraRoll()
292+
297293
for metadata in metadatasToUpload {
298-
guard !expired else {
299-
return
300-
}
294+
guard !expired else { return }
301295

302-
// File exists for Auto Upload? skip it
296+
// File exists? skip it
303297
let error = await NCNetworking.shared.fileExists(serverUrlFileName: metadata.serverUrlFileName, account: metadata.account)
304298
if error == .success {
305299
await NCManageDatabase.shared.deleteMetadataAsync(id: metadata.ocId)
@@ -308,6 +302,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
308302

309303
// Expand seed into concrete metadatas (e.g., Live Photo pair)
310304
let extracted = await cameraRoll.extractCameraRoll(from: metadata)
305+
guard !expired else { return }
311306

312307
for metadata in extracted {
313308
// Sequential await keeps ordering and simplifies backpressure
@@ -317,6 +312,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
317312
} else {
318313
nkLog(tag: self.global.logTagBgSync, emoji: .error, message: "Upload failed \(metadata.fileName) -> \(metadata.serverUrl) [\(err.errorDescription)]")
319314
}
315+
guard !expired else { return }
320316
}
321317
}
322318
}
@@ -326,9 +322,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
326322
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
327323
nkLog(debug: "Handle events For background URLSession: \(identifier)")
328324

329-
if NCManageDatabase.shared.openRealmBackground() {
330-
WidgetCenter.shared.reloadAllTimelines()
331-
}
325+
NCManageDatabase.shared.openRealmBackground()
332326

333327
backgroundSessionCompletionHandler = completionHandler
334328
}

iOSClient/Data/NCManageDatabase.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ final class NCManageDatabase: @unchecked Sendable {
9595
}
9696
}
9797

98+
@discardableResult
9899
func openRealmBackground() -> Bool {
99100
let dirGroup = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
100101
let databaseFileUrl = dirGroup?.appendingPathComponent(NCGlobal.shared.appDatabaseNextcloud + "/" + databaseName)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// SPDX-FileCopyrightText: Nextcloud GmbH
2+
// SPDX-FileCopyrightText: 2025 Marino Faggiana
3+
// SPDX-License-Identifier: GPL-3.0-or-later
4+
5+
import SwiftUI
6+
7+
/// Wraps a SwiftUI view in a transparent `UIView` for use as a custom left or right view
8+
/// in JDStatusBarNotification. Useful to display animated SwiftUI symbols.
9+
@MainActor
10+
func makeHostingNotificationPresenterView<Content: View>(_ content: Content, size: CGSize) -> UIView {
11+
let host = UIHostingController(rootView: content)
12+
host.view.backgroundColor = .clear
13+
host.view.isUserInteractionEnabled = false
14+
host.view.frame = .init(origin: .zero, size: size)
15+
host.view.translatesAutoresizingMaskIntoConstraints = false
16+
return host.view
17+
}
18+
19+
/// Animated gear symbol for JDStatusBarNotification.
20+
struct NotificationPresenterGearSymbol: View {
21+
var body: some View {
22+
if #available(iOS 18.0, *) {
23+
Image(systemName: "gearshape.arrow.triangle.2.circlepath")
24+
.symbolEffect(.rotate, options: .repeat(.continuous))
25+
.font(.system(size: 20, weight: .regular))
26+
.foregroundStyle(.white)
27+
.padding(4)
28+
} else {
29+
Image(systemName: "gearshape.arrow.triangle.2.circlepath")
30+
.font(.system(size: 20, weight: .regular))
31+
.foregroundStyle(.white)
32+
.padding(4)
33+
}
34+
}
35+
}
36+
37+
/// Animated gear symbol for JDStatusBarNotification.
38+
struct NotificationPresenterTryArrowSymbol: View {
39+
var body: some View {
40+
if #available(iOS 18.0, *) {
41+
Image(systemName: "tray.and.arrow.down")
42+
.symbolEffect(.pulse.byLayer, options: .repeat(.continuous))
43+
.font(.system(size: 20, weight: .regular))
44+
.foregroundStyle(.white)
45+
.padding(4)
46+
} else {
47+
Image(systemName: "tray.and.arrow.down")
48+
.font(.system(size: 20, weight: .regular))
49+
.foregroundStyle(.white)
50+
.padding(4)
51+
}
52+
}
53+
}
54+
55+
/// Animated gear symbol for JDStatusBarNotification.
56+
struct NotificationPresenterArrowShapeSymbol: View {
57+
var body: some View {
58+
if #available(iOS 18.0, *) {
59+
Image(systemName: "arrowshape.up.circle")
60+
.symbolEffect(.breathe, options: .repeat(.continuous))
61+
.font(.system(size: 20, weight: .regular))
62+
.foregroundStyle(.white)
63+
.padding(4)
64+
} else {
65+
Image(systemName: "arrowshape.up.circle")
66+
.font(.system(size: 20, weight: .regular))
67+
.foregroundStyle(.white)
68+
.padding(4)
69+
}
70+
}
71+
}

0 commit comments

Comments
 (0)