capacitor-jpush-core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,241 @@
1
+ // JPushWrapper.swift
2
+ // Swift wrapper for JPush functionality
3
+
4
+ import Foundation
5
+ import UIKit
6
+
7
+ // Alias operation completion handler type
8
+ typealias JPushAliasCompletion = (Bool, Error?) -> Void
9
+
10
+ // UserDefaults key for saving launchOptions
11
+ private let kJPushLaunchOptionsKey = "JPushLaunchOptions"
12
+
13
+ class JPushWrapper: NSObject {
14
+
15
+ private static func showAlert(_ message: String) {
16
+ // Show native alert with launchOptions content for debugging
17
+ DispatchQueue.main.async {
18
+ let alertController = UIAlertController(title: "JPush", message: message, preferredStyle: .alert)
19
+
20
+ let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
21
+ alertController.addAction(okAction)
22
+
23
+ // Get the current root view controller
24
+ if let rootViewController = UIApplication.shared.windows.first?.rootViewController {
25
+ rootViewController.present(alertController, animated: true, completion: nil)
26
+ }
27
+ }
28
+ }
29
+
30
+ static func initJPush(withAppKey appKey: String, channel: String?, production: Bool) {
31
+
32
+ JPUSHService.setup(withOption: nil, appKey: appKey, channel: channel, apsForProduction: production)
33
+ if !production {
34
+ JPUSHService.setDebugMode()
35
+ }
36
+
37
+ // 初始化完成后清除保存的launchOptions
38
+ UserDefaults.standard.removeObject(forKey: kJPushLaunchOptionsKey)
39
+ }
40
+
41
+ /**
42
+ * Get registration ID
43
+ * @return Registration ID
44
+ */
45
+ static func registrationID() -> String {
46
+ return JPUSHService.registrationID()
47
+ }
48
+
49
+ /**
50
+ * Set alias
51
+ * @param alias Alias
52
+ * @param seq Sequence number, user-defined for operation identification
53
+ * @param completion Completion handler
54
+ */
55
+ static func setAlias(_ alias: String, seq: Int? = nil, completion: @escaping JPushAliasCompletion) {
56
+ let sequence = seq ?? 0
57
+ JPUSHService.setAlias(alias, completion: { (iResCode, iAlias, sequence) in
58
+ if iResCode == 0 {
59
+ completion(true, nil)
60
+ } else {
61
+ let error = NSError(domain: "JPush", code: Int(iResCode), userInfo: [NSLocalizedDescriptionKey: "Alias setting failed, error code: \(iResCode)"])
62
+ completion(false, error)
63
+ }
64
+ }, seq: sequence)
65
+ }
66
+
67
+ /**
68
+ * Delete alias
69
+ * @param seq Sequence number, user-defined for operation identification
70
+ * @param completion Completion handler
71
+ */
72
+ static func deleteAlias(seq: Int? = nil, completion: @escaping JPushAliasCompletion) {
73
+ let sequence = seq ?? 0
74
+ JPUSHService.deleteAlias({ (iResCode, iAlias, sequence) in
75
+ if iResCode == 0 {
76
+ completion(true, nil)
77
+ } else {
78
+ let error = NSError(domain: "JPush", code: Int(iResCode), userInfo: [NSLocalizedDescriptionKey: "Alias deletion failed, error code: \(iResCode)"])
79
+ completion(false, error)
80
+ }
81
+ }, seq: sequence)
82
+ }
83
+
84
+ /**
85
+ * Set tags
86
+ * @param tags Tags to set
87
+ * @param seq Sequence number, user-defined for operation identification
88
+ * @param completion Completion handler
89
+ */
90
+ static func setTags(_ tags: Set<String>, seq: Int? = nil, completion: @escaping JPushAliasCompletion) {
91
+ let sequence = seq ?? 0
92
+ JPUSHService.setTags(tags, completion: { (iResCode, iTags, sequence) in
93
+ if iResCode == 0 {
94
+ completion(true, nil)
95
+ } else {
96
+ let error = NSError(domain: "JPush", code: Int(iResCode), userInfo: [NSLocalizedDescriptionKey: "Tags setting failed, error code: \(iResCode)"])
97
+ completion(false, error)
98
+ }
99
+ }, seq: sequence)
100
+ }
101
+
102
+ /**
103
+ * Add tags
104
+ * @param tags Tags to add
105
+ * @param seq Sequence number, user-defined for operation identification
106
+ * @param completion Completion handler
107
+ */
108
+ static func addTags(_ tags: Set<String>, seq: Int? = nil, completion: @escaping JPushAliasCompletion) {
109
+ let sequence = seq ?? 0
110
+ JPUSHService.addTags(tags, completion: { (iResCode, iTags, sequence) in
111
+ if iResCode == 0 {
112
+ completion(true, nil)
113
+ } else {
114
+ let error = NSError(domain: "JPush", code: Int(iResCode), userInfo: [NSLocalizedDescriptionKey: "Tags adding failed, error code: \(iResCode)"])
115
+ completion(false, error)
116
+ }
117
+ }, seq: sequence)
118
+ }
119
+
120
+ /**
121
+ * Delete tags
122
+ * @param tags Tags to delete
123
+ * @param seq Sequence number, user-defined for operation identification
124
+ * @param completion Completion handler
125
+ */
126
+ static func deleteTags(_ tags: Set<String>, seq: Int? = nil, completion: @escaping JPushAliasCompletion) {
127
+ let sequence = seq ?? 0
128
+ JPUSHService.deleteTags(tags, completion: { (iResCode, iTags, sequence) in
129
+ if iResCode == 0 {
130
+ completion(true, nil)
131
+ } else {
132
+ let error = NSError(domain: "JPush", code: Int(iResCode), userInfo: [NSLocalizedDescriptionKey: "Tags deletion failed, error code: \(iResCode)"])
133
+ completion(false, error)
134
+ }
135
+ }, seq: sequence)
136
+ }
137
+
138
+ /**
139
+ * Clean all tags
140
+ * @param seq Sequence number, user-defined for operation identification
141
+ * @param completion Completion handler
142
+ */
143
+ static func cleanTags(seq: Int? = nil, completion: @escaping JPushAliasCompletion) {
144
+ let sequence = seq ?? 0
145
+ JPUSHService.cleanTags({ (iResCode, iTags, sequence) in
146
+ if iResCode == 0 {
147
+ completion(true, nil)
148
+ } else {
149
+ let error = NSError(domain: "JPush", code: Int(iResCode), userInfo: [NSLocalizedDescriptionKey: "Tags cleaning failed, error code: \(iResCode)"])
150
+ completion(false, error)
151
+ }
152
+ }, seq: sequence)
153
+ }
154
+
155
+ /**
156
+ * Request notification authorization
157
+ * @param completion Completion handler with authorization status
158
+ */
159
+ static func requestNotificationAuthorization(completion: @escaping (Bool) -> Void) {
160
+ JPUSHService.requestNotificationAuthorization { status in
161
+ let granted = status == .statusAuthorized || status == .statusProvisional
162
+ completion(granted)
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Handle remote notification
168
+ * @param userInfo Notification content
169
+ */
170
+ static func handleRemoteNotification(_ userInfo: [AnyHashable: Any]) {
171
+ JPUSHService.handleRemoteNotification(userInfo)
172
+ }
173
+
174
+ /**
175
+ * Register device token
176
+ * @param deviceToken Device token
177
+ */
178
+ static func registerDeviceToken(_ deviceToken: Data) {
179
+ JPUSHService.registerDeviceToken(deviceToken)
180
+ }
181
+
182
+ /**
183
+ * Set unread badge count
184
+ * @param badge Badge count, 0 means clear badge
185
+ */
186
+ static func setBadge(_ badge: Int) {
187
+
188
+ JPUSHService.setBadge(badge)
189
+
190
+ if #available(iOS 16.0, *) {
191
+ UNUserNotificationCenter.current().setBadgeCount(badge)
192
+ } else if (badge == 0) {
193
+ clearBadgeOnlyKeepNotifications()
194
+ } else {
195
+ UIApplication.shared.applicationIconBadgeNumber = badge
196
+ }
197
+ }
198
+
199
+ private static func clearBadgeOnlyKeepNotifications() {
200
+ UNUserNotificationCenter.current().getDeliveredNotifications { notifications in
201
+ let center = UNUserNotificationCenter.current()
202
+
203
+ notifications.forEach { notification in
204
+ // 关键修复:将只读的 UNNotificationContent 转为可变的 UNMutableNotificationContent
205
+ guard let mutableContent = notification.request.content.mutableCopy() as? UNMutableNotificationContent else {
206
+ print("❌ 无法转换为可变通知内容")
207
+ return
208
+ }
209
+
210
+ // 现在可以正常修改 badge(可变对象的可写属性)
211
+ mutableContent.badge = 0
212
+
213
+ // 重新创建通知请求(用可变内容)
214
+ let newRequest = UNNotificationRequest(
215
+ identifier: notification.request.identifier, // 复用原ID,覆盖原通知
216
+ content: mutableContent,
217
+ trigger: nil
218
+ )
219
+
220
+ center.add(newRequest) { error in
221
+ if let error = error {
222
+ print("❌ 更新通知角标失败:\(error.localizedDescription)")
223
+ }
224
+ }
225
+ }
226
+
227
+ let emptyContent = UNMutableNotificationContent() // 直接创建可变对象
228
+ emptyContent.badge = 0
229
+ let emptyRequest = UNNotificationRequest(
230
+ identifier: "clear_badge_only",
231
+ content: emptyContent,
232
+ trigger: nil
233
+ )
234
+ center.add(emptyRequest) { _ in
235
+ center.removeDeliveredNotifications(withIdentifiers: ["clear_badge_only"])
236
+ }
237
+
238
+ // JPUSHService.resetBadge()
239
+ }
240
+ }
241
+ }
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "capacitor-jpush-core",
3
+ "version": "0.0.1",
4
+ "description": "极光推送Capacitor插件,支持Android和iOS平台基本推送功能",
5
+ "keywords": [
6
+ "ionic",
7
+ "capacitor",
8
+ "plugin",
9
+ "native",
10
+ "android",
11
+ "ios",
12
+ "jpush",
13
+ "jiguang",
14
+ "core",
15
+ "极光推送",
16
+ "push notification",
17
+ "推送通知"
18
+ ],
19
+ "main": "dist/plugin.cjs.js",
20
+ "module": "dist/esm/index.js",
21
+ "types": "dist/esm/index.d.ts",
22
+ "unpkg": "dist/plugin.js",
23
+ "files": [
24
+ "android/src/main/",
25
+ "android/build.gradle",
26
+ "dist/",
27
+ "ios/Sources",
28
+ "Package.swift",
29
+ "CapacitorJpushCore.podspec"
30
+ ],
31
+ "author": "hybrid",
32
+ "maintainers":["hybrid"],
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/hybrid/capacitor-jpush-core.git"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/hybrid/capacitor-jpush-core/issues"
40
+ },
41
+ "scripts": {
42
+ "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
43
+ "verify:ios": "xcodebuild -scheme capacitor-jpush-core -destination generic/platform=iOS",
44
+ "verify:android": "cd android && ./gradlew clean build test && cd ..",
45
+ "verify:web": "npm run build",
46
+ "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
47
+ "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
48
+ "eslint": "eslint . --ext ts",
49
+ "prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
50
+ "swiftlint": "node-swiftlint",
51
+ "docgen": "docgen --api JPushPlugin --output-readme README.md --output-json dist/docs.json",
52
+ "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
53
+ "clean": "rimraf ./dist",
54
+ "watch": "tsc --watch",
55
+ "prepublishOnly": "npm run build"
56
+ },
57
+ "devDependencies": {
58
+ "@capacitor/android": "^7.0.0",
59
+ "@capacitor/core": "^7.0.0",
60
+ "@capacitor/docgen": "^0.3.0",
61
+ "@capacitor/ios": "^7.0.0",
62
+ "@ionic/eslint-config": "^0.4.0",
63
+ "@ionic/prettier-config": "^4.0.0",
64
+ "@ionic/swiftlint-config": "^2.0.0",
65
+ "@types/node": "^22.0.0",
66
+ "eslint": "^8.57.0",
67
+ "prettier": "^3.4.2",
68
+ "prettier-plugin-java": "^2.6.6",
69
+ "rimraf": "^6.0.1",
70
+ "rollup": "^4.30.1",
71
+ "swiftlint": "^2.0.0",
72
+ "typescript": "^5.9.3"
73
+ },
74
+ "peerDependencies": {
75
+ "@capacitor/core": ">=7.0.0"
76
+ },
77
+ "prettier": "@ionic/prettier-config",
78
+ "swiftlint": "@ionic/swiftlint-config",
79
+ "eslintConfig": {
80
+ "extends": "@ionic/eslint-config/recommended"
81
+ },
82
+ "capacitor": {
83
+ "ios": {
84
+ "src": "ios"
85
+ },
86
+ "android": {
87
+ "src": "android"
88
+ }
89
+ }
90
+ }