@capawesome/capacitor-silent-mode 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.
Files changed (36) hide show
  1. package/CapawesomeCapacitorSilentMode.podspec +17 -0
  2. package/LICENSE +21 -0
  3. package/Package.swift +28 -0
  4. package/README.md +242 -0
  5. package/android/build.gradle +58 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/java/io/capawesome/capacitorjs/plugins/silentmode/SilentMode.java +90 -0
  8. package/android/src/main/java/io/capawesome/capacitorjs/plugins/silentmode/SilentModePlugin.java +112 -0
  9. package/android/src/main/java/io/capawesome/capacitorjs/plugins/silentmode/classes/events/SilentModeChangeEvent.java +22 -0
  10. package/android/src/main/java/io/capawesome/capacitorjs/plugins/silentmode/classes/results/GetRingerModeResult.java +23 -0
  11. package/android/src/main/java/io/capawesome/capacitorjs/plugins/silentmode/classes/results/IsSilentResult.java +22 -0
  12. package/android/src/main/java/io/capawesome/capacitorjs/plugins/silentmode/interfaces/Callback.java +5 -0
  13. package/android/src/main/java/io/capawesome/capacitorjs/plugins/silentmode/interfaces/NonEmptyResultCallback.java +7 -0
  14. package/android/src/main/java/io/capawesome/capacitorjs/plugins/silentmode/interfaces/Result.java +7 -0
  15. package/android/src/main/res/.gitkeep +0 -0
  16. package/dist/docs.json +222 -0
  17. package/dist/esm/definitions.d.ts +92 -0
  18. package/dist/esm/definitions.js +2 -0
  19. package/dist/esm/definitions.js.map +1 -0
  20. package/dist/esm/index.d.ts +4 -0
  21. package/dist/esm/index.js +7 -0
  22. package/dist/esm/index.js.map +1 -0
  23. package/dist/esm/web.d.ts +6 -0
  24. package/dist/esm/web.js +10 -0
  25. package/dist/esm/web.js.map +1 -0
  26. package/dist/plugin.cjs.js +24 -0
  27. package/dist/plugin.cjs.js.map +1 -0
  28. package/dist/plugin.js +27 -0
  29. package/dist/plugin.js.map +1 -0
  30. package/ios/Plugin/Classes/Events/SilentModeChangeEvent.swift +16 -0
  31. package/ios/Plugin/Classes/Results/IsSilentResult.swift +16 -0
  32. package/ios/Plugin/Info.plist +24 -0
  33. package/ios/Plugin/Protocols/Result.swift +5 -0
  34. package/ios/Plugin/SilentMode.swift +177 -0
  35. package/ios/Plugin/SilentModePlugin.swift +74 -0
  36. package/package.json +91 -0
package/dist/docs.json ADDED
@@ -0,0 +1,222 @@
1
+ {
2
+ "api": {
3
+ "name": "SilentModePlugin",
4
+ "slug": "silentmodeplugin",
5
+ "docs": "",
6
+ "tags": [],
7
+ "methods": [
8
+ {
9
+ "name": "getRingerMode",
10
+ "signature": "() => Promise<GetRingerModeResult>",
11
+ "parameters": [],
12
+ "returns": "Promise<GetRingerModeResult>",
13
+ "tags": [
14
+ {
15
+ "name": "since",
16
+ "text": "0.1.0"
17
+ }
18
+ ],
19
+ "docs": "Get the current ringer mode of the device.\n\nOnly available on Android.",
20
+ "complexTypes": [
21
+ "GetRingerModeResult"
22
+ ],
23
+ "slug": "getringermode"
24
+ },
25
+ {
26
+ "name": "isSilent",
27
+ "signature": "() => Promise<IsSilentResult>",
28
+ "parameters": [],
29
+ "returns": "Promise<IsSilentResult>",
30
+ "tags": [
31
+ {
32
+ "name": "since",
33
+ "text": "0.1.0"
34
+ }
35
+ ],
36
+ "docs": "Get the current silent mode state of the device.\n\nOn Android, the device is considered silent if the ringer mode is not set\nto normal (that is, either vibrate or silent).\n\nOn iOS, there is no public API to read the ring/silent switch. The state is\ntherefore determined using a heuristic that plays a short muted system sound\nand measures how long it takes to complete. The result may be inaccurate\nwhile other audio is playing.\n\nOnly available on Android and iOS.",
37
+ "complexTypes": [
38
+ "IsSilentResult"
39
+ ],
40
+ "slug": "issilent"
41
+ },
42
+ {
43
+ "name": "addListener",
44
+ "signature": "(eventName: 'silentModeChange', listenerFunc: (event: SilentModeChangeEvent) => void) => Promise<PluginListenerHandle>",
45
+ "parameters": [
46
+ {
47
+ "name": "eventName",
48
+ "docs": "",
49
+ "type": "'silentModeChange'"
50
+ },
51
+ {
52
+ "name": "listenerFunc",
53
+ "docs": "",
54
+ "type": "(event: SilentModeChangeEvent) => void"
55
+ }
56
+ ],
57
+ "returns": "Promise<PluginListenerHandle>",
58
+ "tags": [
59
+ {
60
+ "name": "since",
61
+ "text": "0.1.0"
62
+ }
63
+ ],
64
+ "docs": "Listen for changes to the silent mode state of the device.\n\nThe device is only observed while at least one listener is attached.\n\nOn iOS, the state is polled on a timer while the app is in the foreground\nand the listener is not called while the app is in the background.\n\nOnly available on Android and iOS.",
65
+ "complexTypes": [
66
+ "PluginListenerHandle",
67
+ "SilentModeChangeEvent"
68
+ ],
69
+ "slug": "addlistenersilentmodechange-"
70
+ },
71
+ {
72
+ "name": "removeAllListeners",
73
+ "signature": "() => Promise<void>",
74
+ "parameters": [],
75
+ "returns": "Promise<void>",
76
+ "tags": [
77
+ {
78
+ "name": "since",
79
+ "text": "0.1.0"
80
+ }
81
+ ],
82
+ "docs": "Remove all listeners for this plugin.",
83
+ "complexTypes": [],
84
+ "slug": "removealllisteners"
85
+ }
86
+ ],
87
+ "properties": []
88
+ },
89
+ "interfaces": [
90
+ {
91
+ "name": "GetRingerModeResult",
92
+ "slug": "getringermoderesult",
93
+ "docs": "",
94
+ "tags": [
95
+ {
96
+ "text": "0.1.0",
97
+ "name": "since"
98
+ }
99
+ ],
100
+ "methods": [],
101
+ "properties": [
102
+ {
103
+ "name": "mode",
104
+ "tags": [
105
+ {
106
+ "text": "'normal'",
107
+ "name": "example"
108
+ },
109
+ {
110
+ "text": "0.1.0",
111
+ "name": "since"
112
+ }
113
+ ],
114
+ "docs": "The current ringer mode of the device.",
115
+ "complexTypes": [
116
+ "RingerMode"
117
+ ],
118
+ "type": "RingerMode"
119
+ }
120
+ ]
121
+ },
122
+ {
123
+ "name": "IsSilentResult",
124
+ "slug": "issilentresult",
125
+ "docs": "",
126
+ "tags": [
127
+ {
128
+ "text": "0.1.0",
129
+ "name": "since"
130
+ }
131
+ ],
132
+ "methods": [],
133
+ "properties": [
134
+ {
135
+ "name": "silent",
136
+ "tags": [
137
+ {
138
+ "text": "true",
139
+ "name": "example"
140
+ },
141
+ {
142
+ "text": "0.1.0",
143
+ "name": "since"
144
+ }
145
+ ],
146
+ "docs": "Whether the device is currently in silent mode.",
147
+ "complexTypes": [],
148
+ "type": "boolean"
149
+ }
150
+ ]
151
+ },
152
+ {
153
+ "name": "PluginListenerHandle",
154
+ "slug": "pluginlistenerhandle",
155
+ "docs": "",
156
+ "tags": [],
157
+ "methods": [],
158
+ "properties": [
159
+ {
160
+ "name": "remove",
161
+ "tags": [],
162
+ "docs": "",
163
+ "complexTypes": [],
164
+ "type": "() => Promise<void>"
165
+ }
166
+ ]
167
+ },
168
+ {
169
+ "name": "SilentModeChangeEvent",
170
+ "slug": "silentmodechangeevent",
171
+ "docs": "",
172
+ "tags": [
173
+ {
174
+ "text": "0.1.0",
175
+ "name": "since"
176
+ }
177
+ ],
178
+ "methods": [],
179
+ "properties": [
180
+ {
181
+ "name": "silent",
182
+ "tags": [
183
+ {
184
+ "text": "true",
185
+ "name": "example"
186
+ },
187
+ {
188
+ "text": "0.1.0",
189
+ "name": "since"
190
+ }
191
+ ],
192
+ "docs": "Whether the device is currently in silent mode.",
193
+ "complexTypes": [],
194
+ "type": "boolean"
195
+ }
196
+ ]
197
+ }
198
+ ],
199
+ "enums": [],
200
+ "typeAliases": [
201
+ {
202
+ "name": "RingerMode",
203
+ "slug": "ringermode",
204
+ "docs": "The ringer mode of the device.\n\n- `normal`: The device plays sounds and rings for incoming calls.\n- `silent`: The device is silent and does not vibrate.\n- `vibrate`: The device is silent but vibrates.",
205
+ "types": [
206
+ {
207
+ "text": "'normal'",
208
+ "complexTypes": []
209
+ },
210
+ {
211
+ "text": "'silent'",
212
+ "complexTypes": []
213
+ },
214
+ {
215
+ "text": "'vibrate'",
216
+ "complexTypes": []
217
+ }
218
+ ]
219
+ }
220
+ ],
221
+ "pluginConfigs": []
222
+ }
@@ -0,0 +1,92 @@
1
+ import type { PluginListenerHandle } from '@capacitor/core';
2
+ export interface SilentModePlugin {
3
+ /**
4
+ * Get the current ringer mode of the device.
5
+ *
6
+ * Only available on Android.
7
+ *
8
+ * @since 0.1.0
9
+ */
10
+ getRingerMode(): Promise<GetRingerModeResult>;
11
+ /**
12
+ * Get the current silent mode state of the device.
13
+ *
14
+ * On Android, the device is considered silent if the ringer mode is not set
15
+ * to normal (that is, either vibrate or silent).
16
+ *
17
+ * On iOS, there is no public API to read the ring/silent switch. The state is
18
+ * therefore determined using a heuristic that plays a short muted system sound
19
+ * and measures how long it takes to complete. The result may be inaccurate
20
+ * while other audio is playing.
21
+ *
22
+ * Only available on Android and iOS.
23
+ *
24
+ * @since 0.1.0
25
+ */
26
+ isSilent(): Promise<IsSilentResult>;
27
+ /**
28
+ * Listen for changes to the silent mode state of the device.
29
+ *
30
+ * The device is only observed while at least one listener is attached.
31
+ *
32
+ * On iOS, the state is polled on a timer while the app is in the foreground
33
+ * and the listener is not called while the app is in the background.
34
+ *
35
+ * Only available on Android and iOS.
36
+ *
37
+ * @since 0.1.0
38
+ */
39
+ addListener(eventName: 'silentModeChange', listenerFunc: (event: SilentModeChangeEvent) => void): Promise<PluginListenerHandle>;
40
+ /**
41
+ * Remove all listeners for this plugin.
42
+ *
43
+ * @since 0.1.0
44
+ */
45
+ removeAllListeners(): Promise<void>;
46
+ }
47
+ /**
48
+ * @since 0.1.0
49
+ */
50
+ export interface IsSilentResult {
51
+ /**
52
+ * Whether the device is currently in silent mode.
53
+ *
54
+ * @example true
55
+ * @since 0.1.0
56
+ */
57
+ silent: boolean;
58
+ }
59
+ /**
60
+ * @since 0.1.0
61
+ */
62
+ export interface GetRingerModeResult {
63
+ /**
64
+ * The current ringer mode of the device.
65
+ *
66
+ * @example 'normal'
67
+ * @since 0.1.0
68
+ */
69
+ mode: RingerMode;
70
+ }
71
+ /**
72
+ * @since 0.1.0
73
+ */
74
+ export interface SilentModeChangeEvent {
75
+ /**
76
+ * Whether the device is currently in silent mode.
77
+ *
78
+ * @example true
79
+ * @since 0.1.0
80
+ */
81
+ silent: boolean;
82
+ }
83
+ /**
84
+ * The ringer mode of the device.
85
+ *
86
+ * - `normal`: The device plays sounds and rings for incoming calls.
87
+ * - `silent`: The device is silent and does not vibrate.
88
+ * - `vibrate`: The device is silent but vibrates.
89
+ *
90
+ * @since 0.1.0
91
+ */
92
+ export type RingerMode = 'normal' | 'silent' | 'vibrate';
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=definitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\n\nexport interface SilentModePlugin {\n /**\n * Get the current ringer mode of the device.\n *\n * Only available on Android.\n *\n * @since 0.1.0\n */\n getRingerMode(): Promise<GetRingerModeResult>;\n /**\n * Get the current silent mode state of the device.\n *\n * On Android, the device is considered silent if the ringer mode is not set\n * to normal (that is, either vibrate or silent).\n *\n * On iOS, there is no public API to read the ring/silent switch. The state is\n * therefore determined using a heuristic that plays a short muted system sound\n * and measures how long it takes to complete. The result may be inaccurate\n * while other audio is playing.\n *\n * Only available on Android and iOS.\n *\n * @since 0.1.0\n */\n isSilent(): Promise<IsSilentResult>;\n /**\n * Listen for changes to the silent mode state of the device.\n *\n * The device is only observed while at least one listener is attached.\n *\n * On iOS, the state is polled on a timer while the app is in the foreground\n * and the listener is not called while the app is in the background.\n *\n * Only available on Android and iOS.\n *\n * @since 0.1.0\n */\n addListener(\n eventName: 'silentModeChange',\n listenerFunc: (event: SilentModeChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n /**\n * Remove all listeners for this plugin.\n *\n * @since 0.1.0\n */\n removeAllListeners(): Promise<void>;\n}\n\n/**\n * @since 0.1.0\n */\nexport interface IsSilentResult {\n /**\n * Whether the device is currently in silent mode.\n *\n * @example true\n * @since 0.1.0\n */\n silent: boolean;\n}\n\n/**\n * @since 0.1.0\n */\nexport interface GetRingerModeResult {\n /**\n * The current ringer mode of the device.\n *\n * @example 'normal'\n * @since 0.1.0\n */\n mode: RingerMode;\n}\n\n/**\n * @since 0.1.0\n */\nexport interface SilentModeChangeEvent {\n /**\n * Whether the device is currently in silent mode.\n *\n * @example true\n * @since 0.1.0\n */\n silent: boolean;\n}\n\n/**\n * The ringer mode of the device.\n *\n * - `normal`: The device plays sounds and rings for incoming calls.\n * - `silent`: The device is silent and does not vibrate.\n * - `vibrate`: The device is silent but vibrates.\n *\n * @since 0.1.0\n */\nexport type RingerMode = 'normal' | 'silent' | 'vibrate';\n"]}
@@ -0,0 +1,4 @@
1
+ import type { SilentModePlugin } from './definitions';
2
+ declare const SilentMode: SilentModePlugin;
3
+ export * from './definitions';
4
+ export { SilentMode };
@@ -0,0 +1,7 @@
1
+ import { registerPlugin } from '@capacitor/core';
2
+ const SilentMode = registerPlugin('SilentMode', {
3
+ web: () => import('./web').then(m => new m.SilentModeWeb()),
4
+ });
5
+ export * from './definitions';
6
+ export { SilentMode };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,UAAU,GAAG,cAAc,CAAmB,YAAY,EAAE;IAChE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;CAC5D,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { SilentModePlugin } from './definitions';\n\nconst SilentMode = registerPlugin<SilentModePlugin>('SilentMode', {\n web: () => import('./web').then(m => new m.SilentModeWeb()),\n});\n\nexport * from './definitions';\nexport { SilentMode };\n"]}
@@ -0,0 +1,6 @@
1
+ import { WebPlugin } from '@capacitor/core';
2
+ import type { GetRingerModeResult, IsSilentResult, SilentModePlugin } from './definitions';
3
+ export declare class SilentModeWeb extends WebPlugin implements SilentModePlugin {
4
+ getRingerMode(): Promise<GetRingerModeResult>;
5
+ isSilent(): Promise<IsSilentResult>;
6
+ }
@@ -0,0 +1,10 @@
1
+ import { WebPlugin } from '@capacitor/core';
2
+ export class SilentModeWeb extends WebPlugin {
3
+ async getRingerMode() {
4
+ throw this.unimplemented('Not implemented on web.');
5
+ }
6
+ async isSilent() {
7
+ throw this.unimplemented('Not implemented on web.');
8
+ }
9
+ }
10
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQ5C,MAAM,OAAO,aAAc,SAAQ,SAAS;IAC1C,KAAK,CAAC,aAAa;QACjB,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;IACtD,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type {\n GetRingerModeResult,\n IsSilentResult,\n SilentModePlugin,\n} from './definitions';\n\nexport class SilentModeWeb extends WebPlugin implements SilentModePlugin {\n async getRingerMode(): Promise<GetRingerModeResult> {\n throw this.unimplemented('Not implemented on web.');\n }\n\n async isSilent(): Promise<IsSilentResult> {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n"]}
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ var core = require('@capacitor/core');
4
+
5
+ const SilentMode = core.registerPlugin('SilentMode', {
6
+ web: () => Promise.resolve().then(function () { return web; }).then(m => new m.SilentModeWeb()),
7
+ });
8
+
9
+ class SilentModeWeb extends core.WebPlugin {
10
+ async getRingerMode() {
11
+ throw this.unimplemented('Not implemented on web.');
12
+ }
13
+ async isSilent() {
14
+ throw this.unimplemented('Not implemented on web.');
15
+ }
16
+ }
17
+
18
+ var web = /*#__PURE__*/Object.freeze({
19
+ __proto__: null,
20
+ SilentModeWeb: SilentModeWeb
21
+ });
22
+
23
+ exports.SilentMode = SilentMode;
24
+ //# sourceMappingURL=plugin.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst SilentMode = registerPlugin('SilentMode', {\n web: () => import('./web').then(m => new m.SilentModeWeb()),\n});\nexport * from './definitions';\nexport { SilentMode };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class SilentModeWeb extends WebPlugin {\n async getRingerMode() {\n throw this.unimplemented('Not implemented on web.');\n }\n async isSilent() {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,UAAU,GAAGA,mBAAc,CAAC,YAAY,EAAE;AAChD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;AAC/D,CAAC;;ACFM,MAAM,aAAa,SAASC,cAAS,CAAC;AAC7C,IAAI,MAAM,aAAa,GAAG;AAC1B,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ,IAAI,MAAM,QAAQ,GAAG;AACrB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;AAC3D,IAAI;AACJ;;;;;;;;;"}
package/dist/plugin.js ADDED
@@ -0,0 +1,27 @@
1
+ var capacitorSilentMode = (function (exports, core) {
2
+ 'use strict';
3
+
4
+ const SilentMode = core.registerPlugin('SilentMode', {
5
+ web: () => Promise.resolve().then(function () { return web; }).then(m => new m.SilentModeWeb()),
6
+ });
7
+
8
+ class SilentModeWeb extends core.WebPlugin {
9
+ async getRingerMode() {
10
+ throw this.unimplemented('Not implemented on web.');
11
+ }
12
+ async isSilent() {
13
+ throw this.unimplemented('Not implemented on web.');
14
+ }
15
+ }
16
+
17
+ var web = /*#__PURE__*/Object.freeze({
18
+ __proto__: null,
19
+ SilentModeWeb: SilentModeWeb
20
+ });
21
+
22
+ exports.SilentMode = SilentMode;
23
+
24
+ return exports;
25
+
26
+ })({}, capacitorExports);
27
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst SilentMode = registerPlugin('SilentMode', {\n web: () => import('./web').then(m => new m.SilentModeWeb()),\n});\nexport * from './definitions';\nexport { SilentMode };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class SilentModeWeb extends WebPlugin {\n async getRingerMode() {\n throw this.unimplemented('Not implemented on web.');\n }\n async isSilent() {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,UAAU,GAAGA,mBAAc,CAAC,YAAY,EAAE;IAChD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;IAC/D,CAAC;;ICFM,MAAM,aAAa,SAASC,cAAS,CAAC;IAC7C,IAAI,MAAM,aAAa,GAAG;IAC1B,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ,IAAI,MAAM,QAAQ,GAAG;IACrB,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D,IAAI;IACJ;;;;;;;;;;;;;;;"}
@@ -0,0 +1,16 @@
1
+ import Foundation
2
+ import Capacitor
3
+
4
+ @objc public class SilentModeChangeEvent: NSObject, Result {
5
+ let silent: Bool
6
+
7
+ init(silent: Bool) {
8
+ self.silent = silent
9
+ }
10
+
11
+ @objc public func toJSObject() -> AnyObject {
12
+ var result = JSObject()
13
+ result["silent"] = silent
14
+ return result as AnyObject
15
+ }
16
+ }
@@ -0,0 +1,16 @@
1
+ import Foundation
2
+ import Capacitor
3
+
4
+ @objc public class IsSilentResult: NSObject, Result {
5
+ let silent: Bool
6
+
7
+ init(silent: Bool) {
8
+ self.silent = silent
9
+ }
10
+
11
+ @objc public func toJSObject() -> AnyObject {
12
+ var result = JSObject()
13
+ result["silent"] = silent
14
+ return result as AnyObject
15
+ }
16
+ }
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
7
+ <key>CFBundleExecutable</key>
8
+ <string>$(EXECUTABLE_NAME)</string>
9
+ <key>CFBundleIdentifier</key>
10
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11
+ <key>CFBundleInfoDictionaryVersion</key>
12
+ <string>6.0</string>
13
+ <key>CFBundleName</key>
14
+ <string>$(PRODUCT_NAME)</string>
15
+ <key>CFBundlePackageType</key>
16
+ <string>FMWK</string>
17
+ <key>CFBundleShortVersionString</key>
18
+ <string>1.0</string>
19
+ <key>CFBundleVersion</key>
20
+ <string>$(CURRENT_PROJECT_VERSION)</string>
21
+ <key>NSPrincipalClass</key>
22
+ <string></string>
23
+ </dict>
24
+ </plist>
@@ -0,0 +1,5 @@
1
+ import Capacitor
2
+
3
+ @objc public protocol Result {
4
+ @objc func toJSObject() -> AnyObject
5
+ }
@@ -0,0 +1,177 @@
1
+ import Foundation
2
+ import AudioToolbox
3
+ import UIKit
4
+
5
+ @objc public class SilentMode: NSObject {
6
+ private let plugin: SilentModePlugin
7
+ private var hasSound = false
8
+ private var isObserving = false
9
+ private var lastSilent: Bool?
10
+ private let pollingIntervalInSeconds: TimeInterval = 1.5
11
+ private let queue = DispatchQueue(label: "io.capawesome.capacitorjs.plugins.silentmode")
12
+ private let soundDurationInSeconds: TimeInterval = 0.5
13
+ private var soundId: SystemSoundID = 0
14
+ private var timer: Timer?
15
+
16
+ init(plugin: SilentModePlugin) {
17
+ self.plugin = plugin
18
+ super.init()
19
+ self.prepareSound()
20
+ }
21
+
22
+ deinit {
23
+ if hasSound {
24
+ AudioServicesDisposeSystemSoundID(soundId)
25
+ }
26
+ NotificationCenter.default.removeObserver(self)
27
+ }
28
+
29
+ @objc public func isSilent(completion: @escaping (IsSilentResult?, Error?) -> Void) {
30
+ measureSilent { silent in
31
+ completion(IsSilentResult(silent: silent), nil)
32
+ }
33
+ }
34
+
35
+ func startObserving() {
36
+ DispatchQueue.main.async { [weak self] in
37
+ guard let self = self, !self.isObserving else {
38
+ return
39
+ }
40
+ self.isObserving = true
41
+ NotificationCenter.default.addObserver(
42
+ self,
43
+ selector: #selector(self.handleDidBecomeActive),
44
+ name: UIApplication.didBecomeActiveNotification,
45
+ object: nil
46
+ )
47
+ NotificationCenter.default.addObserver(
48
+ self,
49
+ selector: #selector(self.handleDidEnterBackground),
50
+ name: UIApplication.didEnterBackgroundNotification,
51
+ object: nil
52
+ )
53
+ if UIApplication.shared.applicationState != .background {
54
+ self.startTimer()
55
+ }
56
+ }
57
+ }
58
+
59
+ func stopObserving() {
60
+ DispatchQueue.main.async { [weak self] in
61
+ guard let self = self, self.isObserving else {
62
+ return
63
+ }
64
+ self.isObserving = false
65
+ self.lastSilent = nil
66
+ NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
67
+ NotificationCenter.default.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil)
68
+ self.stopTimer()
69
+ }
70
+ }
71
+
72
+ private func createSilentSoundFile() -> URL? {
73
+ let sampleRate = 44100
74
+ let numberOfChannels = 1
75
+ let bitsPerSample = 16
76
+ let numberOfSamples = Int(Double(sampleRate) * soundDurationInSeconds)
77
+ let blockAlign = numberOfChannels * bitsPerSample / 8
78
+ let byteRate = sampleRate * blockAlign
79
+ let dataSize = numberOfSamples * blockAlign
80
+
81
+ var data = Data()
82
+ func appendUInt16(_ value: UInt16) {
83
+ var littleEndian = value.littleEndian
84
+ withUnsafeBytes(of: &littleEndian) { data.append(contentsOf: $0) }
85
+ }
86
+ func appendUInt32(_ value: UInt32) {
87
+ var littleEndian = value.littleEndian
88
+ withUnsafeBytes(of: &littleEndian) { data.append(contentsOf: $0) }
89
+ }
90
+
91
+ data.append(contentsOf: Array("RIFF".utf8))
92
+ appendUInt32(UInt32(36 + dataSize))
93
+ data.append(contentsOf: Array("WAVE".utf8))
94
+ data.append(contentsOf: Array("fmt ".utf8))
95
+ appendUInt32(16)
96
+ appendUInt16(1)
97
+ appendUInt16(UInt16(numberOfChannels))
98
+ appendUInt32(UInt32(sampleRate))
99
+ appendUInt32(UInt32(byteRate))
100
+ appendUInt16(UInt16(blockAlign))
101
+ appendUInt16(UInt16(bitsPerSample))
102
+ data.append(contentsOf: Array("data".utf8))
103
+ appendUInt32(UInt32(dataSize))
104
+ data.append(Data(count: dataSize))
105
+
106
+ let url = FileManager.default.temporaryDirectory.appendingPathComponent("capawesome_capacitor_silent_mode.wav")
107
+ do {
108
+ try data.write(to: url)
109
+ return url
110
+ } catch {
111
+ return nil
112
+ }
113
+ }
114
+
115
+ @objc private func handleDidBecomeActive() {
116
+ if isObserving {
117
+ startTimer()
118
+ }
119
+ }
120
+
121
+ @objc private func handleDidEnterBackground() {
122
+ stopTimer()
123
+ }
124
+
125
+ private func handleSilentModeCheck() {
126
+ measureSilent { [weak self] silent in
127
+ DispatchQueue.main.async {
128
+ guard let self = self else {
129
+ return
130
+ }
131
+ let previousSilent = self.lastSilent
132
+ self.lastSilent = silent
133
+ if let previousSilent = previousSilent, previousSilent != silent {
134
+ self.plugin.notifySilentModeChangeListeners(SilentModeChangeEvent(silent: silent))
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ private func measureSilent(completion: @escaping (Bool) -> Void) {
141
+ queue.async { [weak self] in
142
+ guard let self = self, self.hasSound else {
143
+ completion(false)
144
+ return
145
+ }
146
+ let semaphore = DispatchSemaphore(value: 0)
147
+ let startTime = Date()
148
+ AudioServicesPlaySystemSoundWithCompletion(self.soundId) {
149
+ let elapsed = Date().timeIntervalSince(startTime)
150
+ completion(elapsed < self.soundDurationInSeconds / 2)
151
+ semaphore.signal()
152
+ }
153
+ semaphore.wait()
154
+ }
155
+ }
156
+
157
+ private func prepareSound() {
158
+ guard let url = createSilentSoundFile() else {
159
+ return
160
+ }
161
+ let status = AudioServicesCreateSystemSoundID(url as CFURL, &soundId)
162
+ hasSound = status == kAudioServicesNoError
163
+ }
164
+
165
+ private func startTimer() {
166
+ stopTimer()
167
+ timer = Timer.scheduledTimer(withTimeInterval: pollingIntervalInSeconds, repeats: true) { [weak self] _ in
168
+ self?.handleSilentModeCheck()
169
+ }
170
+ handleSilentModeCheck()
171
+ }
172
+
173
+ private func stopTimer() {
174
+ timer?.invalidate()
175
+ timer = nil
176
+ }
177
+ }