diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2977461
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+install:
+ ionic cordova plugin add cordova-plugin-local-notification
+ npm install --save @ionic-native/local-notifications
+ npm install --save @ionic-native/core
+ npm install --save @capacitor/core
+
+android:
+ ionic build
+ sudo archlinux-java set java-8-openjdk
+ ANDROID_SDK_ROOT=/home/mal/Android/Sdk JAVA_HOME=/usr/lib/jvm/java-8-openjdk/ ionic cordova build android
+ sudo archlinux-java set java-11-openjdk
+
+deployment:
+ read VERSION
+ cp platforms/android/app/build/outputs/apk/debug/app-debug.apk '/run/user/1000/gvfs/mtp:host=Fairphone_FP2_ff87fc9d/Interner gemeinsamer Speicher/bluetooth/metasocket-${VERSION}.apk'
+
+
diff --git a/build/android/build.bash b/build/android/build.bash
new file mode 100755
index 0000000..62c0dab
--- /dev/null
+++ b/build/android/build.bash
@@ -0,0 +1,60 @@
+#/bin/bash
+
+TARGET='/home/mal/Code/Ionic/metasocket-cordova/resources/android'
+TARGET_RESOURCES=${TARGET}
+TARGET_JAVA=/home/mal/Code/Ionic/metasocket-cordova/platforms/android/app/java/com/metasocket/app
+
+RESOURCES='/home/mal/Code/Ionic/metasocket-cordova/build/android'
+
+# SPLASH LANDSCAPE
+inkscape ${RESOURCES}/splash-drawable-480x320.svg -o ${TARGET_RESOURCES}/splash/drawable-land-ldpi-screen.png -w 320 -h 240 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-800x480.svg -o ${TARGET_RESOURCES}/splash/drawable-land-hdpi-screen.png -w 800 -h 480 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-480x320.svg -o ${TARGET_RESOURCES}/splash/drawable-land-mdpi-screen.png -w 480 -h 320 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-1280x720.svg -o ${TARGET_RESOURCES}/splash/drawable-land-xhdpi-screen.png -w 1280 -h 720 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-1600x960.svg -o ${TARGET_RESOURCES}/splash/drawable-land-xxhdpi-screen.png -w 1600 -h 960 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-1920x1280.svg -o ${TARGET_RESOURCES}/splash/drawable-land-xxxhdpi-screen.png -w 1920 -h 1280 --export-overwrite
+
+# SPLASH PORTRAIT
+inkscape ${RESOURCES}/splash-drawable-320x480.svg -o ${TARGET_RESOURCES}/splash/drawable-port-ldpi-screen.png -w 240 -h 320 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-480x800.svg -o ${TARGET_RESOURCES}/splash/drawable-port-hdpi-screen.png -w 480 -h 800 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-320x480.svg -o ${TARGET_RESOURCES}/splash/drawable-port-mdpi-screen.png -w 320 -h 480 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-720x1280.svg -o ${TARGET_RESOURCES}/splash/drawable-port-xhdpi-screen.png -w 720 -h 1280 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-960x1600.svg -o ${TARGET_RESOURCES}/splash/drawable-port-xxhdpi-screen.png -w 960 -h 1600 --export-overwrite
+inkscape ${RESOURCES}/splash-drawable-1280x1920.svg -o ${TARGET_RESOURCES}/splash/drawable-port-xxxhdpi-screen.png -w 1280 -h 1920 --export-overwrite
+
+# ICONS
+inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/icon/drawable-ldpi-icon.png -w 36 -h 36 --export-overwrite
+
+inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/icon/drawable-hdpi-icon.png -w 72 -h 72 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher_round.svg -o ${TARGET_RESOURCES}/icon/drawable-mipmap-hdpi/ic_launcher_round.png -w 72 -h 72 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/mipmap-hdpi/ic_launcher_foreground.png -w 162 -h 162 --export-overwrite
+
+inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/icon/drawable-mdpi-icon.png -w 48 -h 48 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher_round.svg -o ${TARGET_RESOURCES}/mipmap-mdpi/ic_launcher_round.png -w 48 -h 48 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/mipmap-mdpi/ic_launcher_foreground.png -w 108 -h 108 --export-overwrite
+
+inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/icon/drawable-xhdpi-icon.png -w 96 -h 96 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher_round.svg -o ${TARGET_RESOURCES}/mipmap-xhdpi/ic_launcher_round.png -w 96 -h 96 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/mipmap-xhdpi/ic_launcher_foreground.png -w 216 -h 216 --export-overwrite
+
+inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/icon/drawable-xxhdpi-icon.png -w 144 -h 144 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher_round.svg -o ${TARGET_RESOURCES}/mipmap-xxhdpi/ic_launcher_round.png -w 144 -h 144 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/mipmap-xxhdpi/ic_launcher_foreground.png -w 324 -h 324 --export-overwrite
+
+inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/icon/drawable-xxxhdpi-icon.png -w 192 -h 192 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher_round.svg -o ${TARGET_RESOURCES}/mipmap-xxxhdpi/ic_launcher_round.png -w 192 -h 192 --export-overwrite
+# inkscape ${RESOURCES}/ic_launcher.svg -o ${TARGET_RESOURCES}/mipmap-xxxhdpi/ic_launcher_foreground.png -w 432 -h 432 --export-overwrite
+
+exit 0
+
+# cp -R ${RESOURCES}/res/* ${TARGET_RESOURCES}/
+
+# SOUND
+mkdir -p ${TARGET_RESOURCES}/raw
+cp ${RESOURCES}/murloc.wav ${TARGET_RESOURCES}/raw/
+
+# OVERRIDE MainActivity.java
+# cp ${RESOURCES}/MainActivity.java ${TARGET_JAVA}/
+
+# OVERRIDE AndroidManifest.xml
+cp ${RESOURCES}/AndroidManifest.xml ${TARGET}/
diff --git a/build/android/ic_launcher.svg b/build/android/ic_launcher.svg
new file mode 100644
index 0000000..d077488
--- /dev/null
+++ b/build/android/ic_launcher.svg
@@ -0,0 +1,68 @@
+
+
diff --git a/build/android/ic_launcher_round.svg b/build/android/ic_launcher_round.svg
new file mode 100644
index 0000000..d6ce0e6
--- /dev/null
+++ b/build/android/ic_launcher_round.svg
@@ -0,0 +1,67 @@
+
+
diff --git a/build/android/notification-icon-disabled.svg b/build/android/notification-icon-disabled.svg
new file mode 100644
index 0000000..bdcc628
--- /dev/null
+++ b/build/android/notification-icon-disabled.svg
@@ -0,0 +1,62 @@
+
+
diff --git a/build/android/notification-icon-enabled.svg b/build/android/notification-icon-enabled.svg
new file mode 100644
index 0000000..c87d643
--- /dev/null
+++ b/build/android/notification-icon-enabled.svg
@@ -0,0 +1,62 @@
+
+
diff --git a/build/android/res/drawable-hdpi/ic_stat_notification_icon_enabled.png b/build/android/res/drawable-hdpi/ic_stat_notification_icon_enabled.png
new file mode 100644
index 0000000..a0ec5c7
Binary files /dev/null and b/build/android/res/drawable-hdpi/ic_stat_notification_icon_enabled.png differ
diff --git a/build/android/res/drawable-mdpi/ic_stat_notification_icon_enabled.png b/build/android/res/drawable-mdpi/ic_stat_notification_icon_enabled.png
new file mode 100644
index 0000000..8c08017
Binary files /dev/null and b/build/android/res/drawable-mdpi/ic_stat_notification_icon_enabled.png differ
diff --git a/build/android/res/drawable-xhdpi/ic_stat_notification_icon_enabled.png b/build/android/res/drawable-xhdpi/ic_stat_notification_icon_enabled.png
new file mode 100644
index 0000000..91b3910
Binary files /dev/null and b/build/android/res/drawable-xhdpi/ic_stat_notification_icon_enabled.png differ
diff --git a/build/android/res/drawable-xxhdpi/ic_stat_notification_icon_enabled.png b/build/android/res/drawable-xxhdpi/ic_stat_notification_icon_enabled.png
new file mode 100644
index 0000000..80d7209
Binary files /dev/null and b/build/android/res/drawable-xxhdpi/ic_stat_notification_icon_enabled.png differ
diff --git a/build/android/res/drawable-xxxhdpi/ic_stat_notification_icon_enabled.png b/build/android/res/drawable-xxxhdpi/ic_stat_notification_icon_enabled.png
new file mode 100644
index 0000000..1916b86
Binary files /dev/null and b/build/android/res/drawable-xxxhdpi/ic_stat_notification_icon_enabled.png differ
diff --git a/build/android/splash-drawable-1280x1920.svg b/build/android/splash-drawable-1280x1920.svg
new file mode 100644
index 0000000..4e75fae
--- /dev/null
+++ b/build/android/splash-drawable-1280x1920.svg
@@ -0,0 +1,73 @@
+
+
diff --git a/build/android/splash-drawable-1280x720.svg b/build/android/splash-drawable-1280x720.svg
new file mode 100644
index 0000000..b56de82
--- /dev/null
+++ b/build/android/splash-drawable-1280x720.svg
@@ -0,0 +1,72 @@
+
+
diff --git a/build/android/splash-drawable-1600x960.svg b/build/android/splash-drawable-1600x960.svg
new file mode 100644
index 0000000..b6e1ae4
--- /dev/null
+++ b/build/android/splash-drawable-1600x960.svg
@@ -0,0 +1,72 @@
+
+
diff --git a/build/android/splash-drawable-1920x1280.svg b/build/android/splash-drawable-1920x1280.svg
new file mode 100644
index 0000000..4a6b202
--- /dev/null
+++ b/build/android/splash-drawable-1920x1280.svg
@@ -0,0 +1,72 @@
+
+
diff --git a/build/android/splash-drawable-320x480.svg b/build/android/splash-drawable-320x480.svg
new file mode 100644
index 0000000..8ab1169
--- /dev/null
+++ b/build/android/splash-drawable-320x480.svg
@@ -0,0 +1,69 @@
+
+
diff --git a/build/android/splash-drawable-480x320.svg b/build/android/splash-drawable-480x320.svg
new file mode 100644
index 0000000..97a80b8
--- /dev/null
+++ b/build/android/splash-drawable-480x320.svg
@@ -0,0 +1,68 @@
+
+
diff --git a/build/android/splash-drawable-480x800.svg b/build/android/splash-drawable-480x800.svg
new file mode 100644
index 0000000..f95b925
--- /dev/null
+++ b/build/android/splash-drawable-480x800.svg
@@ -0,0 +1,73 @@
+
+
diff --git a/build/android/splash-drawable-720x1280.svg b/build/android/splash-drawable-720x1280.svg
new file mode 100644
index 0000000..77993e5
--- /dev/null
+++ b/build/android/splash-drawable-720x1280.svg
@@ -0,0 +1,73 @@
+
+
diff --git a/build/android/splash-drawable-800x480.svg b/build/android/splash-drawable-800x480.svg
new file mode 100644
index 0000000..9adec9d
--- /dev/null
+++ b/build/android/splash-drawable-800x480.svg
@@ -0,0 +1,72 @@
+
+
diff --git a/build/android/splash-drawable-960x1600.svg b/build/android/splash-drawable-960x1600.svg
new file mode 100644
index 0000000..d3ad235
--- /dev/null
+++ b/build/android/splash-drawable-960x1600.svg
@@ -0,0 +1,73 @@
+
+
diff --git a/build/android/splash.svg b/build/android/splash.svg
new file mode 100644
index 0000000..f516cba
--- /dev/null
+++ b/build/android/splash.svg
@@ -0,0 +1,68 @@
+
+
diff --git a/build/ios/AppIcon.svg b/build/ios/AppIcon.svg
new file mode 100644
index 0000000..d077488
--- /dev/null
+++ b/build/ios/AppIcon.svg
@@ -0,0 +1,68 @@
+
+
diff --git a/build/ios/build.bash b/build/ios/build.bash
new file mode 100755
index 0000000..3672e14
--- /dev/null
+++ b/build/ios/build.bash
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+TARGET='/home/mal/Code/Angular/metasocket/ios/App/App/Assets.xcassets'
+RESOURCES='/home/mal/Code/Angular/metasocket/build/ios'
+
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-20x20@1x.png -w 20 -h 20 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-20x20@2x.png -w 40 -h 40 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-20x20@2x-1.png -w 40 -h 40 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-20x20@3x.png -w 60 -h 60 --export-overwrite
+
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-29x29@1x.png -w 29 -h 29 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-29x29@2x.png -w 58 -h 58 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-29x29@2x-1.png -w 58 -h 58 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-29x29@3x.png -w 87 -h 87 --export-overwrite
+
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-40x40@1x.png -w 40 -h 40 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-40x40@2x.png -w 80 -h 80 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-40x40@2x-1.png -w 80 -h 80 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-40x40@3x.png -w 120 -h 120 --export-overwrite
+
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-60x60@2x.png -w 120 -h 120 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-60x60@3x.png -w 180 -h 180 --export-overwrite
+
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-76x76@1x.png -w 76 -h 76 --export-overwrite
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-76x76@2x.png -w 152 -h 152 --export-overwrite
+
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-83.5x83.5@2x.png -w 167 -h 167 --export-overwrite
+
+inkscape ${RESOURCES}/AppIcon.svg -o ${TARGET}/AppIcon.appiconset/AppIcon-512@2x.png -w 1024 -h 1024 --export-overwrite
+
+inkscape ${RESOURCES}/splash.svg -o ${TARGET}/Splash.imageset/splash-2732x2732.png -w 2732 -h 2732 --export-overwrite
+inkscape ${RESOURCES}/splash.svg -o ${TARGET}/Splash.imageset/splash-2732x2732-1.png -w 2732 -h 2732 --export-overwrite
+inkscape ${RESOURCES}/splash.svg -o ${TARGET}/Splash.imageset/splash-2732x2732-2.png -w 2732 -h 2732 --export-overwrite
diff --git a/build/ios/splash.svg b/build/ios/splash.svg
new file mode 100644
index 0000000..3a9cc2e
--- /dev/null
+++ b/build/ios/splash.svg
@@ -0,0 +1,68 @@
+
+
diff --git a/config.xml b/config.xml
new file mode 100644
index 0000000..3e6546d
--- /dev/null
+++ b/config.xml
@@ -0,0 +1,101 @@
+
+
+ METAsocket
+ WowApp's awesome instant messenger
+ Ionic Framework Team
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ionic.config.json b/ionic.config.json
index b8710bf..8bd5282 100644
--- a/ionic.config.json
+++ b/ionic.config.json
@@ -1,5 +1,7 @@
{
"name": "metasocket-cordova",
- "integrations": {},
+ "integrations": {
+ "cordova": {}
+ },
"type": "angular"
}
diff --git a/package-lock.json b/package-lock.json
index 4504aac..4fcbe94 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1566,6 +1566,53 @@
"to-fast-properties": "^2.0.0"
}
},
+ "@capacitor/core": {
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-2.4.6.tgz",
+ "integrity": "sha512-3KLSMorCELA5RNRXwHOGlRGuxXaxCEYHC29wOUxObicI2mf14hbMJWylt4QBzNmSqh3/ha7u4/CAZMoJUQR/QA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ }
+ }
+ },
+ "@ionic-native/background-mode": {
+ "version": "5.31.1",
+ "resolved": "https://registry.npmjs.org/@ionic-native/background-mode/-/background-mode-5.31.1.tgz",
+ "integrity": "sha512-m5pCR2/QPblE5u9eqRC04qUyHkB0FzgD0a3/G6Q1Xx00BmuBeA/95BB2Htyrt3Ly/pp3W+ynTwljFMeDayi6bw==",
+ "requires": {
+ "@types/cordova": "^0.0.34"
+ }
+ },
+ "@ionic-native/core": {
+ "version": "5.31.1",
+ "resolved": "https://registry.npmjs.org/@ionic-native/core/-/core-5.31.1.tgz",
+ "integrity": "sha512-dbJHezSuY8OqyFwyQiS+5QscA/BONhWitXgniljEblC5kQeLOCe+8p30JYHXj9xDciYzfqFP8ICmyaGOqUHJYw==",
+ "requires": {
+ "@types/cordova": "^0.0.34"
+ }
+ },
+ "@ionic-native/foreground-service": {
+ "version": "5.31.1",
+ "resolved": "https://registry.npmjs.org/@ionic-native/foreground-service/-/foreground-service-5.31.1.tgz",
+ "integrity": "sha512-ln+2b9VgynZaemcAq+8v0BQ6Qxnx4veebVnAGsZ5fGzwqGIW9qMAbzncWJo9k7CK/jWDjZiqviIbKTxw4uPptQ==",
+ "requires": {
+ "@types/cordova": "^0.0.34"
+ }
+ },
+ "@ionic-native/local-notifications": {
+ "version": "5.31.1",
+ "resolved": "https://registry.npmjs.org/@ionic-native/local-notifications/-/local-notifications-5.31.1.tgz",
+ "integrity": "sha512-OOd4EUnnfpDbvuJIwh3UzJ/6fFMTmf8f43mAfU0URkUS/LVJpl9aJzDCOLIB+0RXo+ZeRqW17q44qgUArgz1VQ==",
+ "requires": {
+ "@types/cordova": "^0.0.34"
+ }
+ },
"@ionic/angular": {
"version": "5.5.5",
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-5.5.5.tgz",
@@ -1646,6 +1693,25 @@
"schema-utils": "^2.7.0"
}
},
+ "@netflix/nerror": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@netflix/nerror/-/nerror-1.1.3.tgz",
+ "integrity": "sha512-b+MGNyP9/LXkapreJzNUzcvuzZslj/RGgdVVJ16P2wSlYatfLycPObImqVJSmNAdyeShvNeM/pl3sVZsObFueg==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "extsprintf": "^1.4.0",
+ "lodash": "^4.17.15"
+ },
+ "dependencies": {
+ "extsprintf": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz",
+ "integrity": "sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=",
+ "dev": true
+ }
+ }
+ },
"@ngtools/webpack": {
"version": "11.1.4",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.1.4.tgz",
@@ -1826,6 +1892,11 @@
"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
"dev": true
},
+ "@types/cordova": {
+ "version": "0.0.34",
+ "resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
+ "integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
+ },
"@types/glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
@@ -2215,6 +2286,29 @@
"integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
"dev": true
},
+ "android-versions": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/android-versions/-/android-versions-1.6.0.tgz",
+ "integrity": "sha512-ojC2Ig7b/KJ6iNtR8e4bacmOsJyEkoERk3CKMIsnH7kJz5z6551NMbrVaRb7KXYavu1d74Uhml/bfcmqT3nAcg==",
+ "dev": true,
+ "requires": {
+ "semver": "^5.7.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "ansi": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz",
+ "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=",
+ "dev": true
+ },
"ansi-colors": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
@@ -2495,6 +2589,12 @@
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
"dev": true
},
+ "at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true
+ },
"atob": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
@@ -2679,6 +2779,12 @@
"tweetnacl": "^0.14.3"
}
},
+ "big-integer": {
+ "version": "1.6.48",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
+ "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==",
+ "dev": true
+ },
"big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
@@ -2790,6 +2896,15 @@
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
"dev": true
},
+ "bplist-parser": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
+ "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
+ "dev": true,
+ "requires": {
+ "big-integer": "^1.6.44"
+ }
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -3836,6 +3951,296 @@
}
}
},
+ "cordova-android": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-9.0.0.tgz",
+ "integrity": "sha512-2ZEgApK4LPMYW0zh/mLAH3CabzCaKE0yxQTzA2wTf0Eo2HHTJnRtDCf9spGf3nPOkubyXS6+pvzz5QzNHpVTqQ==",
+ "dev": true,
+ "requires": {
+ "android-versions": "^1.5.0",
+ "cordova-common": "^4.0.1",
+ "execa": "^4.0.2",
+ "fs-extra": "^9.0.1",
+ "nopt": "^4.0.3",
+ "properties-parser": "^0.3.1",
+ "which": "^2.0.2"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "execa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+ "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "is-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
+ "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "nopt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
+ "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
+ "dev": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "cordova-common": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/cordova-common/-/cordova-common-4.0.2.tgz",
+ "integrity": "sha512-od7aNShyuBajzPY83mUEO8tERwwWdFklXETHiXP5Ft87CWeo/tSuwNPFztyTy8XYc74yXdogXKPTJeUHuVzB8Q==",
+ "dev": true,
+ "requires": {
+ "@netflix/nerror": "^1.1.3",
+ "ansi": "^0.3.1",
+ "bplist-parser": "^0.2.0",
+ "cross-spawn": "^7.0.1",
+ "elementtree": "^0.1.7",
+ "endent": "^1.4.1",
+ "fast-glob": "^3.2.2",
+ "fs-extra": "^9.0.0",
+ "glob": "^7.1.6",
+ "plist": "^3.0.1",
+ "q": "^1.5.1",
+ "read-chunk": "^3.2.0",
+ "strip-bom": "^4.0.0",
+ "underscore": "^1.9.2"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "cordova-plugin-background-mode": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-background-mode/-/cordova-plugin-background-mode-0.7.3.tgz",
+ "integrity": "sha512-LsU1v7EgTUROaks+tcQ8TnMzVUcU/TwjDVwj2O/4e4aI2q2ldLGsiZorqKqfqvwh2HoIssmY73OwJk91hQi62w==",
+ "dev": true
+ },
+ "cordova-plugin-badge": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-badge/-/cordova-plugin-badge-0.8.8.tgz",
+ "integrity": "sha512-RhIBtd5xhD/iLnxjt35jvOae28oNW/wtMZBOmQR3Rf0y4wirvA1bpAZEhBoFqL+rZGhsd6ddOdQXdex1T0DRyQ==",
+ "dev": true
+ },
+ "cordova-plugin-device": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-device/-/cordova-plugin-device-2.0.3.tgz",
+ "integrity": "sha512-Jb3V72btxf3XHpkPQsGdyc8N6tVBYn1vsxSFj43fIz9vonJDUThYPCJJHqk6PX6N4dJw6I4FjxkpfCR4LDYMlw==",
+ "dev": true
+ },
+ "cordova-plugin-foreground-service": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-foreground-service/-/cordova-plugin-foreground-service-1.1.3.tgz",
+ "integrity": "sha512-/C2Z8w9JIfAaLeXP290msQP9jcHR+CAJYbp6/x+mS21VtvS2Ug0upKsgjEzzSzRnt08Mr8kuwCV7juUd6eCWcw==",
+ "dev": true
+ },
+ "cordova-plugin-ionic-keyboard": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-ionic-keyboard/-/cordova-plugin-ionic-keyboard-2.2.0.tgz",
+ "integrity": "sha512-yDUG+9ieKVRitq5mGlNxjaZh/MgEhFFIgTIPhqSbUaQ8UuZbawy5mhJAVClqY97q8/rcQtL6dCDa7x2sEtCLcA==",
+ "dev": true
+ },
+ "cordova-plugin-ionic-webview": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-ionic-webview/-/cordova-plugin-ionic-webview-4.2.1.tgz",
+ "integrity": "sha512-7KrmqLaOGq1RP8N2z1ezN1kqkWFzTwwMvQ3/qAkd+exxFZuOe3DIN4eaU1gdNphsxdirI8Ajnr9q4So5vQbWqw==",
+ "dev": true
+ },
+ "cordova-plugin-local-notification": {
+ "version": "0.9.0-beta.2",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-local-notification/-/cordova-plugin-local-notification-0.9.0-beta.2.tgz",
+ "integrity": "sha512-63n77K1pt8dnbWnNR8QWETi9Glezi1bvNHvHWmGNIOv0xCb0phZnm+Ku49BQ+omwe8Z5voMvrA4I03SYPpv38w==",
+ "dev": true
+ },
+ "cordova-plugin-splashscreen": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-splashscreen/-/cordova-plugin-splashscreen-5.0.2.tgz",
+ "integrity": "sha1-dH509W4gHNWFvGLRS8oZ9oZ/8e0=",
+ "dev": true
+ },
+ "cordova-plugin-statusbar": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-statusbar/-/cordova-plugin-statusbar-2.4.2.tgz",
+ "integrity": "sha1-/B+9wNjXAzp+jh8ff/FnrJvU+vY=",
+ "dev": true
+ },
+ "cordova-plugin-whitelist": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.3.3.tgz",
+ "integrity": "sha1-tehezbv+Wu3tQKG/TuI3LmfZb7Q=",
+ "dev": true
+ },
"core-js": {
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.2.tgz",
@@ -4490,6 +4895,12 @@
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
"dev": true
},
+ "dedent": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
+ "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
+ "dev": true
+ },
"deep-equal": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
@@ -4876,6 +5287,23 @@
"integrity": "sha512-GEQw+6dNWjueXGkGfjgm7dAMtXfEqrfDG3uWcZdeaD4cZ3dKYdPRQVruVXQRXtPLtOr5GNVVlNLRMChOZ611pQ==",
"dev": true
},
+ "elementtree": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.7.tgz",
+ "integrity": "sha1-mskb5uUvtuYkTE5UpKw+2K6OKcA=",
+ "dev": true,
+ "requires": {
+ "sax": "1.1.4"
+ },
+ "dependencies": {
+ "sax": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz",
+ "integrity": "sha1-dLbTPJrh4AFRDxeakRaFiPGu2qk=",
+ "dev": true
+ }
+ }
+ },
"elliptic": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
@@ -4948,6 +5376,17 @@
"once": "^1.4.0"
}
},
+ "endent": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/endent/-/endent-1.4.1.tgz",
+ "integrity": "sha512-buHTb5c8AC9NshtP6dgmNLYkiT+olskbq1z6cEGvfGCF3Qphbu/1zz5Xu+yjTDln8RbxNhPoUyJ5H8MSrp1olQ==",
+ "dev": true,
+ "requires": {
+ "dedent": "^0.7.0",
+ "fast-json-parse": "^1.0.3",
+ "objectorarray": "^1.0.4"
+ }
+ },
"engine.io": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz",
@@ -5550,6 +5989,12 @@
"picomatch": "^2.2.1"
}
},
+ "fast-json-parse": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz",
+ "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==",
+ "dev": true
+ },
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -6531,6 +6976,12 @@
"debug": "4"
}
},
+ "human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "dev": true
+ },
"humanize-ms": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
@@ -8894,6 +9345,12 @@
"has": "^1.0.3"
}
},
+ "objectorarray": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.4.tgz",
+ "integrity": "sha512-91k8bjcldstRz1bG6zJo8lWD7c6QXcB4nTDUqiEvIL1xAsLoZlOOZZG+nd6YPz+V7zY1580J4Xxh1vZtyv4i/w==",
+ "dev": true
+ },
"obuf": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
@@ -9042,12 +9499,28 @@
"integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
"dev": true
},
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true
+ },
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
+ "osenv": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+ "dev": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
@@ -9379,6 +9852,25 @@
"find-up": "^4.0.0"
}
},
+ "plist": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz",
+ "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.2.3",
+ "xmlbuilder": "^9.0.7",
+ "xmldom": "0.1.x"
+ },
+ "dependencies": {
+ "xmlbuilder": {
+ "version": "9.0.7",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
+ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
+ "dev": true
+ }
+ }
+ },
"pnp-webpack-plugin": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz",
@@ -10804,6 +11296,15 @@
}
}
},
+ "properties-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/properties-parser/-/properties-parser-0.3.1.tgz",
+ "integrity": "sha1-ExbpU5/7/ZOEXjabIRAiq9R4dxo=",
+ "dev": true,
+ "requires": {
+ "string.prototype.codepointat": "^0.2.0"
+ }
+ },
"protractor": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz",
@@ -11335,6 +11836,16 @@
}
}
},
+ "read-chunk": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz",
+ "integrity": "sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ==",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "with-open-file": "^0.1.6"
+ }
+ },
"read-package-json-fast": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-1.2.2.tgz",
@@ -12906,6 +13417,12 @@
"strip-ansi": "^6.0.0"
}
},
+ "string.prototype.codepointat": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz",
+ "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==",
+ "dev": true
+ },
"string.prototype.trimend": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
@@ -12952,12 +13469,24 @@
"ansi-regex": "^5.0.0"
}
},
+ "strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true
+ },
"strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
"dev": true
},
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true
+ },
"style-loader": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz",
@@ -13534,6 +14063,12 @@
"integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==",
"dev": true
},
+ "underscore": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.0.tgz",
+ "integrity": "sha512-21rQzss/XPMjolTiIezSu3JAjgagXKROtNrYFEOWK109qY1Uv2tVjPTZ1ci2HgvQDA16gHYSthQIJfB+XId/rQ==",
+ "dev": true
+ },
"unicode-canonical-property-names-ecmascript": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
@@ -15053,6 +15588,17 @@
"integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==",
"dev": true
},
+ "with-open-file": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz",
+ "integrity": "sha512-ecJS2/oHtESJ1t3ZfMI3B7KIDKyfN0O16miWxdn30zdh66Yd3LsRFebXZXq6GU4xfxLf6nVxp9kIqElb5fqczA==",
+ "dev": true,
+ "requires": {
+ "p-finally": "^1.0.0",
+ "p-try": "^2.1.0",
+ "pify": "^4.0.1"
+ }
+ },
"worker-farm": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
@@ -15175,6 +15721,12 @@
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
"dev": true
},
+ "xmldom": {
+ "version": "0.1.31",
+ "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz",
+ "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==",
+ "dev": true
+ },
"xmlhttprequest-ssl": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
diff --git a/package.json b/package.json
index 1d20ded..22176bd 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,11 @@
"@angular/platform-browser": "~11.2.0",
"@angular/platform-browser-dynamic": "~11.2.0",
"@angular/router": "~11.2.0",
+ "@capacitor/core": "^2.4.6",
+ "@ionic-native/background-mode": "^5.31.1",
+ "@ionic-native/core": "^5.31.1",
+ "@ionic-native/foreground-service": "^5.31.1",
+ "@ionic-native/local-notifications": "^5.31.1",
"@ionic/angular": "^5.5.2",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
@@ -35,6 +40,17 @@
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
+ "cordova-android": "^9.0.0",
+ "cordova-plugin-background-mode": "^0.7.3",
+ "cordova-plugin-badge": "^0.8.8",
+ "cordova-plugin-device": "^2.0.3",
+ "cordova-plugin-foreground-service": "^1.1.3",
+ "cordova-plugin-ionic-keyboard": "^2.2.0",
+ "cordova-plugin-ionic-webview": "^4.2.1",
+ "cordova-plugin-local-notification": "^0.9.0-beta.2",
+ "cordova-plugin-splashscreen": "^5.0.2",
+ "cordova-plugin-statusbar": "^2.4.2",
+ "cordova-plugin-whitelist": "^1.3.3",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~5.2.0",
@@ -48,5 +64,23 @@
"tslint": "~6.1.0",
"typescript": "~4.0.2"
},
- "description": "An Ionic project"
+ "description": "An Ionic project",
+ "cordova": {
+ "plugins": {
+ "cordova-plugin-local-notification": {},
+ "cordova-plugin-whitelist": {},
+ "cordova-plugin-statusbar": {},
+ "cordova-plugin-device": {},
+ "cordova-plugin-splashscreen": {},
+ "cordova-plugin-ionic-webview": {
+ "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
+ },
+ "cordova-plugin-ionic-keyboard": {},
+ "cordova-plugin-background-mode": {},
+ "cordova-plugin-foreground-service": {}
+ },
+ "platforms": [
+ "android"
+ ]
+ }
}
diff --git a/resources/android/icon/drawable-hdpi-icon.png b/resources/android/icon/drawable-hdpi-icon.png
new file mode 100644
index 0000000..0913286
Binary files /dev/null and b/resources/android/icon/drawable-hdpi-icon.png differ
diff --git a/resources/android/icon/drawable-ldpi-icon.png b/resources/android/icon/drawable-ldpi-icon.png
new file mode 100644
index 0000000..9aa7982
Binary files /dev/null and b/resources/android/icon/drawable-ldpi-icon.png differ
diff --git a/resources/android/icon/drawable-mdpi-icon.png b/resources/android/icon/drawable-mdpi-icon.png
new file mode 100644
index 0000000..f630706
Binary files /dev/null and b/resources/android/icon/drawable-mdpi-icon.png differ
diff --git a/resources/android/icon/drawable-xhdpi-icon.png b/resources/android/icon/drawable-xhdpi-icon.png
new file mode 100644
index 0000000..717b017
Binary files /dev/null and b/resources/android/icon/drawable-xhdpi-icon.png differ
diff --git a/resources/android/icon/drawable-xxhdpi-icon.png b/resources/android/icon/drawable-xxhdpi-icon.png
new file mode 100644
index 0000000..cb7d456
Binary files /dev/null and b/resources/android/icon/drawable-xxhdpi-icon.png differ
diff --git a/resources/android/icon/drawable-xxxhdpi-icon.png b/resources/android/icon/drawable-xxxhdpi-icon.png
new file mode 100644
index 0000000..53d8b39
Binary files /dev/null and b/resources/android/icon/drawable-xxxhdpi-icon.png differ
diff --git a/resources/android/splash/drawable-land-hdpi-screen.png b/resources/android/splash/drawable-land-hdpi-screen.png
new file mode 100644
index 0000000..1932966
Binary files /dev/null and b/resources/android/splash/drawable-land-hdpi-screen.png differ
diff --git a/resources/android/splash/drawable-land-ldpi-screen.png b/resources/android/splash/drawable-land-ldpi-screen.png
new file mode 100644
index 0000000..b3b0cc0
Binary files /dev/null and b/resources/android/splash/drawable-land-ldpi-screen.png differ
diff --git a/resources/android/splash/drawable-land-mdpi-screen.png b/resources/android/splash/drawable-land-mdpi-screen.png
new file mode 100644
index 0000000..e00f74b
Binary files /dev/null and b/resources/android/splash/drawable-land-mdpi-screen.png differ
diff --git a/resources/android/splash/drawable-land-xhdpi-screen.png b/resources/android/splash/drawable-land-xhdpi-screen.png
new file mode 100644
index 0000000..533d3a7
Binary files /dev/null and b/resources/android/splash/drawable-land-xhdpi-screen.png differ
diff --git a/resources/android/splash/drawable-land-xxhdpi-screen.png b/resources/android/splash/drawable-land-xxhdpi-screen.png
new file mode 100644
index 0000000..f64e154
Binary files /dev/null and b/resources/android/splash/drawable-land-xxhdpi-screen.png differ
diff --git a/resources/android/splash/drawable-land-xxxhdpi-screen.png b/resources/android/splash/drawable-land-xxxhdpi-screen.png
new file mode 100644
index 0000000..47844f8
Binary files /dev/null and b/resources/android/splash/drawable-land-xxxhdpi-screen.png differ
diff --git a/resources/android/splash/drawable-port-hdpi-screen.png b/resources/android/splash/drawable-port-hdpi-screen.png
new file mode 100644
index 0000000..0089232
Binary files /dev/null and b/resources/android/splash/drawable-port-hdpi-screen.png differ
diff --git a/resources/android/splash/drawable-port-ldpi-screen.png b/resources/android/splash/drawable-port-ldpi-screen.png
new file mode 100644
index 0000000..76e8c70
Binary files /dev/null and b/resources/android/splash/drawable-port-ldpi-screen.png differ
diff --git a/resources/android/splash/drawable-port-mdpi-screen.png b/resources/android/splash/drawable-port-mdpi-screen.png
new file mode 100644
index 0000000..9785306
Binary files /dev/null and b/resources/android/splash/drawable-port-mdpi-screen.png differ
diff --git a/resources/android/splash/drawable-port-xhdpi-screen.png b/resources/android/splash/drawable-port-xhdpi-screen.png
new file mode 100644
index 0000000..b4f1315
Binary files /dev/null and b/resources/android/splash/drawable-port-xhdpi-screen.png differ
diff --git a/resources/android/splash/drawable-port-xxhdpi-screen.png b/resources/android/splash/drawable-port-xxhdpi-screen.png
new file mode 100644
index 0000000..83af947
Binary files /dev/null and b/resources/android/splash/drawable-port-xxhdpi-screen.png differ
diff --git a/resources/android/splash/drawable-port-xxxhdpi-screen.png b/resources/android/splash/drawable-port-xxxhdpi-screen.png
new file mode 100644
index 0000000..76e01cc
Binary files /dev/null and b/resources/android/splash/drawable-port-xxxhdpi-screen.png differ
diff --git a/resources/icon.png b/resources/icon.png
new file mode 100644
index 0000000..0dfc0ca
Binary files /dev/null and b/resources/icon.png differ
diff --git a/src/app/api.service.ts b/src/app/api.service.ts
new file mode 100644
index 0000000..7e6cee8
--- /dev/null
+++ b/src/app/api.service.ts
@@ -0,0 +1,52 @@
+import {Injectable} from '@angular/core';
+import {Observable} from 'rxjs';
+import {HttpClient} from '@angular/common/http';
+import {Token} from './token';
+import {Host} from './host';
+import {ChatMessage} from './chat.message';
+import {ChatTokenResponse} from './chat.token';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ApiService {
+ public static userToken: string;
+
+ constructor(private client: HttpClient) {
+ }
+
+ storeData(key: string, value: string): void
+ {
+ sessionStorage.setItem(key, value);
+ }
+
+ getFromStorage(key: string): string {
+ return sessionStorage.getItem(key);
+ }
+
+ getAuthToken(username: string, password: string): Observable {
+ return this.client.post(Host.URL + '/token', {username, password});
+ }
+
+ getChatToken(authToken: string): Observable {
+ return this.client.get(
+ Host.URL + '/session/chat',
+ {headers: {Authorization: 'Bearer ' + authToken}}
+ );
+ }
+
+ getChatHistory(token: string, offset: number, limit: number): Observable {
+ return this.client.get(
+ Host.URL + '/session/chat/history?limit=' + limit + '&offset=' + offset,
+ {headers: {Authorization: 'Bearer ' + token}}
+ );
+ }
+
+ deleteAuthToken(token: string): Observable
+ {
+ return this.client.delete(
+ Host.URL + '/token/' + token,
+ {headers: {Authorization: 'Bearer ' + token}}
+ );
+ }
+}
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index e7b0d5a..75b1f5d 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -2,15 +2,6 @@ import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
- {
- path: 'home',
- loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)
- },
- {
- path: '',
- redirectTo: 'home',
- pathMatch: 'full'
- },
];
@NgModule({
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 13b9677..0b117df 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,3 +1,4 @@
-
+
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 913de3d..01abf81 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,10 +1,23 @@
import { Component } from '@angular/core';
+import { ApiService } from './api.service';
@Component({
selector: 'app-root',
- templateUrl: 'app.component.html',
- styleUrls: ['app.component.scss'],
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.scss']
})
export class AppComponent {
- constructor() {}
+ public static token: string = null;
+
+ title = 'METAsocket';
+
+ public constructor(private apiService: ApiService)
+ {
+ AppComponent.token = this.apiService.getFromStorage('token');
+ }
+
+ public getToken(): string
+ {
+ return AppComponent.token;
+ }
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index f8b75ac..be80f6c 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -4,14 +4,25 @@ import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
+import { FormsModule } from '@angular/forms';
+import { HttpClientModule } from '@angular/common/http';
+
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
+import {ChatComponent} from './chat/chat.component';
+import {LoginComponent} from './login/login.component';
+import {TopbarComponent} from './topbar/topbar.component';
+import {LocalNotifications} from '@ionic-native/local-notifications/ngx';
+import {BackgroundMode} from '@ionic-native/background-mode/ngx';
+import {ForegroundService} from '@ionic-native/foreground-service/ngx';
@NgModule({
- declarations: [AppComponent],
+ declarations: [AppComponent, ChatComponent, LoginComponent, TopbarComponent],
entryComponents: [],
- imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
- providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
+ imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, FormsModule, HttpClientModule],
+ providers: [
+ { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, LocalNotifications, BackgroundMode, ForegroundService
+ ],
bootstrap: [AppComponent],
})
export class AppModule {}
diff --git a/src/app/chat.message.ts b/src/app/chat.message.ts
new file mode 100644
index 0000000..69b362c
--- /dev/null
+++ b/src/app/chat.message.ts
@@ -0,0 +1,7 @@
+export interface ChatMessage
+{
+ userId: number;
+ username: string;
+ message: string;
+ datetime: string;
+}
diff --git a/src/app/chat.token.ts b/src/app/chat.token.ts
new file mode 100644
index 0000000..2062282
--- /dev/null
+++ b/src/app/chat.token.ts
@@ -0,0 +1,5 @@
+export interface ChatTokenResponse
+{
+ userId: number;
+ token: string;
+}
diff --git a/src/app/chat/chat.component.html b/src/app/chat/chat.component.html
new file mode 100644
index 0000000..6ea002a
--- /dev/null
+++ b/src/app/chat/chat.component.html
@@ -0,0 +1,17 @@
+
+
+
+
+

+
+
{{message.username}}
+
{{message.message}}
+
{{message.datetime}}
+
+
+
+
+
+
+
+
diff --git a/src/app/chat/chat.component.scss b/src/app/chat/chat.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/chat/chat.component.spec.ts b/src/app/chat/chat.component.spec.ts
new file mode 100644
index 0000000..89a60fa
--- /dev/null
+++ b/src/app/chat/chat.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { IonicModule } from '@ionic/angular';
+
+import { ChatComponent } from './chat.component';
+
+describe('ChatComponent', () => {
+ let component: ChatComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ ChatComponent ],
+ imports: [IonicModule.forRoot()]
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ChatComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ }));
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/chat/chat.component.ts b/src/app/chat/chat.component.ts
new file mode 100644
index 0000000..f3ee026
--- /dev/null
+++ b/src/app/chat/chat.component.ts
@@ -0,0 +1,162 @@
+import {Plugins, AppState} from '@capacitor/core';
+import {AfterViewChecked, AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
+import {ChatMessage} from '../chat.message';
+import {Host} from '../host';
+import {ApiService} from '../api.service';
+import {WebsocketListener} from '../websocket.listener';
+import {WebsocketService} from '../websocket.service';
+import {LocalNotifications} from '@ionic-native/local-notifications/ngx';
+import {BackgroundMode} from '@ionic-native/background-mode/ngx';
+import {ForegroundService} from '@ionic-native/foreground-service/ngx';
+
+const {App} = Plugins;
+
+@Component({
+ selector: 'app-chat',
+ templateUrl: './chat.component.html',
+ styleUrls: ['./chat.component.scss'],
+})
+export class ChatComponent implements OnInit, AfterViewInit, AfterViewChecked, WebsocketListener {
+ messages: ChatMessage[] = [];
+ userToken: string;
+ userId: number;
+ url: string;
+
+ @ViewChild('chatPostArea') chatPostArea: ElementRef;
+ chatText: string;
+
+ private oldScrollHeight = 0;
+ private messageOffset = 0;
+ private messageLimit = 10;
+ private hasBeenReloaded = false;
+ private hasFocus = true;
+
+ public constructor(
+ private apiService: ApiService,
+ private websocketService: WebsocketService,
+ private localNotifications: LocalNotifications,
+ private backgroundMode: BackgroundMode,
+ private foregroundService: ForegroundService
+ ) {
+ this.userToken = this.apiService.getFromStorage('token');
+ this.userId = Number(this.apiService.getFromStorage('userId'));
+ this.url = Host.URL;
+ this.websocketService.setListener(this);
+ this.websocketService.initializeSocket(this.apiService.getFromStorage('chatToken'));
+ this.backgroundMode.disableBatteryOptimizations();
+ this.backgroundMode.disableWebViewOptimizations();
+ }
+
+ ngAfterViewInit(): void {
+ this.chatPostArea.nativeElement.scroll(0, this.chatPostArea.nativeElement.scrollHeight);
+ }
+
+ ngAfterViewChecked(): void {
+ if (this.oldScrollHeight !== this.chatPostArea.nativeElement.scrollHeight) {
+ const scrollTop = this.chatPostArea.nativeElement.scrollTop;
+ const clientHeight = this.chatPostArea.nativeElement.clientHeight;
+
+ if (this.hasBeenReloaded) {
+ this.chatPostArea.nativeElement.scroll(0, this.chatPostArea.nativeElement.scrollHeight - this.oldScrollHeight);
+ this.hasBeenReloaded = false;
+ } else if (scrollTop + clientHeight > this.oldScrollHeight - 10) {
+ this.chatPostArea.nativeElement.scroll(0, this.oldScrollHeight);
+ }
+
+ this.oldScrollHeight = this.chatPostArea.nativeElement.scrollHeight;
+ }
+ }
+
+ ngOnInit(): void {
+ if (this.userToken === null) {
+ return;
+ }
+
+ this.localNotifications.requestPermission();
+
+ this.foregroundService.start('METAsocket', 'The chat for WowApp', 'ic_stat_notification_icon_enabled');
+
+ this.apiService.getChatHistory(this.userToken, this.messageOffset, this.messageLimit).subscribe(
+ (response) => {
+ this.messages = response;
+ this.messageOffset += this.messageLimit;
+ }
+ );
+
+ App.addListener('appStateChange', (state: AppState) => {
+ this.hasFocus = state.isActive;
+ });
+
+ setInterval(
+ () => {
+ this.websocketService.sendKeepAliveMessage();
+ }, 1000 * 60 // every minute
+ );
+ }
+
+ onScroll(): void {
+ if (this.chatPostArea.nativeElement.scrollTop === 0) {
+ this.apiService.getChatHistory(this.userToken, this.messageOffset, this.messageLimit).subscribe(
+ (response) => {
+ this.messages = response.concat(this.messages);
+ this.messageOffset += this.messageLimit;
+ this.hasBeenReloaded = true;
+ }
+ );
+ }
+ }
+
+ onTextInput(event: Event): void {
+ if (!(event instanceof KeyboardEvent)) {
+ return;
+ }
+
+ switch (event.key) {
+ case 'Enter':
+ event.preventDefault();
+
+ if (this.chatText.trim() === '') {
+ return;
+ }
+
+ this.websocketService.sendChatMessage(this.chatText);
+ this.chatText = '';
+
+ return;
+
+ default:
+ return;
+ }
+ }
+
+ onChatMessage(message: ChatMessage): void {
+ this.messages.push(message);
+ this.messageOffset++;
+
+ if (message.userId === this.userId) {
+ return;
+ }
+
+ this.triggerNotification(message);
+ }
+
+ triggerNotification(message: ChatMessage): void
+ {
+ this.localNotifications.schedule(
+ {
+ title: message.username,
+ text: message.message,
+ id: 1,
+ priority: 2,
+ lockscreen: true,
+ autoClear: true,
+ icon: Host.URL + '/user/' + message.userId + '/avatar?token=' + this.userToken,
+ smallIcon: 'ic_stat_notification_icon_enabled',
+ led: {color: '#ff00ff', on: 500, off: 500},
+ trigger: { at: new Date(new Date().getTime() + 1000) },
+ sound: 'file://assets/audio/murloc.wav',
+ vibrate: true
+ }
+ );
+ }
+}
diff --git a/src/app/host.ts b/src/app/host.ts
new file mode 100644
index 0000000..e0bb978
--- /dev/null
+++ b/src/app/host.ts
@@ -0,0 +1,5 @@
+export class Host
+{
+ public static readonly URL: string = 'https://sabolli.de/wow/api/v1';
+ public static readonly WEBSOCKET: string = 'wss://sabolli.de/metasocket';
+}
diff --git a/src/app/login/login.component.html b/src/app/login/login.component.html
new file mode 100644
index 0000000..9b2927b
--- /dev/null
+++ b/src/app/login/login.component.html
@@ -0,0 +1,20 @@
+
diff --git a/src/app/login/login.component.scss b/src/app/login/login.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/login/login.component.spec.ts b/src/app/login/login.component.spec.ts
new file mode 100644
index 0000000..b9cb059
--- /dev/null
+++ b/src/app/login/login.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { IonicModule } from '@ionic/angular';
+
+import { LoginComponent } from './login.component';
+
+describe('LoginComponent', () => {
+ let component: LoginComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ LoginComponent ],
+ imports: [IonicModule.forRoot()]
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(LoginComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ }));
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts
new file mode 100644
index 0000000..fdb818e
--- /dev/null
+++ b/src/app/login/login.component.ts
@@ -0,0 +1,71 @@
+import { Component, OnInit } from '@angular/core';
+import { ApiService } from '../api.service';
+
+@Component({
+ selector: 'app-login',
+ templateUrl: './login.component.html',
+ styleUrls: ['./login.component.scss']
+})
+export class LoginComponent implements OnInit {
+ username = '';
+ password = '';
+ error: string = null;
+
+ constructor(private apiService: ApiService) { }
+
+ ngOnInit(): void {}
+
+ login(event): void
+ {
+ event.target.disabled = true;
+ event.target.style.visibility = 'hidden';
+
+ this.apiService.getAuthToken(this.username, this.password).toPromise()
+ .then(
+ (response) => {
+ this.apiService.storeData('token', response.token);
+
+ this.apiService.getChatToken(response.token).toPromise()
+ .then(
+ (chatTokenResponse) => {
+ this.apiService.storeData('chatToken', chatTokenResponse.token);
+ this.apiService.storeData('userId', chatTokenResponse.userId.toString());
+
+ window.location.reload();
+ }
+ ).catch(
+ (error) => {
+ this.apiService.storeData('token', null);
+ this.error = error.name + ': ' + error.message;
+
+ event.target.disabled = false;
+ event.target.style.visibility = 'visible';
+ }
+ );
+ }
+ ).catch (
+ (error) => {
+ this.apiService.storeData('token', null);
+
+ switch (error.status) {
+ case 401:
+ this.error = 'Login fehlgeschlagen: Die Zugangsdaten sind falsch!';
+ break;
+
+ case 0:
+ this.error = 'Verbindungsfehler: Konnte keine Verbindung zum Server herstellen!';
+ break;
+
+ default:
+ this.error = 'Fehler: Etwas unfassbar schlimmes ist passiert!';
+ break;
+ }
+
+ console.log(error);
+
+ event.target.disabled = false;
+ event.target.style.visibility = 'visible';
+ }
+ );
+ }
+}
diff --git a/src/app/socket.keepalive.message.ts b/src/app/socket.keepalive.message.ts
new file mode 100644
index 0000000..b7545a1
--- /dev/null
+++ b/src/app/socket.keepalive.message.ts
@@ -0,0 +1,4 @@
+export interface SocketKeepaliveMessage
+{
+ type: number;
+}
diff --git a/src/app/socket.received.message.ts b/src/app/socket.received.message.ts
new file mode 100644
index 0000000..a33bc81
--- /dev/null
+++ b/src/app/socket.received.message.ts
@@ -0,0 +1,6 @@
+export interface SocketReceivedMessage {
+ type: number;
+ userId: number;
+ message: string;
+ datetime: string;
+}
diff --git a/src/app/socket.registration.message.ts b/src/app/socket.registration.message.ts
new file mode 100644
index 0000000..11a7ea8
--- /dev/null
+++ b/src/app/socket.registration.message.ts
@@ -0,0 +1,5 @@
+export interface SocketRegistrationMessage {
+ type: number;
+ token: string;
+}
+
diff --git a/src/app/socket.send.message.ts b/src/app/socket.send.message.ts
new file mode 100644
index 0000000..cbe6572
--- /dev/null
+++ b/src/app/socket.send.message.ts
@@ -0,0 +1,4 @@
+export interface SocketSendMessage {
+ type: number;
+ message: string;
+}
diff --git a/src/app/token.ts b/src/app/token.ts
new file mode 100644
index 0000000..8b6cc8e
--- /dev/null
+++ b/src/app/token.ts
@@ -0,0 +1,3 @@
+export interface Token {
+ token: string;
+}
\ No newline at end of file
diff --git a/src/app/topbar/topbar.component.html b/src/app/topbar/topbar.component.html
new file mode 100644
index 0000000..c4a8244
--- /dev/null
+++ b/src/app/topbar/topbar.component.html
@@ -0,0 +1,4 @@
+
+

+
+
diff --git a/src/app/topbar/topbar.component.scss b/src/app/topbar/topbar.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/topbar/topbar.component.spec.ts b/src/app/topbar/topbar.component.spec.ts
new file mode 100644
index 0000000..deb90d0
--- /dev/null
+++ b/src/app/topbar/topbar.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { IonicModule } from '@ionic/angular';
+
+import { TopbarComponent } from './topbar.component';
+
+describe('TopbarComponent', () => {
+ let component: TopbarComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [ TopbarComponent ],
+ imports: [IonicModule.forRoot()]
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(TopbarComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ }));
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/topbar/topbar.component.ts b/src/app/topbar/topbar.component.ts
new file mode 100644
index 0000000..35173b5
--- /dev/null
+++ b/src/app/topbar/topbar.component.ts
@@ -0,0 +1,31 @@
+import {Component, Input, OnInit} from '@angular/core';
+import {ApiService} from '../api.service';
+import {AppComponent} from '../app.component';
+import {ForegroundService} from '@ionic-native/foreground-service/ngx';
+
+@Component({
+ selector: 'app-topbar',
+ templateUrl: './topbar.component.html',
+ styleUrls: ['./topbar.component.scss']
+})
+export class TopbarComponent implements OnInit {
+ @Input() token: string;
+
+ constructor(private apiService: ApiService, private foregroundService: ForegroundService) {
+ }
+
+ ngOnInit(): void {
+ }
+
+ logout(): void {
+ this.apiService.deleteAuthToken(this.apiService.getFromStorage('token')).toPromise()
+ .then()
+ .catch(
+ (error) => {console.log(error); }
+ );
+ this.apiService.storeData('token', null);
+ this.foregroundService.stop();
+
+ AppComponent.token = null;
+ }
+}
diff --git a/src/app/websocket.listener.ts b/src/app/websocket.listener.ts
new file mode 100644
index 0000000..f318a2b
--- /dev/null
+++ b/src/app/websocket.listener.ts
@@ -0,0 +1,6 @@
+import {ChatMessage} from './chat.message';
+
+export interface WebsocketListener
+{
+ onChatMessage(message: ChatMessage): void;
+}
diff --git a/src/app/websocket.service.ts b/src/app/websocket.service.ts
new file mode 100644
index 0000000..927ea46
--- /dev/null
+++ b/src/app/websocket.service.ts
@@ -0,0 +1,104 @@
+import {Injectable} from '@angular/core';
+import {Host} from './host';
+import {ChatMessage} from './chat.message';
+import {SocketRegistrationMessage} from './socket.registration.message';
+import {SocketReceivedMessage} from './socket.received.message';
+import {WebsocketListener} from './websocket.listener';
+import {SocketSendMessage} from './socket.send.message';
+import {SocketKeepaliveMessage} from './socket.keepalive.message';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class WebsocketService {
+ private socket: WebSocket = new WebSocket(Host.WEBSOCKET);
+ private userList: Map = new Map();
+ private listener: WebsocketListener;
+ private chatToken: string;
+
+ initializeSocket(chatToken: string): void {
+ this.chatToken = chatToken;
+
+ this.socket = new WebSocket(Host.WEBSOCKET);
+ this.socket.addEventListener('open', () => {
+ this.authorize();
+ });
+ this.socket.addEventListener('message', (transmission: MessageEvent) => {
+ this.handleIncomingTransmission(transmission);
+ });
+ this.socket.addEventListener(
+ 'close',
+ () => {
+ this.initializeSocket(this.chatToken);
+ this.authorize();
+ }
+ );
+ }
+
+ setListener(listener: WebsocketListener): void {
+ this.listener = listener;
+ }
+
+ sendChatMessage(message: string): void {
+ const socketMessage: SocketSendMessage = {
+ type: Response.CHAT_MESSAGE,
+ message
+ };
+ this.socket.send(JSON.stringify(socketMessage));
+ }
+
+ sendKeepAliveMessage(): void {
+ const socketMessage: SocketKeepaliveMessage = {
+ type: Response.KEEP_ALIVE
+ };
+
+ this.socket.send(JSON.stringify(socketMessage));
+ }
+
+ private authorize(): void {
+ const message: SocketRegistrationMessage = {type: Response.REGISTRATION_MESSAGE, token: this.chatToken};
+ this.socket.send(JSON.stringify(message));
+ }
+
+ private handleIncomingTransmission(transmission: MessageEvent): void {
+ const response = JSON.parse(transmission.data);
+
+ switch (response.type) {
+ case Response.CHAT_MESSAGE:
+ const messageReceived: SocketReceivedMessage = response;
+
+ const message: ChatMessage = {
+ userId: messageReceived.userId,
+ username: this.userList.get(messageReceived.userId),
+ datetime: messageReceived.datetime,
+ message: messageReceived.message
+ };
+
+ this.listener.onChatMessage(message);
+
+ break;
+
+ case Response.REGISTRATION_MESSAGE:
+ this.userList.set(response.userId, response.username);
+ break;
+
+ case Response.USERLIST:
+ response.users.forEach(
+ (user) => {
+ this.userList.set(user.userId, user.username);
+ }
+ );
+ break;
+
+ default:
+ throw new Error('Unknown message type: ' + response.type);
+ }
+ }
+}
+
+enum Response {
+ CHAT_MESSAGE = 1,
+ REGISTRATION_MESSAGE,
+ USERLIST,
+ KEEP_ALIVE
+}
diff --git a/src/assets/.gitkeep b/src/assets/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/src/assets/audio/murloc.ogg b/src/assets/audio/murloc.ogg
new file mode 100644
index 0000000..3c07d60
Binary files /dev/null and b/src/assets/audio/murloc.ogg differ
diff --git a/src/assets/audio/murloc.wav b/src/assets/audio/murloc.wav
new file mode 100644
index 0000000..bfc2395
Binary files /dev/null and b/src/assets/audio/murloc.wav differ
diff --git a/src/assets/graphics/bg_responsive.jpg b/src/assets/graphics/bg_responsive.jpg
new file mode 100644
index 0000000..51d9314
Binary files /dev/null and b/src/assets/graphics/bg_responsive.jpg differ
diff --git a/src/assets/graphics/metasocket-banner.svg b/src/assets/graphics/metasocket-banner.svg
new file mode 100644
index 0000000..ec9682f
--- /dev/null
+++ b/src/assets/graphics/metasocket-banner.svg
@@ -0,0 +1,83 @@
+
+
diff --git a/src/assets/graphics/metasocket-icon.svg b/src/assets/graphics/metasocket-icon.svg
new file mode 100644
index 0000000..721f05d
--- /dev/null
+++ b/src/assets/graphics/metasocket-icon.svg
@@ -0,0 +1,61 @@
+
+
diff --git a/src/assets/icon/favicon.png b/src/assets/icon/favicon.png
index 51888a7..fdc08a8 100644
Binary files a/src/assets/icon/favicon.png and b/src/assets/icon/favicon.png differ
diff --git a/src/global.scss b/src/global.scss
index d854de8..3116d92 100644
--- a/src/global.scss
+++ b/src/global.scss
@@ -1,26 +1,175 @@
-/*
- * App Global CSS
- * ----------------------------------------------------------------------------
- * Put style rules here that you want to apply globally. These styles are for
- * the entire app and not just one component. Additionally, this file can be
- * used as an entry point to import other CSS/Sass files to be included in the
- * output CSS.
- * For more information on global stylesheets, visit the documentation:
- * https://ionicframework.com/docs/layout/global-stylesheets
- */
+* {
+ box-sizing: border-box;
+ font-family: sans-serif;
+ outline: none;
+}
-/* Core CSS required for Ionic components to work properly */
-@import "~@ionic/angular/css/core.css";
+#chat {
+ background: rgb(27, 47, 114) url("assets/graphics/bg_responsive.jpg") repeat;
+ margin: 0;
+ font-size: 16px;
+ font-family: sans-serif;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ color: white;
+}
-/* Basic CSS for apps built with Ionic */
-@import "~@ionic/angular/css/normalize.css";
-@import "~@ionic/angular/css/structure.css";
-@import "~@ionic/angular/css/typography.css";
-@import '~@ionic/angular/css/display.css';
+#chat-post-area {
+ position: fixed;
+ top: 40px;
+ left: 0;
+ right: 0;
+ bottom: 50px;
+ overflow-x: hidden;
+ box-sizing: border-box;
+ padding-bottom: 20px;
+}
+
+#chat-type-area {
+ position: fixed;
+ height: 50px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.9);
+}
+
+#chat-textarea {
+ width: 100%;
+ height: 100%;
+ background-color: #333333;
+ font-family: sans-serif;
+ font-size: 16px;
+ color: white;
+ border: 2px grey solid;
+ box-sizing: border-box;
+ padding: 5px;
+ resize: none;
+ outline: none;
+}
+
+.chat-post {
+ background-color: rgba(37, 26, 37, 0.9);
+ border-radius: 0 20px 20px 0;
+ margin-right: 20px;
+ margin-left: 0;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 20px;
+ overflow: hidden;
+}
+
+.chat-own-post {
+ border-radius: 20px 0 0 20px;
+ margin-left: 20px;
+ margin-right: 0;
+ padding: 20px 0 20px 20px;
+ background-color: rgba(26, 37, 26, 0.9);
+}
+
+.chat-avatar {
+ width: 64px;
+ height: 64px;
+ border-radius: 32px;
+ margin-right: 20px;
+ float: left;
+}
+
+.chat-own-post > .chat-avatar {
+ margin-left: 20px;
+ float: right;
+}
+
+.chat-username {
+ font-weight: bold;
+}
+
+.chat-post-message {
+ margin-top: 10px;
+ overflow: hidden;
+}
+
+.chat-datetime {
+ font-style: italic;
+ color: grey;
+ margin-top: 10px;
+}
+
+#login {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgb(37, 26, 37);
+ display: flex;
+ align-items: center;
+}
+
+#login-form {
+ max-width: 500px;
+ margin: auto;
+ text-align: center;
+ padding: 20px;
+}
+
+#login-form label {
+ display: block;
+ color: white;
+ font-weight: bold;
+ margin-bottom: 20px;
+}
+
+#login-form input {
+ display: block;
+ background-color: transparent;
+ border: solid 1px white;
+ color: white;
+ border-radius: 5px;
+ font-size: 18px;
+ width: 100%;
+ padding: 5px;
+}
+
+#login-form input[type=submit] {
+ margin-top: 50px;
+}
+
+.error-message {
+ background-color: #550000;
+ border: solid 1px red;
+ color: white;
+ padding: 5px;
+ margin-bottom: 30px;
+}
+
+#metasocket-banner {
+ width: 100%;
+ margin-bottom: 50px;
+}
+
+#metasocket-logo {
+ height: 100%;
+}
+
+#topbar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 40px;
+ background-color: #888888;
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.9);
+ padding: 5px;
+ display: inline-flex;
+ justify-content: space-between;
+}
+
+#logout-button {
+ width: 70px;
+ text-align: center;
+}
-/* Optional CSS utils that can be commented out */
-@import "~@ionic/angular/css/padding.css";
-@import "~@ionic/angular/css/float-elements.css";
-@import "~@ionic/angular/css/text-alignment.css";
-@import "~@ionic/angular/css/text-transformation.css";
-@import "~@ionic/angular/css/flex-utils.css";