@capgo/capacitor-screen-orientation 7.0.0
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.
- package/CapgoCapacitorScreenOrientation.podspec +17 -0
- package/LICENSE +373 -0
- package/Package.swift +28 -0
- package/README.md +364 -0
- package/android/build.gradle +58 -0
- package/android/src/main/java/ee/forgr/capacitor/screenorientation/CapacitorScreenOrientationPlugin.java +277 -0
- package/dist/docs.json +513 -0
- package/dist/esm/definitions.d.ts +302 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +20 -0
- package/dist/esm/web.js +81 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +95 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +98 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/CapacitorScreenOrientationPlugin/CapacitorScreenOrientationPlugin.swift +287 -0
- package/ios/Tests/CapacitorScreenOrientationPluginTests/.gitkeep +0 -0
- package/package.json +92 -0
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
var capacitorScreenOrientation = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const ScreenOrientation = core.registerPlugin('CapacitorScreenOrientation', {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapacitorScreenOrientationWeb()),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
class CapacitorScreenOrientationWeb extends core.WebPlugin {
|
|
9
|
+
constructor() {
|
|
10
|
+
var _a;
|
|
11
|
+
super();
|
|
12
|
+
this.pluginVersion = '1.0.0';
|
|
13
|
+
if ((_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation) {
|
|
14
|
+
window.screen.orientation.addEventListener('change', () => {
|
|
15
|
+
this.notifyListeners('screenOrientationChange', {
|
|
16
|
+
type: this.mapOrientationType(window.screen.orientation.type),
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async orientation() {
|
|
22
|
+
var _a;
|
|
23
|
+
if (!((_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation)) {
|
|
24
|
+
throw this.unavailable('Screen Orientation API not available');
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
type: this.mapOrientationType(window.screen.orientation.type),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async lock(options) {
|
|
31
|
+
var _a;
|
|
32
|
+
const screenOrientation = (_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation;
|
|
33
|
+
if (!(screenOrientation === null || screenOrientation === void 0 ? void 0 : screenOrientation.lock)) {
|
|
34
|
+
throw this.unavailable('Screen Orientation lock not available');
|
|
35
|
+
}
|
|
36
|
+
// bypassOrientationLock is only supported on iOS native platform
|
|
37
|
+
// Silently ignore it on web
|
|
38
|
+
try {
|
|
39
|
+
await screenOrientation.lock(options.orientation);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw new Error(`Failed to lock orientation: ${error}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async unlock() {
|
|
46
|
+
var _a;
|
|
47
|
+
const screenOrientation = (_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation;
|
|
48
|
+
if (!(screenOrientation === null || screenOrientation === void 0 ? void 0 : screenOrientation.unlock)) {
|
|
49
|
+
throw this.unavailable('Screen Orientation unlock not available');
|
|
50
|
+
}
|
|
51
|
+
screenOrientation.unlock();
|
|
52
|
+
}
|
|
53
|
+
async startOrientationTracking(_options) {
|
|
54
|
+
// Motion-based orientation tracking is only supported on iOS
|
|
55
|
+
// Silently ignore on web
|
|
56
|
+
}
|
|
57
|
+
async stopOrientationTracking() {
|
|
58
|
+
// Motion-based orientation tracking is only supported on iOS
|
|
59
|
+
// Silently ignore on web
|
|
60
|
+
}
|
|
61
|
+
async isOrientationLocked() {
|
|
62
|
+
const orientationResult = await this.orientation();
|
|
63
|
+
return {
|
|
64
|
+
locked: false,
|
|
65
|
+
uiOrientation: orientationResult.type,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
async getPluginVersion() {
|
|
69
|
+
return { version: this.pluginVersion };
|
|
70
|
+
}
|
|
71
|
+
mapOrientationType(type) {
|
|
72
|
+
if (type.includes('portrait-primary') || type === 'portrait-primary') {
|
|
73
|
+
return 'portrait-primary';
|
|
74
|
+
}
|
|
75
|
+
if (type.includes('portrait-secondary') || type === 'portrait-secondary') {
|
|
76
|
+
return 'portrait-secondary';
|
|
77
|
+
}
|
|
78
|
+
if (type.includes('landscape-primary') || type === 'landscape-primary') {
|
|
79
|
+
return 'landscape-primary';
|
|
80
|
+
}
|
|
81
|
+
if (type.includes('landscape-secondary') || type === 'landscape-secondary') {
|
|
82
|
+
return 'landscape-secondary';
|
|
83
|
+
}
|
|
84
|
+
return 'portrait-primary'; // default fallback
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
89
|
+
__proto__: null,
|
|
90
|
+
CapacitorScreenOrientationWeb: CapacitorScreenOrientationWeb
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
exports.ScreenOrientation = ScreenOrientation;
|
|
94
|
+
|
|
95
|
+
return exports;
|
|
96
|
+
|
|
97
|
+
})({}, capacitorExports);
|
|
98
|
+
//# 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 ScreenOrientation = registerPlugin('CapacitorScreenOrientation', {\n web: () => import('./web').then((m) => new m.CapacitorScreenOrientationWeb()),\n});\nexport * from './definitions';\nexport { ScreenOrientation };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class CapacitorScreenOrientationWeb extends WebPlugin {\n constructor() {\n var _a;\n super();\n this.pluginVersion = '1.0.0';\n if ((_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation) {\n window.screen.orientation.addEventListener('change', () => {\n this.notifyListeners('screenOrientationChange', {\n type: this.mapOrientationType(window.screen.orientation.type),\n });\n });\n }\n }\n async orientation() {\n var _a;\n if (!((_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation)) {\n throw this.unavailable('Screen Orientation API not available');\n }\n return {\n type: this.mapOrientationType(window.screen.orientation.type),\n };\n }\n async lock(options) {\n var _a;\n const screenOrientation = (_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation;\n if (!(screenOrientation === null || screenOrientation === void 0 ? void 0 : screenOrientation.lock)) {\n throw this.unavailable('Screen Orientation lock not available');\n }\n // bypassOrientationLock is only supported on iOS native platform\n // Silently ignore it on web\n try {\n await screenOrientation.lock(options.orientation);\n }\n catch (error) {\n throw new Error(`Failed to lock orientation: ${error}`);\n }\n }\n async unlock() {\n var _a;\n const screenOrientation = (_a = window.screen) === null || _a === void 0 ? void 0 : _a.orientation;\n if (!(screenOrientation === null || screenOrientation === void 0 ? void 0 : screenOrientation.unlock)) {\n throw this.unavailable('Screen Orientation unlock not available');\n }\n screenOrientation.unlock();\n }\n async startOrientationTracking(_options) {\n // Motion-based orientation tracking is only supported on iOS\n // Silently ignore on web\n }\n async stopOrientationTracking() {\n // Motion-based orientation tracking is only supported on iOS\n // Silently ignore on web\n }\n async isOrientationLocked() {\n const orientationResult = await this.orientation();\n return {\n locked: false,\n uiOrientation: orientationResult.type,\n };\n }\n async getPluginVersion() {\n return { version: this.pluginVersion };\n }\n mapOrientationType(type) {\n if (type.includes('portrait-primary') || type === 'portrait-primary') {\n return 'portrait-primary';\n }\n if (type.includes('portrait-secondary') || type === 'portrait-secondary') {\n return 'portrait-secondary';\n }\n if (type.includes('landscape-primary') || type === 'landscape-primary') {\n return 'landscape-primary';\n }\n if (type.includes('landscape-secondary') || type === 'landscape-secondary') {\n return 'landscape-secondary';\n }\n return 'portrait-primary'; // default fallback\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
import CoreMotion
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Capacitor Screen Orientation Plugin
|
|
8
|
+
*
|
|
9
|
+
* Provides screen orientation detection and control with support for
|
|
10
|
+
* bypassing device orientation lock using Core Motion sensors.
|
|
11
|
+
*/
|
|
12
|
+
@objc(CapacitorScreenOrientationPlugin)
|
|
13
|
+
public class CapacitorScreenOrientationPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
14
|
+
private let pluginVersion: String = "7.0.0"
|
|
15
|
+
public let identifier = "CapacitorScreenOrientationPlugin"
|
|
16
|
+
public let jsName = "CapacitorScreenOrientation"
|
|
17
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
18
|
+
CAPPluginMethod(name: "orientation", returnType: CAPPluginReturnPromise),
|
|
19
|
+
CAPPluginMethod(name: "lock", returnType: CAPPluginReturnPromise),
|
|
20
|
+
CAPPluginMethod(name: "unlock", returnType: CAPPluginReturnPromise),
|
|
21
|
+
CAPPluginMethod(name: "startOrientationTracking", returnType: CAPPluginReturnPromise),
|
|
22
|
+
CAPPluginMethod(name: "stopOrientationTracking", returnType: CAPPluginReturnPromise),
|
|
23
|
+
CAPPluginMethod(name: "isOrientationLocked", returnType: CAPPluginReturnPromise),
|
|
24
|
+
CAPPluginMethod(name: "getPluginVersion", returnType: CAPPluginReturnPromise)
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
private var motionManager: CMMotionManager?
|
|
28
|
+
private var currentDeviceOrientation: UIDeviceOrientation = .portrait
|
|
29
|
+
private var isTrackingWithMotion = false
|
|
30
|
+
private var lastNotifiedOrientation: String?
|
|
31
|
+
|
|
32
|
+
override public func load() {
|
|
33
|
+
// Listen for device orientation changes from system
|
|
34
|
+
NotificationCenter.default.addObserver(
|
|
35
|
+
self,
|
|
36
|
+
selector: #selector(self.orientationDidChange),
|
|
37
|
+
name: UIDevice.orientationDidChangeNotification,
|
|
38
|
+
object: nil
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// Start monitoring device orientation
|
|
42
|
+
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
deinit {
|
|
46
|
+
stopMotionTracking()
|
|
47
|
+
UIDevice.current.endGeneratingDeviceOrientationNotifications()
|
|
48
|
+
NotificationCenter.default.removeObserver(self)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@objc private func orientationDidChange() {
|
|
52
|
+
let orientation = UIDevice.current.orientation
|
|
53
|
+
if orientation.isValidInterfaceOrientation {
|
|
54
|
+
notifyOrientationChange(fromDeviceOrientation: orientation)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc func orientation(_ call: CAPPluginCall) {
|
|
59
|
+
let orientationType = getCurrentOrientationType()
|
|
60
|
+
call.resolve(["type": orientationType])
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@objc func lock(_ call: CAPPluginCall) {
|
|
64
|
+
guard let orientationString = call.getString("orientation") else {
|
|
65
|
+
call.reject("Orientation parameter is required")
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let bypassLock = call.getBool("bypassOrientationLock") ?? false
|
|
70
|
+
|
|
71
|
+
DispatchQueue.main.async {
|
|
72
|
+
// Lock the orientation at the app level
|
|
73
|
+
if let mask = self.getOrientationMask(from: orientationString) {
|
|
74
|
+
// Note: Actual implementation would need to communicate with AppDelegate
|
|
75
|
+
// to set the supported interface orientations
|
|
76
|
+
// For now, we'll just track the preference
|
|
77
|
+
print("Locking orientation to: \(orientationString)")
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Start motion tracking if bypass is requested
|
|
81
|
+
if bypassLock {
|
|
82
|
+
self.startMotionTracking()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
call.resolve()
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@objc func unlock(_ call: CAPPluginCall) {
|
|
90
|
+
DispatchQueue.main.async {
|
|
91
|
+
// Stop motion tracking
|
|
92
|
+
self.stopMotionTracking()
|
|
93
|
+
|
|
94
|
+
// Unlock orientation at app level
|
|
95
|
+
print("Unlocking orientation")
|
|
96
|
+
|
|
97
|
+
call.resolve()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@objc func startOrientationTracking(_ call: CAPPluginCall) {
|
|
102
|
+
let bypassLock = call.getBool("bypassOrientationLock") ?? false
|
|
103
|
+
|
|
104
|
+
if bypassLock {
|
|
105
|
+
startMotionTracking()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
call.resolve()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@objc func stopOrientationTracking(_ call: CAPPluginCall) {
|
|
112
|
+
stopMotionTracking()
|
|
113
|
+
call.resolve()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@objc func isOrientationLocked(_ call: CAPPluginCall) {
|
|
117
|
+
let uiOrientation = getCurrentOrientationType()
|
|
118
|
+
|
|
119
|
+
if isTrackingWithMotion {
|
|
120
|
+
// We have motion data, compare physical vs UI orientation
|
|
121
|
+
let physicalOrientation = mapDeviceOrientationToString(currentDeviceOrientation)
|
|
122
|
+
let locked = physicalOrientation != uiOrientation
|
|
123
|
+
|
|
124
|
+
call.resolve([
|
|
125
|
+
"locked": locked,
|
|
126
|
+
"physicalOrientation": physicalOrientation,
|
|
127
|
+
"uiOrientation": uiOrientation
|
|
128
|
+
])
|
|
129
|
+
} else {
|
|
130
|
+
// No motion tracking active, can't determine if locked
|
|
131
|
+
// Return false by default, but note that we don't have physical orientation data
|
|
132
|
+
call.resolve([
|
|
133
|
+
"locked": false,
|
|
134
|
+
"uiOrientation": uiOrientation
|
|
135
|
+
])
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@objc func getPluginVersion(_ call: CAPPluginCall) {
|
|
140
|
+
call.resolve(["version": self.pluginVersion])
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// MARK: - Core Motion Tracking
|
|
144
|
+
|
|
145
|
+
private func startMotionTracking() {
|
|
146
|
+
guard !isTrackingWithMotion else { return }
|
|
147
|
+
|
|
148
|
+
motionManager = CMMotionManager()
|
|
149
|
+
guard let motionManager = motionManager else { return }
|
|
150
|
+
|
|
151
|
+
motionManager.accelerometerUpdateInterval = 0.2
|
|
152
|
+
motionManager.gyroUpdateInterval = 0.2
|
|
153
|
+
|
|
154
|
+
if motionManager.isAccelerometerAvailable {
|
|
155
|
+
isTrackingWithMotion = true
|
|
156
|
+
|
|
157
|
+
motionManager.startAccelerometerUpdates(to: .main) { [weak self] (data, _) in
|
|
158
|
+
guard let self = self, let data = data else { return }
|
|
159
|
+
|
|
160
|
+
let acceleration = data.acceleration
|
|
161
|
+
let orientation = self.determineOrientation(from: acceleration)
|
|
162
|
+
|
|
163
|
+
if orientation != self.currentDeviceOrientation {
|
|
164
|
+
self.currentDeviceOrientation = orientation
|
|
165
|
+
self.notifyOrientationChange(fromDeviceOrientation: orientation)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
print("Started motion-based orientation tracking")
|
|
170
|
+
} else {
|
|
171
|
+
print("Accelerometer not available")
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private func stopMotionTracking() {
|
|
176
|
+
guard isTrackingWithMotion else { return }
|
|
177
|
+
|
|
178
|
+
motionManager?.stopAccelerometerUpdates()
|
|
179
|
+
motionManager = nil
|
|
180
|
+
isTrackingWithMotion = false
|
|
181
|
+
|
|
182
|
+
print("Stopped motion-based orientation tracking")
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private func determineOrientation(from acceleration: CMAcceleration) -> UIDeviceOrientation {
|
|
186
|
+
let threshold = 0.5
|
|
187
|
+
|
|
188
|
+
if acceleration.x < -threshold {
|
|
189
|
+
return .landscapeRight
|
|
190
|
+
} else if acceleration.x > threshold {
|
|
191
|
+
return .landscapeLeft
|
|
192
|
+
} else if acceleration.y < -threshold {
|
|
193
|
+
return .portrait
|
|
194
|
+
} else if acceleration.y > threshold {
|
|
195
|
+
return .portraitUpsideDown
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return currentDeviceOrientation
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// MARK: - Helper Methods
|
|
202
|
+
|
|
203
|
+
private func getCurrentOrientationType() -> String {
|
|
204
|
+
let interfaceOrientation: UIInterfaceOrientation
|
|
205
|
+
|
|
206
|
+
if #available(iOS 13.0, *) {
|
|
207
|
+
interfaceOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? .portrait
|
|
208
|
+
} else {
|
|
209
|
+
interfaceOrientation = UIApplication.shared.statusBarOrientation
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return mapInterfaceOrientationToString(interfaceOrientation)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private func notifyOrientationChange(fromDeviceOrientation deviceOrientation: UIDeviceOrientation) {
|
|
216
|
+
let orientationType = mapDeviceOrientationToString(deviceOrientation)
|
|
217
|
+
|
|
218
|
+
// Only notify if orientation actually changed
|
|
219
|
+
if orientationType != lastNotifiedOrientation {
|
|
220
|
+
lastNotifiedOrientation = orientationType
|
|
221
|
+
notifyListeners("screenOrientationChange", data: ["type": orientationType])
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private func mapInterfaceOrientationToString(_ orientation: UIInterfaceOrientation) -> String {
|
|
226
|
+
switch orientation {
|
|
227
|
+
case .portrait:
|
|
228
|
+
return "portrait-primary"
|
|
229
|
+
case .portraitUpsideDown:
|
|
230
|
+
return "portrait-secondary"
|
|
231
|
+
case .landscapeLeft:
|
|
232
|
+
return "landscape-primary"
|
|
233
|
+
case .landscapeRight:
|
|
234
|
+
return "landscape-secondary"
|
|
235
|
+
default:
|
|
236
|
+
return "portrait-primary"
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
private func mapDeviceOrientationToString(_ orientation: UIDeviceOrientation) -> String {
|
|
241
|
+
switch orientation {
|
|
242
|
+
case .portrait:
|
|
243
|
+
return "portrait-primary"
|
|
244
|
+
case .portraitUpsideDown:
|
|
245
|
+
return "portrait-secondary"
|
|
246
|
+
case .landscapeLeft:
|
|
247
|
+
return "landscape-secondary" // Note: device left = interface right
|
|
248
|
+
case .landscapeRight:
|
|
249
|
+
return "landscape-primary" // Note: device right = interface left
|
|
250
|
+
default:
|
|
251
|
+
return "portrait-primary"
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
private func getOrientationMask(from orientationString: String) -> UIInterfaceOrientationMask? {
|
|
256
|
+
switch orientationString {
|
|
257
|
+
case "any":
|
|
258
|
+
return .all
|
|
259
|
+
case "natural", "portrait":
|
|
260
|
+
return .portrait
|
|
261
|
+
case "landscape":
|
|
262
|
+
return .landscape
|
|
263
|
+
case "portrait-primary":
|
|
264
|
+
return .portrait
|
|
265
|
+
case "portrait-secondary":
|
|
266
|
+
return .portraitUpsideDown
|
|
267
|
+
case "landscape-primary":
|
|
268
|
+
return .landscapeLeft
|
|
269
|
+
case "landscape-secondary":
|
|
270
|
+
return .landscapeRight
|
|
271
|
+
default:
|
|
272
|
+
return nil
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Helper extension
|
|
278
|
+
extension UIDeviceOrientation {
|
|
279
|
+
var isValidInterfaceOrientation: Bool {
|
|
280
|
+
switch self {
|
|
281
|
+
case .portrait, .portraitUpsideDown, .landscapeLeft, .landscapeRight:
|
|
282
|
+
return true
|
|
283
|
+
default:
|
|
284
|
+
return false
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@capgo/capacitor-screen-orientation",
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"description": "Screen orientation plugin with support for bypassing orientation lock",
|
|
5
|
+
"main": "dist/plugin.cjs.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/esm/index.d.ts",
|
|
8
|
+
"unpkg": "dist/plugin.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"android/src/main/",
|
|
11
|
+
"android/build.gradle",
|
|
12
|
+
"dist/",
|
|
13
|
+
"ios/Sources",
|
|
14
|
+
"ios/Tests",
|
|
15
|
+
"Package.swift",
|
|
16
|
+
"CapgoCapacitorScreenOrientation.podspec"
|
|
17
|
+
],
|
|
18
|
+
"author": "Cap-go <contact@capgo.app>",
|
|
19
|
+
"license": "MPL-2.0",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/Cap-go/capacitor-screen-orientation.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/Cap-go/capacitor-screen-orientation/issues"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"capacitor",
|
|
29
|
+
"plugin",
|
|
30
|
+
"screen",
|
|
31
|
+
"orientation",
|
|
32
|
+
"rotation",
|
|
33
|
+
"portrait",
|
|
34
|
+
"landscape",
|
|
35
|
+
"lock",
|
|
36
|
+
"bypass",
|
|
37
|
+
"coremotion",
|
|
38
|
+
"native"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|
|
42
|
+
"verify:ios": "xcodebuild -scheme CapgoCapacitorScreenOrientation -destination generic/platform=iOS",
|
|
43
|
+
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
44
|
+
"verify:web": "npm run build",
|
|
45
|
+
"lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
|
|
46
|
+
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
|
|
47
|
+
"eslint": "eslint .",
|
|
48
|
+
"prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
49
|
+
"swiftlint": "node-swiftlint",
|
|
50
|
+
"docgen": "docgen --api CapacitorScreenOrientationPlugin --output-readme README.md --output-json dist/docs.json",
|
|
51
|
+
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
52
|
+
"clean": "rimraf ./dist",
|
|
53
|
+
"watch": "tsc --watch",
|
|
54
|
+
"prepublishOnly": "npm run build"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@capacitor/android": "^7.0.0",
|
|
58
|
+
"@capacitor/cli": "^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.13.1",
|
|
66
|
+
"eslint": "^8.57.0",
|
|
67
|
+
"eslint-plugin-import": "^2.31.0",
|
|
68
|
+
"husky": "^9.1.7",
|
|
69
|
+
"prettier": "^3.4.2",
|
|
70
|
+
"prettier-plugin-java": "^2.6.7",
|
|
71
|
+
"rimraf": "^6.0.1",
|
|
72
|
+
"rollup": "^4.34.6",
|
|
73
|
+
"swiftlint": "^2.0.0",
|
|
74
|
+
"typescript": "^5.7.3"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"@capacitor/core": ">=7.0.0"
|
|
78
|
+
},
|
|
79
|
+
"eslintConfig": {
|
|
80
|
+
"extends": "@ionic/eslint-config/recommended"
|
|
81
|
+
},
|
|
82
|
+
"prettier": "@ionic/prettier-config",
|
|
83
|
+
"swiftlint": "@ionic/swiftlint-config",
|
|
84
|
+
"capacitor": {
|
|
85
|
+
"ios": {
|
|
86
|
+
"src": "ios"
|
|
87
|
+
},
|
|
88
|
+
"android": {
|
|
89
|
+
"src": "android"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|