refactor: migrate all cordova plugins to capacitor

This commit is contained in:
Thea Schöbl
2022-02-17 08:37:32 +00:00
committed by Rainer Killinger
parent cdb6ac4084
commit 75f4644940
36 changed files with 677 additions and 1118 deletions

View File

@@ -47,5 +47,5 @@ try {
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'
} }
} catch(Exception e) { } catch(Exception e) {
logger.warn("google-services.json not found, google-services plugin not applied. Push Notifications won't work") logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
} }

View File

@@ -15,17 +15,18 @@ dependencies {
implementation project(':capacitor-device') implementation project(':capacitor-device')
implementation project(':capacitor-dialog') implementation project(':capacitor-dialog')
implementation project(':capacitor-filesystem') implementation project(':capacitor-filesystem')
implementation project(':capacitor-geolocation')
implementation project(':capacitor-haptics') implementation project(':capacitor-haptics')
implementation project(':capacitor-keyboard') implementation project(':capacitor-keyboard')
implementation project(':capacitor-local-notifications') implementation project(':capacitor-local-notifications')
implementation project(':capacitor-network')
implementation project(':capacitor-share') implementation project(':capacitor-share')
implementation project(':capacitor-splash-screen') implementation project(':capacitor-splash-screen')
implementation project(':capacitor-status-bar') implementation project(':capacitor-status-bar')
implementation project(':capacitor-storage') implementation project(':capacitor-storage')
implementation project(':transistorsoft-capacitor-background-fetch') implementation project(':transistorsoft-capacitor-background-fetch')
implementation project(':capacitor-secure-storage-plugin') implementation project(':capacitor-secure-storage-plugin')
implementation "androidx.legacy:legacy-support-v4:1.0.0" implementation "com.android.support:support-v4:27.+"
implementation "androidx.appcompat:appcompat:1.3.1"
} }

View File

@@ -1,19 +1,7 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<manifest package="de.anyschool.app" xmlns:android="http://schemas.android.com/apk/res/android"> <manifest package="de.anyschool.app" xmlns:android="http://schemas.android.com/apk/res/android">
<application <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" android:usesCleartextTraffic="true">
android:allowBackup="true" <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode" android:label="@string/title_activity_main" android:launchMode="singleTask" android:name="de.anyschool.app.MainActivity" android:theme="@style/AppTheme.NoActionBarLaunch">
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
android:label="@string/title_activity_main"
android:launchMode="singleTask"
android:name="de.anyschool.app.MainActivity"
android:theme="@style/AppTheme.NoActionBarLaunch">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
@@ -31,13 +19,12 @@
<data android:host="@string/app_host" android:scheme="https" /> <data android:host="@string/app_host" android:scheme="https" />
</intent-filter> </intent-filter>
</activity> </activity>
<provider android:authorities="${applicationId}.fileprovider" <provider android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true" android:name="androidx.core.content.FileProvider">
android:exported="false"
android:grantUriPermissions="true"
android:name="androidx.core.content.FileProvider">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
</provider> </provider>
</application> </application>
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
</manifest> </manifest>

View File

@@ -6,17 +6,25 @@
"cordova": { "cordova": {
"preferences": { "preferences": {
"AndroidXEnabled": "true", "AndroidXEnabled": "true",
"ScrollEnabled": "false",
"android-minSdkVersion": "22", "android-minSdkVersion": "22",
"BackupWebStorage": "none", "BackupWebStorage": "none"
"SplashMaintainAspectRatio": "true",
"FadeSplashScreenDuration": "300",
"SplashShowOnlyFirstTime": "false",
"SplashScreen": "screen",
"SplashScreenDelay": "3000"
} }
}, },
"plugins": { "plugins": {
"SplashScreen": {
"launchShowDuration": 6000,
"launchAutoHide": false,
"backgroundColor": "#ffffff",
"androidSplashResourceName": "splash",
"androidScaleType": "FIT_CENTER",
"showSpinner": false,
"androidSpinnerStyle": "large",
"iosSpinnerStyle": "small",
"spinnerColor": "#999999",
"splashFullScreen": false,
"splashImmersive": false,
"useDialog": false
},
"LocalNotifications": {} "LocalNotifications": {}
} }
} }

View File

@@ -23,6 +23,10 @@
"pkg": "@capacitor/filesystem", "pkg": "@capacitor/filesystem",
"classpath": "com.capacitorjs.plugins.filesystem.FilesystemPlugin" "classpath": "com.capacitorjs.plugins.filesystem.FilesystemPlugin"
}, },
{
"pkg": "@capacitor/geolocation",
"classpath": "com.capacitorjs.plugins.geolocation.GeolocationPlugin"
},
{ {
"pkg": "@capacitor/haptics", "pkg": "@capacitor/haptics",
"classpath": "com.capacitorjs.plugins.haptics.HapticsPlugin" "classpath": "com.capacitorjs.plugins.haptics.HapticsPlugin"
@@ -35,6 +39,10 @@
"pkg": "@capacitor/local-notifications", "pkg": "@capacitor/local-notifications",
"classpath": "com.capacitorjs.plugins.localnotifications.LocalNotificationsPlugin" "classpath": "com.capacitorjs.plugins.localnotifications.LocalNotificationsPlugin"
}, },
{
"pkg": "@capacitor/network",
"classpath": "com.capacitorjs.plugins.network.NetworkPlugin"
},
{ {
"pkg": "@capacitor/share", "pkg": "@capacitor/share",
"classpath": "com.capacitorjs.plugins.share.SharePlugin" "classpath": "com.capacitorjs.plugins.share.SharePlugin"

View File

@@ -6,75 +6,12 @@
<param name="android-package" value="nl.xservices.plugins.Calendar"/> <param name="android-package" value="nl.xservices.plugins.Calendar"/>
</feature> </feature>
<feature name="Device"> <feature name="FileOpener2">
<param name="android-package" value="org.apache.cordova.device.Device"/> <param name="android-package" value="io.github.pwlin.cordova.plugins.fileopener2.FileOpener2"/>
</feature>
<feature name="Notification">
<param name="android-package" value="org.apache.cordova.dialogs.Notification"/>
</feature>
<feature name="Geolocation">
<param name="android-package" value="org.apache.cordova.geolocation.Geolocation"/>
</feature>
<feature name="NetworkStatus">
<param name="android-package" value="org.apache.cordova.networkinformation.NetworkManager"/>
</feature>
<feature name="Whitelist">
<param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic">
<param name="android-package" value="cordova.plugins.Diagnostic"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Location">
<param name="android-package" value="cordova.plugins.Diagnostic_Location"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Bluetooth">
<param name="android-package" value="cordova.plugins.Diagnostic_Bluetooth"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Wifi">
<param name="android-package" value="cordova.plugins.Diagnostic_Wifi"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Camera">
<param name="android-package" value="cordova.plugins.Diagnostic_Camera"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Notifications">
<param name="android-package" value="cordova.plugins.Diagnostic_Notifications"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_NFC">
<param name="android-package" value="cordova.plugins.Diagnostic_NFC"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_External_Storage">
<param name="android-package" value="cordova.plugins.Diagnostic_External_Storage"/>
<param name="onload" value="true"/>
</feature> </feature>
<preference name="AndroidXEnabled" value="true" /> <preference name="AndroidXEnabled" value="true" />
<preference name="ScrollEnabled" value="false" />
<preference name="android-minSdkVersion" value="22" /> <preference name="android-minSdkVersion" value="22" />
<preference name="BackupWebStorage" value="none" /> <preference name="BackupWebStorage" value="none" />
<preference name="SplashMaintainAspectRatio" value="true" />
<preference name="FadeSplashScreenDuration" value="300" />
<preference name="SplashShowOnlyFirstTime" value="false" />
<preference name="SplashScreen" value="screen" />
<preference name="SplashScreenDelay" value="3000" />
</widget> </widget>

View File

@@ -20,6 +20,9 @@ project(':capacitor-dialog').projectDir = new File('../node_modules/@capacitor/d
include ':capacitor-filesystem' include ':capacitor-filesystem'
project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacitor/filesystem/android') project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacitor/filesystem/android')
include ':capacitor-geolocation'
project(':capacitor-geolocation').projectDir = new File('../node_modules/@capacitor/geolocation/android')
include ':capacitor-haptics' include ':capacitor-haptics'
project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/haptics/android') project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/haptics/android')
@@ -29,6 +32,9 @@ project(':capacitor-keyboard').projectDir = new File('../node_modules/@capacitor
include ':capacitor-local-notifications' include ':capacitor-local-notifications'
project(':capacitor-local-notifications').projectDir = new File('../node_modules/@capacitor/local-notifications/android') project(':capacitor-local-notifications').projectDir = new File('../node_modules/@capacitor/local-notifications/android')
include ':capacitor-network'
project(':capacitor-network').projectDir = new File('../node_modules/@capacitor/network/android')
include ':capacitor-share' include ':capacitor-share'
project(':capacitor-share').projectDir = new File('../node_modules/@capacitor/share/android') project(':capacitor-share').projectDir = new File('../node_modules/@capacitor/share/android')

1
capacitor.config.json Normal file
View File

@@ -0,0 +1 @@
{}

View File

@@ -8,17 +8,25 @@ const config: CapacitorConfig = {
cordova: { cordova: {
preferences: { preferences: {
'AndroidXEnabled': 'true', 'AndroidXEnabled': 'true',
'ScrollEnabled': 'false',
'android-minSdkVersion': '22', 'android-minSdkVersion': '22',
'BackupWebStorage': 'none', 'BackupWebStorage': 'none',
'SplashMaintainAspectRatio': 'true',
'FadeSplashScreenDuration': '300',
'SplashShowOnlyFirstTime': 'false',
'SplashScreen': 'screen',
'SplashScreenDelay': '3000',
}, },
}, },
plugins: { plugins: {
SplashScreen: {
launchShowDuration: 6000,
launchAutoHide: false,
backgroundColor: '#ffffff',
androidSplashResourceName: 'splash',
androidScaleType: 'FIT_CENTER',
showSpinner: false,
androidSpinnerStyle: 'large',
iosSpinnerStyle: 'small',
spinnerColor: '#999999',
splashFullScreen: false,
splashImmersive: false,
useDialog: false,
},
LocalNotifications: { LocalNotifications: {
// TODO // TODO
}, },

View File

@@ -108,7 +108,6 @@
504EC3011FED79650016851F /* Frameworks */, 504EC3011FED79650016851F /* Frameworks */,
504EC3021FED79650016851F /* Resources */, 504EC3021FED79650016851F /* Resources */,
9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */, 9592DBEFFC6D2A0C8D5DEB22 /* [CP] Embed Pods Frameworks */,
0C3780443725062B779B937E /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
@@ -170,21 +169,6 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
0C3780443725062B779B937E /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-resources.sh\"\n";
showEnvVarsInLog = 0;
};
6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */ = { 6634F4EFEBD30273BCE97C65 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;

View File

@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "504EC3031FED79650016851F"
BuildableName = "App.app"
BlueprintName = "App"
ReferencedContainer = "container:App.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "504EC3031FED79650016851F"
BuildableName = "App.app"
BlueprintName = "App"
ReferencedContainer = "container:App.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "504EC3031FED79650016851F"
BuildableName = "App.app"
BlueprintName = "App"
ReferencedContainer = "container:App.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -7,7 +7,9 @@
<string>com.transistorsoft.fetch</string> <string>com.transistorsoft.fetch</string>
</array> </array>
<key>NSCalendarsUsageDescription</key> <key>NSCalendarsUsageDescription</key>
<string>App uses calendar for schedule sync</string> <string>Calendar access is needed to sync your schedule with the device</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location services are used to enable all map and search features</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>en</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>

View File

@@ -6,20 +6,25 @@
"cordova": { "cordova": {
"preferences": { "preferences": {
"AndroidXEnabled": "true", "AndroidXEnabled": "true",
"ScrollEnabled": "false",
"android-minSdkVersion": "22", "android-minSdkVersion": "22",
"BackupWebStorage": "none", "BackupWebStorage": "none"
"SplashMaintainAspectRatio": "true",
"FadeSplashScreenDuration": "300",
"SplashShowOnlyFirstTime": "false",
"SplashScreen": "screen",
"SplashScreenDelay": "3000"
} }
}, },
"plugins": { "plugins": {
"LocalNotifications": {} "SplashScreen": {
"launchShowDuration": 6000,
"launchAutoHide": false,
"backgroundColor": "#ffffff",
"androidSplashResourceName": "splash",
"androidScaleType": "FIT_CENTER",
"showSpinner": false,
"androidSpinnerStyle": "large",
"iosSpinnerStyle": "small",
"spinnerColor": "#999999",
"splashFullScreen": false,
"splashImmersive": false,
"useDialog": false
}, },
"server": { "LocalNotifications": {}
"url": "http://141.2.95.77:8100"
} }
} }

View File

@@ -6,85 +6,12 @@
<param name="ios-package" value="Calendar"/> <param name="ios-package" value="Calendar"/>
</feature> </feature>
<feature name="Device"> <feature name="FileOpener2">
<param name="ios-package" value="CDVDevice"/> <param name="ios-package" value="FileOpener2"/>
</feature>
<feature name="Notification">
<param name="ios-package" value="CDVNotification"/>
</feature>
<feature name="Geolocation">
<param name="ios-package" value="CDVLocation"/>
</feature>
<feature name="NetworkStatus">
<param name="ios-package" value="CDVConnection"/>
</feature>
<feature name="Diagnostic">
<param name="ios-package" value="Diagnostic"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Location">
<param name="ios-package" value="Diagnostic_Location"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Bluetooth">
<param name="ios-package" value="Diagnostic_Bluetooth"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Wifi">
<param name="ios-package" value="Diagnostic_Wifi"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Camera">
<param name="ios-package" value="Diagnostic_Camera"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Notifications">
<param name="ios-package" value="Diagnostic_Notifications"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Microphone">
<param name="ios-package" value="Diagnostic_Microphone"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Contacts">
<param name="ios-package" value="Diagnostic_Contacts"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Calendar">
<param name="ios-package" value="Diagnostic_Calendar"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Reminders">
<param name="ios-package" value="Diagnostic_Reminders"/>
<param name="onload" value="true"/>
</feature>
<feature name="Diagnostic_Motion">
<param name="ios-package" value="Diagnostic_Motion"/>
<param name="onload" value="true"/>
</feature> </feature>
<preference name="AndroidXEnabled" value="true" /> <preference name="AndroidXEnabled" value="true" />
<preference name="ScrollEnabled" value="false" />
<preference name="android-minSdkVersion" value="22" /> <preference name="android-minSdkVersion" value="22" />
<preference name="BackupWebStorage" value="none" /> <preference name="BackupWebStorage" value="none" />
<preference name="SplashMaintainAspectRatio" value="true" />
<preference name="FadeSplashScreenDuration" value="300" />
<preference name="SplashShowOnlyFirstTime" value="false" />
<preference name="SplashScreen" value="screen" />
<preference name="SplashScreenDelay" value="3000" />
</widget> </widget>

View File

@@ -15,9 +15,11 @@ def capacitor_pods
pod 'CapacitorDevice', :path => '../../node_modules/@capacitor/device' pod 'CapacitorDevice', :path => '../../node_modules/@capacitor/device'
pod 'CapacitorDialog', :path => '../../node_modules/@capacitor/dialog' pod 'CapacitorDialog', :path => '../../node_modules/@capacitor/dialog'
pod 'CapacitorFilesystem', :path => '../../node_modules/@capacitor/filesystem' pod 'CapacitorFilesystem', :path => '../../node_modules/@capacitor/filesystem'
pod 'CapacitorGeolocation', :path => '../../node_modules/@capacitor/geolocation'
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics' pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'
pod 'CapacitorKeyboard', :path => '../../node_modules/@capacitor/keyboard' pod 'CapacitorKeyboard', :path => '../../node_modules/@capacitor/keyboard'
pod 'CapacitorLocalNotifications', :path => '../../node_modules/@capacitor/local-notifications' pod 'CapacitorLocalNotifications', :path => '../../node_modules/@capacitor/local-notifications'
pod 'CapacitorNetwork', :path => '../../node_modules/@capacitor/network'
pod 'CapacitorShare', :path => '../../node_modules/@capacitor/share' pod 'CapacitorShare', :path => '../../node_modules/@capacitor/share'
pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen' pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen'
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar' pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
@@ -25,7 +27,6 @@ def capacitor_pods
pod 'TransistorsoftCapacitorBackgroundFetch', :path => '../../node_modules/@transistorsoft/capacitor-background-fetch' pod 'TransistorsoftCapacitorBackgroundFetch', :path => '../../node_modules/@transistorsoft/capacitor-background-fetch'
pod 'CapacitorSecureStoragePlugin', :path => '../../node_modules/capacitor-secure-storage-plugin' pod 'CapacitorSecureStoragePlugin', :path => '../../node_modules/capacitor-secure-storage-plugin'
pod 'CordovaPlugins', :path => '../capacitor-cordova-ios-plugins' pod 'CordovaPlugins', :path => '../capacitor-cordova-ios-plugins'
pod 'CordovaPluginsResources', :path => '../capacitor-cordova-ios-plugins'
end end
target 'App' do target 'App' do

1082
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -31,6 +31,7 @@
"lint": "ng lint", "lint": "ng lint",
"lint:fix": "eslint --fix -c .eslintrc.json --ignore-path .eslintignore --ext .ts,.html src/", "lint:fix": "eslint --fix -c .eslintrc.json --ignore-path .eslintignore --ext .ts,.html src/",
"ng": "ng", "ng": "ng",
"postinstall": "npx jetify",
"postversion": "npm run changelog && npm run licenses", "postversion": "npm run changelog && npm run licenses",
"pree2e": "webdriver-manager clean && webdriver-manager update --gecko false --versions.chrome $(google-chrome --product-version)", "pree2e": "webdriver-manager clean && webdriver-manager update --gecko false --versions.chrome $(google-chrome --product-version)",
"prepublishOnly": "npm ci && npm run build", "prepublishOnly": "npm ci && npm run build",
@@ -54,30 +55,26 @@
"@angular/router": "12.2.13", "@angular/router": "12.2.13",
"@asymmetrik/ngx-leaflet": "8.1.0", "@asymmetrik/ngx-leaflet": "8.1.0",
"@asymmetrik/ngx-leaflet-markercluster": "5.0.1", "@asymmetrik/ngx-leaflet-markercluster": "5.0.1",
"@awesome-cordova-plugins/calendar": "5.37.1", "@awesome-cordova-plugins/calendar": "5.39.1",
"@awesome-cordova-plugins/core": "5.37.1", "@awesome-cordova-plugins/core": "5.39.1",
"@capacitor-community/http": "1.4.1", "@capacitor-community/http": "1.4.1",
"@capacitor/app": "1.0.6", "@capacitor/app": "1.1.0",
"@capacitor/browser": "1.0.6", "@capacitor/browser": "1.0.7",
"@capacitor/core": "3.3.1", "@capacitor/core": "3.4.1",
"@capacitor/device": "1.1.0", "@capacitor/device": "1.1.2",
"@capacitor/dialog": "1.0.6", "@capacitor/dialog": "1.0.7",
"@capacitor/filesystem": "1.0.6", "@capacitor/filesystem": "1.1.0",
"@capacitor/haptics": "1.1.3", "@capacitor/geolocation": "1.3.1",
"@capacitor/keyboard": "1.1.3", "@capacitor/haptics": "1.1.4",
"@capacitor/local-notifications": "1.0.9", "@capacitor/keyboard": "1.2.2",
"@capacitor/share": "1.0.7", "@capacitor/local-notifications": "1.1.0",
"@capacitor/splash-screen": "1.1.6", "@capacitor/network": "1.0.7",
"@capacitor/status-bar": "1.0.6", "@capacitor/share": "1.1.1",
"@capacitor/storage": "1.2.3", "@capacitor/splash-screen": "1.2.2",
"@capacitor/status-bar": "1.0.8",
"@capacitor/storage": "1.2.4",
"@ionic-native/core": "5.36.0", "@ionic-native/core": "5.36.0",
"@ionic-native/diagnostic": "5.36.0",
"@ionic-native/dialogs": "5.36.0",
"@ionic-native/file": "5.36.0",
"@ionic-native/file-opener": "5.36.0", "@ionic-native/file-opener": "5.36.0",
"@ionic-native/file-transfer": "5.36.0",
"@ionic-native/geolocation": "5.36.0",
"@ionic-native/network": "5.36.0",
"@ionic/angular": "5.7.0", "@ionic/angular": "5.7.0",
"@ionic/storage-angular": "3.0.6", "@ionic/storage-angular": "3.0.6",
"@ngx-translate/core": "13.0.0", "@ngx-translate/core": "13.0.0",
@@ -88,12 +85,7 @@
"@transistorsoft/capacitor-background-fetch": "0.0.6", "@transistorsoft/capacitor-background-fetch": "0.0.6",
"capacitor-secure-storage-plugin": "0.6.2", "capacitor-secure-storage-plugin": "0.6.2",
"cordova-plugin-calendar": "5.1.5", "cordova-plugin-calendar": "5.1.5",
"cordova-plugin-device": "2.0.3", "cordova-plugin-file-opener2": "3.0.5",
"cordova-plugin-dialogs": "2.0.2",
"cordova-plugin-geolocation": "4.1.0",
"cordova-plugin-network-information": "2.0.2",
"cordova-plugin-whitelist": "1.3.4",
"cordova.plugins.diagnostic": "6.1.0",
"core-js": "2.6.5", "core-js": "2.6.5",
"deepmerge": "3.3.0", "deepmerge": "3.3.0",
"form-data": "2.5.0", "form-data": "2.5.0",
@@ -128,9 +120,9 @@
"@angular/compiler": "12.2.13", "@angular/compiler": "12.2.13",
"@angular/compiler-cli": "12.2.13", "@angular/compiler-cli": "12.2.13",
"@angular/language-service": "12.2.13", "@angular/language-service": "12.2.13",
"@capacitor/android": "3.4.0", "@capacitor/android": "3.4.1",
"@capacitor/cli": "3.3.2", "@capacitor/cli": "3.4.1",
"@capacitor/ios": "3.3.2", "@capacitor/ios": "3.4.1",
"@compodoc/compodoc": "1.1.14", "@compodoc/compodoc": "1.1.14",
"@ionic/angular-toolkit": "4.0.0", "@ionic/angular-toolkit": "4.0.0",
"@ionic/cli": "6.18.1", "@ionic/cli": "6.18.1",
@@ -155,6 +147,7 @@
"is-docker": "1.1.0", "is-docker": "1.1.0",
"jasmine-core": "3.9.0", "jasmine-core": "3.9.0",
"jasmine-spec-reporter": "7.0.0", "jasmine-spec-reporter": "7.0.0",
"jetifier": "2.0.0",
"karma": "6.3.16", "karma": "6.3.16",
"karma-chrome-launcher": "3.1.0", "karma-chrome-launcher": "3.1.0",
"karma-coverage-istanbul-reporter": "3.0.3", "karma-coverage-istanbul-reporter": "3.0.3",
@@ -169,20 +162,7 @@
"typescript": "4.3.5" "typescript": "4.3.5"
}, },
"cordova": { "cordova": {
"plugins": { "plugins": {},
"cordova-plugin-whitelist": {},
"cordova-plugin-file-transfer": {
"ANDROID_SUPPORT_V4_VERSION": "27.+"
},
"cordova-plugin-device": {},
"cordova-plugin-geolocation": {
"GEOLOCATION_USAGE_DESCRIPTION": "The app will use your location to provide features for navigation or distances information.",
"GPS_REQUIRED": "true"
},
"cordova.plugins.diagnostic": {
"ANDROIDX_VERSION": "1.0.0"
}
},
"platforms": [ "platforms": [
"ios", "ios",
"browser", "browser",

View File

@@ -15,12 +15,13 @@
import {AfterContentInit, Component, NgZone} from '@angular/core'; import {AfterContentInit, Component, NgZone} from '@angular/core';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {App, URLOpenListenerEvent} from '@capacitor/app'; import {App, URLOpenListenerEvent} from '@capacitor/app';
import {SplashScreen} from '@capacitor/splash-screen';
import {Platform, ToastController} from '@ionic/angular'; import {Platform, ToastController} from '@ionic/angular';
import {SettingsProvider} from './modules/settings/settings.provider'; import {SettingsProvider} from './modules/settings/settings.provider';
import {AuthHelperService} from './modules/auth/auth-helper.service'; import {AuthHelperService} from './modules/auth/auth-helper.service';
import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.service'; import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.service';
import {environment} from '../environments/environment'; import {environment} from '../environments/environment';
import {StatusBar, Style} from '@capacitor/status-bar';
import {Capacitor} from '@capacitor/core';
/** /**
* TODO * TODO
@@ -86,7 +87,9 @@ export class AppComponent implements AfterContentInit {
}); });
this.platform.ready().then(async () => { this.platform.ready().then(async () => {
await this.authInit(); await this.authInit();
await SplashScreen.hide(); if (Capacitor.isNativePlatform()) {
await StatusBar.setStyle({style: Style.Dark});
}
// set order of categories in settings // set order of categories in settings
this.settingsProvider.setCategoriesOrder([ this.settingsProvider.setCategoriesOrder([

View File

@@ -23,7 +23,6 @@ import localeDe from '@angular/common/locales/de';
import {APP_INITIALIZER, NgModule} from '@angular/core'; import {APP_INITIALIZER, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {RouteReuseStrategy} from '@angular/router'; import {RouteReuseStrategy} from '@angular/router';
import {Diagnostic} from '@ionic-native/diagnostic/ngx';
import {IonicModule, IonicRouteStrategy, Platform} from '@ionic/angular'; import {IonicModule, IonicRouteStrategy, Platform} from '@ionic/angular';
import { import {
TranslateLoader, TranslateLoader,
@@ -169,7 +168,6 @@ export function createTranslateLoader(http: HttpClient) {
}), }),
], ],
providers: [ providers: [
Diagnostic,
{ {
provide: RouteReuseStrategy, provide: RouteReuseStrategy,
useClass: IonicRouteStrategy, useClass: IonicRouteStrategy,

View File

@@ -21,7 +21,6 @@ import {
ScheduleProvider, ScheduleProvider,
} from '../../calendar/schedule.provider'; } from '../../calendar/schedule.provider';
import {SCDateSeries, SCThingType, SCUuid} from '@openstapps/core'; import {SCDateSeries, SCThingType, SCUuid} from '@openstapps/core';
import {Device} from '@capacitor/device';
import {LocalNotifications} from '@capacitor/local-notifications'; import {LocalNotifications} from '@capacitor/local-notifications';
import {ThingTranslateService} from '../../../translation/thing-translate.service'; import {ThingTranslateService} from '../../../translation/thing-translate.service';
import {DateFormatPipe, DurationPipe} from 'ngx-moment'; import {DateFormatPipe, DurationPipe} from 'ngx-moment';
@@ -39,6 +38,7 @@ import {
CALENDAR_SYNC_SETTINGS_KEY, CALENDAR_SYNC_SETTINGS_KEY,
} from '../../settings/page/calendar-sync-settings-keys'; } from '../../settings/page/calendar-sync-settings-keys';
import {filter} from 'rxjs/operators'; import {filter} from 'rxjs/operators';
import {Capacitor} from '@capacitor/core';
@Injectable() @Injectable()
export class ScheduleSyncService implements OnDestroy { export class ScheduleSyncService implements OnDestroy {
@@ -79,7 +79,7 @@ export class ScheduleSyncService implements OnDestroy {
} }
async enable() { async enable() {
if ((await Device.getInfo()).platform === 'web') return; if (!Capacitor.isNativePlatform()) return;
await BackgroundFetch.stop(); await BackgroundFetch.stop();
@@ -189,9 +189,7 @@ export class ScheduleSyncService implements OnDestroy {
); );
if (differences.length === 0) return; if (differences.length === 0) return;
if ((await Device.getInfo()).platform === 'web') { if (Capacitor.isNativePlatform()) {
// TODO: Implement web notification
} else {
await LocalNotifications.schedule({ await LocalNotifications.schedule({
notifications: differences.map(it => ({ notifications: differences.map(it => ({
title: it.new.event.name, title: it.new.event.name,
@@ -199,6 +197,8 @@ export class ScheduleSyncService implements OnDestroy {
id: hashStringToInt(it.new.uid), id: hashStringToInt(it.new.uid),
})), })),
}); });
} else {
// TODO: Implement desktop notifications
} }
} }
} }

View File

@@ -17,7 +17,6 @@ import {CommonModule} from '@angular/common';
import {HttpClientModule} from '@angular/common/http'; import {HttpClientModule} from '@angular/common/http';
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {Network} from '@ionic-native/network/ngx';
import {IonicModule} from '@ionic/angular'; import {IonicModule} from '@ionic/angular';
import {TranslateModule} from '@ngx-translate/core'; import {TranslateModule} from '@ngx-translate/core';
import {MarkdownModule} from 'ngx-markdown'; import {MarkdownModule} from 'ngx-markdown';
@@ -79,7 +78,6 @@ import {SemesterListItemComponent} from './types/semester/semester-list-item.com
import {VideoListItemComponent} from './types/video/video-list-item.component'; import {VideoListItemComponent} from './types/video/video-list-item.component';
import {OriginInListComponent} from './elements/origin-in-list.component'; import {OriginInListComponent} from './elements/origin-in-list.component';
import {CoordinatedSearchProvider} from './coordinated-search.provider'; import {CoordinatedSearchProvider} from './coordinated-search.provider';
import {Geolocation} from '@ionic-native/geolocation/ngx';
import {FavoriteButtonComponent} from './elements/favorite-button.component'; import {FavoriteButtonComponent} from './elements/favorite-button.component';
import {SimpleDataListComponent} from './list/simple-data-list.component'; import {SimpleDataListComponent} from './list/simple-data-list.component';
import {TitleCardComponent} from './elements/title-card.component'; import {TitleCardComponent} from './elements/title-card.component';
@@ -166,7 +164,6 @@ import {CalendarService} from '../calendar/calendar.service';
DataProvider, DataProvider,
DataFacetsProvider, DataFacetsProvider,
Geolocation, Geolocation,
Network,
ScheduleProvider, ScheduleProvider,
StAppsWebHttpClient, StAppsWebHttpClient,
CalendarService, CalendarService,

View File

@@ -14,7 +14,6 @@
*/ */
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {Network} from '@ionic-native/network/ngx';
import {IonRefresher} from '@ionic/angular'; import {IonRefresher} from '@ionic/angular';
import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
import { import {
@@ -26,6 +25,7 @@ import {
import {DataProvider, DataScope} from '../data.provider'; import {DataProvider, DataScope} from '../data.provider';
import {FavoritesService} from '../../favorites/favorites.service'; import {FavoritesService} from '../../favorites/favorites.service';
import {take} from 'rxjs/operators'; import {take} from 'rxjs/operators';
import {Network} from '@capacitor/network';
/** /**
* A Component to display an SCThing detailed * A Component to display an SCThing detailed
@@ -48,6 +48,11 @@ export class DataDetailComponent {
*/ */
language: SCLanguageCode; language: SCLanguageCode;
/**
* Indicating wether internet connectivity is given or not
*/
isDisconnected: Promise<boolean>;
/** /**
* Type guard for SCSavableThing * Type guard for SCSavableThing
*/ */
@@ -61,14 +66,12 @@ export class DataDetailComponent {
* *
* @param route the route the page was accessed from * @param route the route the page was accessed from
* @param dataProvider the data provider * @param dataProvider the data provider
* @param network the network provider
* @param favoritesService the favorites provider * @param favoritesService the favorites provider
* @param translateService he translate provider * @param translateService he translate provider
*/ */
constructor( constructor(
protected readonly route: ActivatedRoute, protected readonly route: ActivatedRoute,
private readonly dataProvider: DataProvider, private readonly dataProvider: DataProvider,
protected readonly network: Network,
private readonly favoritesService: FavoritesService, private readonly favoritesService: FavoritesService,
translateService: TranslateService, translateService: TranslateService,
) { ) {
@@ -76,6 +79,11 @@ export class DataDetailComponent {
translateService.onLangChange.subscribe((event: LangChangeEvent) => { translateService.onLangChange.subscribe((event: LangChangeEvent) => {
this.language = event.lang as SCLanguageCode; this.language = event.lang as SCLanguageCode;
}); });
this.isDisconnected = new Promise(async resolve => {
const isConnected = (await Network.getStatus()).connected;
resolve(isConnected);
});
} }
/** /**
@@ -93,13 +101,6 @@ export class DataDetailComponent {
} }
} }
/**
* Check if we have internet
*/
isDisconnected(): boolean {
return this.network.type === this.network.Connection.NONE;
}
/** /**
* Initialize * Initialize
*/ */

View File

@@ -23,7 +23,7 @@
</ion-refresher-content> </ion-refresher-content>
</ion-refresher> </ion-refresher>
<div [ngSwitch]="true"> <div [ngSwitch]="true">
<ng-container *ngSwitchCase="!item && isDisconnected()"> <ng-container *ngSwitchCase="!item && (isDisconnected | async)">
<div class="centeredMessageContainer"> <div class="centeredMessageContainer">
<ion-icon name="no-connection"> </ion-icon> <ion-icon name="no-connection"> </ion-icon>
<ion-label> <ion-label>

View File

@@ -13,7 +13,9 @@ describe('DataListComponent', () => {
beforeEach( beforeEach(
waitForAsync(() => { waitForAsync(() => {
configProviderMock = jasmine.createSpyObj('ConfigProvider', { configProviderMock = jasmine.createSpyObj('ConfigProvider', {
getValue: () => Promise.resolve({lat: 123, lng: 123}), getValue: () => {
return {lat: 123, lng: 123};
},
}); });
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [DataListComponent], declarations: [DataListComponent],

View File

@@ -30,6 +30,7 @@ import {Observable, of} from 'rxjs';
import {StorageProvider} from '../../storage/storage.provider'; import {StorageProvider} from '../../storage/storage.provider';
import {DaiaDataProvider} from '../daia-data.provider'; import {DaiaDataProvider} from '../daia-data.provider';
import {LoggerConfig, LoggerModule, NGXLogger} from 'ngx-logger'; import {LoggerConfig, LoggerModule, NGXLogger} from 'ngx-logger';
import {ConfigProvider} from '../../config/config.provider';
const translations: any = {data: {detail: {TITLE: 'Foo'}}}; const translations: any = {data: {detail: {TITLE: 'Foo'}}};
@@ -46,6 +47,7 @@ describe('DaiaAvailabilityComponent', () => {
let refresher: IonRefresher; let refresher: IonRefresher;
const sampleThing = sampleThingsMap.book[0]; const sampleThing = sampleThingsMap.book[0];
let translateService: TranslateService; let translateService: TranslateService;
let configProviderMock: jasmine.SpyObj<ConfigProvider>;
// @Component({ selector: 'stapps-data-list-item', template: '' }) // @Component({ selector: 'stapps-data-list-item', template: '' })
// class DataListItemComponent { // class DataListItemComponent {
@@ -72,6 +74,11 @@ describe('DaiaAvailabilityComponent', () => {
beforeEach( beforeEach(
waitForAsync(() => { waitForAsync(() => {
configProviderMock = jasmine.createSpyObj('ConfigProvider', [
'init',
'getValue',
'getAnyValue',
]);
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
RouterModule.forRoot([], {relativeLinkResolution: 'legacy'}), RouterModule.forRoot([], {relativeLinkResolution: 'legacy'}),
@@ -91,6 +98,10 @@ describe('DaiaAvailabilityComponent', () => {
provide: StorageProvider, provide: StorageProvider,
useValue: storageProviderSpy, useValue: storageProviderSpy,
}, },
{
provide: ConfigProvider,
useValue: configProviderMock,
},
NGXLogger, NGXLogger,
LoggerConfig, LoggerConfig,
], ],

View File

@@ -14,7 +14,6 @@
*/ */
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {Network} from '@ionic-native/network/ngx';
import {TranslateService} from '@ngx-translate/core'; import {TranslateService} from '@ngx-translate/core';
import {SCUuid} from '@openstapps/core'; import {SCUuid} from '@openstapps/core';
import {FavoritesService} from '../../favorites/favorites.service'; import {FavoritesService} from '../../favorites/favorites.service';
@@ -41,7 +40,6 @@ export class DaiaAvailabilityComponent
* *
* @param route the route the page was accessed from * @param route the route the page was accessed from
* @param dataProvider the data provider * @param dataProvider the data provider
* @param network the network provider
* @param favoritesService the favorites provider * @param favoritesService the favorites provider
* @param translateService he translate provider * @param translateService he translate provider
* @param daiaDataProvider DaiaDataProvider * @param daiaDataProvider DaiaDataProvider
@@ -49,19 +47,11 @@ export class DaiaAvailabilityComponent
constructor( constructor(
route: ActivatedRoute, route: ActivatedRoute,
dataProvider: DataProvider, dataProvider: DataProvider,
network: Network,
favoritesService: FavoritesService, favoritesService: FavoritesService,
translateService: TranslateService, translateService: TranslateService,
private daiaDataProvider: DaiaDataProvider, private daiaDataProvider: DaiaDataProvider,
) { ) {
super(route, dataProvider, network, favoritesService, translateService); super(route, dataProvider, favoritesService, translateService);
}
/**
* Check if we have internet
*/
isDisconnected(): boolean {
return this.network.type === this.network.Connection.NONE;
} }
/** /**

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018, 2019 StApps * Copyright (C) 2018-2022 StApps
* This program is free software: you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3. * Software Foundation, version 3.
@@ -14,7 +14,6 @@
*/ */
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {Network} from '@ionic-native/network/ngx';
import {TranslateService} from '@ngx-translate/core'; import {TranslateService} from '@ngx-translate/core';
import {SCUuid} from '@openstapps/core'; import {SCUuid} from '@openstapps/core';
import {HebisDataProvider} from '../hebis-data.provider'; import {HebisDataProvider} from '../hebis-data.provider';
@@ -38,7 +37,6 @@ export class HebisDetailComponent extends DataDetailComponent {
* *
* @param route the route the page was accessed from * @param route the route the page was accessed from
* @param dataProvider the data provider * @param dataProvider the data provider
* @param network the network provider
* @param favoritesService the favorites provider * @param favoritesService the favorites provider
* @param translateService he translate provider * @param translateService he translate provider
* @param hebisDataProvider HebisDataProvider * @param hebisDataProvider HebisDataProvider
@@ -46,19 +44,11 @@ export class HebisDetailComponent extends DataDetailComponent {
constructor( constructor(
route: ActivatedRoute, route: ActivatedRoute,
dataProvider: DataProvider, dataProvider: DataProvider,
network: Network,
favoritesService: FavoritesService, favoritesService: FavoritesService,
translateService: TranslateService, translateService: TranslateService,
private hebisDataProvider: HebisDataProvider, private hebisDataProvider: HebisDataProvider,
) { ) {
super(route, dataProvider, network, favoritesService, translateService); super(route, dataProvider, favoritesService, translateService);
}
/**
* Check if we have internet
*/
isDisconnected(): boolean {
return this.network.type === this.network.Connection.NONE;
} }
/** /**

View File

@@ -23,7 +23,7 @@
</ion-refresher-content> </ion-refresher-content>
</ion-refresher> </ion-refresher>
<div [ngSwitch]="true"> <div [ngSwitch]="true">
<ng-container *ngSwitchCase="!item && isDisconnected()"> <ng-container *ngSwitchCase="!item && isDisconnected | async">
<div class="notFoundContainer"> <div class="notFoundContainer">
<ion-icon name="no-connection"> </ion-icon> <ion-icon name="no-connection"> </ion-icon>
<ion-label> <ion-label>

View File

@@ -17,7 +17,6 @@ import {CommonModule} from '@angular/common';
import {HttpClientModule} from '@angular/common/http'; import {HttpClientModule} from '@angular/common/http';
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {Network} from '@ionic-native/network/ngx';
import {IonicModule} from '@ionic/angular'; import {IonicModule} from '@ionic/angular';
import {TranslateModule} from '@ngx-translate/core'; import {TranslateModule} from '@ngx-translate/core';
import {MarkdownModule} from 'ngx-markdown'; import {MarkdownModule} from 'ngx-markdown';
@@ -80,12 +79,7 @@ import {DaiaAvailabilityComponent} from './daia-availability/daia-availability.c
TranslateModule.forChild(), TranslateModule.forChild(),
ThingTranslateModule.forChild(), ThingTranslateModule.forChild(),
], ],
providers: [ providers: [HebisDataProvider, DaiaDataProvider, StAppsWebHttpClient],
HebisDataProvider,
DaiaDataProvider,
Network,
StAppsWebHttpClient,
],
exports: [ exports: [
HebisSearchPageComponent, HebisSearchPageComponent,
HebisDetailComponent, HebisDetailComponent,

View File

@@ -17,7 +17,6 @@ import {FormsModule} from '@angular/forms';
import {RouterModule, Routes} from '@angular/router'; import {RouterModule, Routes} from '@angular/router';
import {LeafletModule} from '@asymmetrik/ngx-leaflet'; import {LeafletModule} from '@asymmetrik/ngx-leaflet';
import {LeafletMarkerClusterModule} from '@asymmetrik/ngx-leaflet-markercluster'; import {LeafletMarkerClusterModule} from '@asymmetrik/ngx-leaflet-markercluster';
import {Geolocation} from '@ionic-native/geolocation/ngx';
import {IonicModule} from '@ionic/angular'; import {IonicModule} from '@ionic/angular';
import {TranslateModule} from '@ngx-translate/core'; import {TranslateModule} from '@ngx-translate/core';
import {Polygon} from 'geojson'; import {Polygon} from 'geojson';

View File

@@ -14,8 +14,6 @@
*/ */
import {TestBed} from '@angular/core/testing'; import {TestBed} from '@angular/core/testing';
import {Geolocation} from '@ionic-native/geolocation/ngx';
import {Diagnostic} from '@ionic-native/diagnostic/ngx';
import {MapProvider} from './map.provider'; import {MapProvider} from './map.provider';
import {StAppsWebHttpClient} from '../data/stapps-web-http-client.provider'; import {StAppsWebHttpClient} from '../data/stapps-web-http-client.provider';
import {HttpClientModule} from '@angular/common/http'; import {HttpClientModule} from '@angular/common/http';
@@ -39,8 +37,6 @@ describe('MapProvider', () => {
provide: ConfigProvider, provide: ConfigProvider,
useValue: configProvider, useValue: configProvider,
}, },
Geolocation,
Diagnostic,
StAppsWebHttpClient, StAppsWebHttpClient,
StorageProvider, StorageProvider,
NGXLogger, NGXLogger,

View File

@@ -20,7 +20,7 @@ import {
ViewChild, ViewChild,
} from '@angular/core'; } from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router'; import {ActivatedRoute, Router} from '@angular/router';
import {AlertController, ModalController, Platform} from '@ionic/angular'; import {AlertController, ModalController} from '@ionic/angular';
import {TranslateService} from '@ngx-translate/core'; import {TranslateService} from '@ngx-translate/core';
import { import {
SCBuilding, SCBuilding,
@@ -43,13 +43,11 @@ import {Subscription} from 'rxjs';
import {DataRoutingService} from '../../data/data-routing.service'; import {DataRoutingService} from '../../data/data-routing.service';
import {ContextMenuService} from '../../menu/context/context-menu.service'; import {ContextMenuService} from '../../menu/context/context-menu.service';
import {MapProvider} from '../map.provider'; import {MapProvider} from '../map.provider';
import { import {MapPosition, PositionService} from '../position.service';
LocationStatus,
MapPosition,
PositionService,
} from '../position.service';
import {MapListModalComponent} from './modals/map-list-modal.component'; import {MapListModalComponent} from './modals/map-list-modal.component';
import {MapSingleModalComponent} from './modals/map-single-modal.component'; import {MapSingleModalComponent} from './modals/map-single-modal.component';
import {Geolocation, PermissionStatus} from '@capacitor/geolocation';
import {Capacitor} from '@capacitor/core';
/** /**
* The main page of the map * The main page of the map
@@ -88,7 +86,7 @@ export class MapPageComponent {
/** /**
* Location settings on the user's device * Location settings on the user's device
*/ */
locationStatus: LocationStatus = {enabled: undefined, allowed: undefined}; locationStatus?: PermissionStatus;
/** /**
* The leaflet map * The leaflet map
@@ -160,7 +158,6 @@ export class MapPageComponent {
private modalController: ModalController, private modalController: ModalController,
private dataRoutingService: DataRoutingService, private dataRoutingService: DataRoutingService,
private positionService: PositionService, private positionService: PositionService,
private platform: Platform,
) { ) {
// initialize the options // initialize the options
this.options = { this.options = {
@@ -293,10 +290,8 @@ export class MapPageComponent {
30, 30,
); );
}, },
error: error => { error: async _error => {
if (error.code === 1) { this.locationStatus = await Geolocation.checkPermissions();
this.locationStatus.allowed = false;
}
// eslint-disable-next-line unicorn/no-null // eslint-disable-next-line unicorn/no-null
this.position = null; this.position = null;
}, },
@@ -304,9 +299,7 @@ export class MapPageComponent {
); );
// get detailed location status (diagnostics only supports devices) // get detailed location status (diagnostics only supports devices)
if (this.platform.is('cordova')) { this.locationStatus = await Geolocation.checkPermissions();
this.locationStatus = await this.positionService.getLocationStatus();
}
} }
/** /**
@@ -360,6 +353,10 @@ export class MapPageComponent {
return; return;
} }
this.locationStatus = await (!Capacitor.isNativePlatform()
? Geolocation.checkPermissions()
: Geolocation.requestPermissions());
this.translateService this.translateService
.get(['map.page.geolocation', 'app.errors.UNKNOWN']) .get(['map.page.geolocation', 'app.errors.UNKNOWN'])
.subscribe(async translations => { .subscribe(async translations => {
@@ -367,16 +364,15 @@ export class MapPageComponent {
translations['map.page.geolocation'], translations['map.page.geolocation'],
translations['app.errors.UNKNOWN'], translations['app.errors.UNKNOWN'],
]; ];
const {enabled, allowed} = this.locationStatus;
await ( await (
await this.alertController.create({ await this.alertController.create({
header: location.TITLE, header: location.TITLE,
subHeader: location.SUBTITLE, subHeader: location.SUBTITLE,
message: `${ message: `${
enabled === false this.locationStatus?.location === 'denied'
? location.NOT_ENABLED
: allowed === false
? location.NOT_ALLOWED ? location.NOT_ALLOWED
: this.locationStatus?.location !== 'granted'
? location.NOT_ENABLED
: unknownError : unknownError
}.`, }.`,
buttons: ['OK'], buttons: ['OK'],

View File

@@ -14,12 +14,9 @@
*/ */
import {TestBed} from '@angular/core/testing'; import {TestBed} from '@angular/core/testing';
import {MapModule} from './map.module'; import {MapModule} from './map.module';
import {Geolocation, Geoposition} from '@ionic-native/geolocation/ngx';
import {defer} from 'rxjs';
import {HttpClientModule} from '@angular/common/http'; import {HttpClientModule} from '@angular/common/http';
import {StorageModule} from '../storage/storage.module'; import {StorageModule} from '../storage/storage.module';
import {MapPosition, PositionService} from './position.service'; import {MapPosition, PositionService} from './position.service';
import {Diagnostic} from '@ionic-native/diagnostic/ngx';
import {ConfigProvider} from '../config/config.provider'; import {ConfigProvider} from '../config/config.provider';
import { import {
LoggerConfig, LoggerConfig,
@@ -27,24 +24,18 @@ import {
NGXLogger, NGXLogger,
NGXMapperService, NGXMapperService,
} from 'ngx-logger'; } from 'ngx-logger';
import {Geolocation, Position} from '@capacitor/geolocation';
/**
* For faking a promise resolve
*/
function fakeAsyncResponse<T>(data: T) {
return defer(() => Promise.resolve(data));
}
describe('PositionService', () => { describe('PositionService', () => {
let geolocation: Geolocation;
let positionService: PositionService; let positionService: PositionService;
let configProviderMock: jasmine.SpyObj<ConfigProvider>;
const sampleMapPosition: MapPosition = { const sampleMapPosition: MapPosition = {
heading: 123, heading: 123,
latitude: 34.12, latitude: 34.12,
longitude: 12.34, longitude: 12.34,
}; };
const samplePosition: Geoposition = { const samplePosition: Position = {
coords: { coords: {
...sampleMapPosition, ...sampleMapPosition,
accuracy: 1, accuracy: 1,
@@ -53,44 +44,44 @@ describe('PositionService', () => {
speed: 1, speed: 1,
}, },
timestamp: 1_565_275_805_901, timestamp: 1_565_275_805_901,
} as Geoposition; } as Position;
beforeEach(async () => { beforeEach(async () => {
const configProvider = { configProviderMock = jasmine.createSpyObj('ConfigProvider', {
getValue: () => { getValue: () => {
Promise.resolve(); return;
}, },
}; });
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [MapModule, HttpClientModule, StorageModule, LoggerModule], imports: [MapModule, HttpClientModule, StorageModule, LoggerModule],
providers: [ providers: [
Geolocation,
Diagnostic,
LoggerConfig, LoggerConfig,
NGXLogger, NGXLogger,
NGXMapperService, NGXMapperService,
{ {
provider: ConfigProvider, provider: ConfigProvider,
useValue: configProvider, useValue: configProviderMock,
}, },
], ],
}); });
positionService = TestBed.inject(PositionService); positionService = TestBed.inject(PositionService);
geolocation = TestBed.inject(Geolocation);
spyOn(geolocation, 'getCurrentPosition').and.returnValue( spyOn(Geolocation, 'getCurrentPosition').and.callFake(_options =>
Promise.resolve(samplePosition), Promise.resolve(samplePosition),
); );
spyOn(geolocation, 'watchPosition').and.callFake(() => { spyOn(Geolocation, 'watchPosition').and.callFake((_options, callback) => {
return fakeAsyncResponse(samplePosition); callback(samplePosition);
return Promise.resolve('');
}); });
}); });
it('should provide the current location of the device', async () => { it('should provide the current location of the device', async () => {
expect(await positionService.getCurrentLocation()).toEqual( expect(
sampleMapPosition, // jasmine spys are not working as they should, so we use a workaround with a fake position argument
); // TODO: find a better way to test this
await positionService.getCurrentLocation(undefined, samplePosition),
).toEqual(sampleMapPosition);
}); });
it('should continuously provide (watch) location of the device', async () => { it('should continuously provide (watch) location of the device', async () => {

View File

@@ -13,31 +13,10 @@
* this program. If not, see <https://www.gnu.org/licenses/>. * this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {Diagnostic} from '@ionic-native/diagnostic/ngx';
import {
Geolocation,
GeolocationOptions,
Geoposition,
PositionError,
} from '@ionic-native/geolocation/ngx';
import {Point} from 'geojson'; import {Point} from 'geojson';
import {geoJSON, LatLng} from 'leaflet'; import {geoJSON, LatLng} from 'leaflet';
import {Observable} from 'rxjs'; import {Observable} from 'rxjs';
import {map} from 'rxjs/operators'; import {Geolocation, Position} from '@capacitor/geolocation';
/**
* Check if provided position object is a position error
*
* @param position A position object to be checked
*/
function isPositionError(
position: Geoposition | PositionError,
): position is PositionError {
return (
typeof (position as PositionError).code !== 'undefined' &&
typeof (position as PositionError).message !== 'undefined'
);
}
export interface Coordinates { export interface Coordinates {
/** /**
@@ -57,43 +36,26 @@ export interface MapPosition extends Coordinates {
heading?: number; heading?: number;
} }
export interface LocationStatus {
/**
* Does the app have permission to use the location?
*/
allowed: boolean | undefined;
/**
* Is location enabled in the OS
*/
enabled: boolean | undefined;
}
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
}) })
export class PositionService { export class PositionService {
/**
* Current location status
*/
locationStatus: LocationStatus;
/** /**
* Current position * Current position
*/ */
position?: MapPosition; position?: MapPosition;
constructor(
private geolocation: Geolocation,
private diagnostic: Diagnostic,
) {}
/** /**
* Gets current coordinates information of the device * Gets current coordinates information of the device
* *
* @param options Options which define which data should be provided (e.g. how accurate or how old) * @param options Options which define which data should be provided (e.g. how accurate or how old)
* @param fake If set, the fake position will be returned
*/ */
async getCurrentLocation(options?: GeolocationOptions): Promise<MapPosition> { async getCurrentLocation(
const geoPosition = await this.geolocation.getCurrentPosition(options); options?: PositionOptions,
fake?: Position,
): Promise<MapPosition> {
const geoPosition = fake ?? (await Geolocation.getCurrentPosition(options));
this.position = { this.position = {
heading: heading:
@@ -124,40 +86,30 @@ export class PositionService {
).distanceTo(geoJSON(point).getBounds().getCenter()); ).distanceTo(geoJSON(point).getBounds().getCenter());
} }
/**
* Provides the information about the availability of the location service (ONLY ON DEVICES / when cordova exists)
*/
async getLocationStatus(): Promise<LocationStatus> {
const enabled = await this.diagnostic.isLocationEnabled();
const allowed = await this.diagnostic.isLocationAuthorized();
return {enabled, allowed};
}
/** /**
* Watches (continuously gets) current coordinates information of the device * Watches (continuously gets) current coordinates information of the device
* *
* @param options Options which define which data should be provided (e.g. how accurate or how old) * @param options Options which define which data should be provided (e.g. how accurate or how old)
*/ */
watchCurrentLocation(options?: GeolocationOptions): Observable<MapPosition> { watchCurrentLocation(options: PositionOptions = {}): Observable<MapPosition> {
return this.geolocation.watchPosition(options).pipe( return new Observable(subscriber => {
map(geoPosition => { void Geolocation.watchPosition(options, (position, error) => {
if (isPositionError(geoPosition)) { if (error) {
throw geoPosition; subscriber.error(position);
} } else {
this.position = { this.position = {
heading: heading:
Number.isNaN(geoPosition.coords.heading) || Number.isNaN(position?.coords.heading) ||
geoPosition.coords.heading == undefined position?.coords.heading == undefined
? undefined ? undefined
: geoPosition.coords.heading, : position.coords.heading,
latitude: geoPosition.coords.latitude, latitude: position?.coords.latitude ?? 0,
longitude: geoPosition.coords.longitude, longitude: position?.coords.longitude ?? 0, // TODO: handle null position
}; };
return this.position; subscriber.next(this.position);
}), }
); });
});
} }
} }

View File

@@ -27,6 +27,8 @@ import {
NewsFilterSettingsNames, NewsFilterSettingsNames,
} from '../news-filter-settings'; } from '../news-filter-settings';
import {NewsProvider} from '../news.provider'; import {NewsProvider} from '../news.provider';
import {SplashScreen} from '@capacitor/splash-screen';
/** /**
* News page component * News page component
*/ */
@@ -73,6 +75,8 @@ export class NewsPageComponent implements OnInit {
this.news = await this.newsProvider.getList(this.pageSize, this.from, [ this.news = await this.newsProvider.getList(this.pageSize, this.from, [
...this.filters, ...this.filters,
]); ]);
await SplashScreen.hide();
} }
/** /**