summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Pušnik <marko.pusnik@guru.si>2015-10-05 15:57:43 +0200
committerMarko Pušnik <marko.pusnik@guru.si>2015-10-05 15:57:43 +0200
commit16e584cc8dc057290e14f829b507fbbef3cdf60f (patch)
tree2f6c0aa706f7d38425f69dd50f491b4492ba1a01
parent28e59b13a7c348570ee15663dc5153c5c8012794 (diff)
handle phonegap native mobile app
-rw-r--r--config.xml177
-rw-r--r--cordova.js3
-rw-r--r--index.html6
-rw-r--r--js/codeq/comms.js4
-rw-r--r--js/codeq/core.js84
-rw-r--r--js/codeq/init.js100
6 files changed, 236 insertions, 138 deletions
diff --git a/config.xml b/config.xml
index a22f584..2664448 100644
--- a/config.xml
+++ b/config.xml
@@ -3,8 +3,8 @@
<!-- config.xml reference: https://build.phonegap.com/docs/config-xml -->
<widget xmlns = "http://www.w3.org/ns/widgets"
xmlns:gap = "http://phonegap.com/ns/1.0"
- id = "si.uni-lj.fri.codeq"
- version = "0.0.1">
+ id = "si.uni-lj.fri.gameteam.codeq"
+ version = "0.1.0">
<!--
1.0 first release
@@ -13,10 +13,10 @@
<name>Code Q</name>
<description>
- Code Q.
+ CodeQ je e-storitev in mobilna aplikacija za učenje programiranja. Aplikacija omogoča uporabniku samostojno učenje programiranja prek reševanja skrbno pripravljenih programerskih nalog s pomočjo samodejno generiranih namigov in avtomatskih testnih primerov.
</description>
- <author href="http://www.codeq.net" email="info@codeq.net">
+ <author href="http://www.codeq.net" email="info@codeq.si">
Univerza v Ljubljani, Fakulteta za računalništvo in informatiko, A.I.LAB Ljubljana.
</author>
@@ -39,34 +39,49 @@
<preference name="exit-on-suspend" value="false" /> <!-- ios: if set to true, app will terminate when home button is pressed -->
<preference name="show-splash-screen-spinner" value="true" /> <!-- ios: if set to false, the spinner won't appear on the splash screen during app loading -->
<preference name="auto-hide-splash-screen" value="true" /> <!-- ios: if set to false, the splash screen must be hidden using a JavaScript API -->
- <preference name="disable-cursor" value="false" /> <!-- blackberry: prevents a mouse-icon/cursor from being displayed on the app -->
+ <preference name="deployment-target" value="5.0" /> <!-- ios:-->
<preference name="android-installLocation" value="auto" /> <!-- android: app install location. 'auto' will choose. 'internalOnly' is device memory. 'preferExternal' is SDCard. -->
+ <preference name="android-minSdkVersion" value="10" /> <!-- android:-->
<!--
Define a specific version of PhoneGap to build into your app.
<preference name="phonegap-version" value="3.5.0" />
-->
+ <preference name="phonegap-version" value="cli-5.2.0" />
- <!-- Plugins -->
+ <!-- Feature -->
+ <!--
+ <feature name="http://api.phonegap.com/1.0/network" />
+ <feature name="http://api.phonegap.com/1.0/camera" />
+ <feature name="http://api.phonegap.com/1.0/notification" />
+ <feature name="http://api.phonegap.com/1.0/geolocation" />
+ <feature name="http://api.phonegap.com/1.0/media" />
+ <feature name="http://api.phonegap.com/1.0/contacts" />
+ <feature name="http://api.phonegap.com/1.0/file" />
+ <feature name="http://api.phonegap.com/1.0/battery" />
+ <feature name="http://api.phonegap.com/1.0/device" />
+ -->
- <!-- Core plugins -->
- <gap:plugin name="org.apache.cordova.battery-status" />
- <gap:plugin name="org.apache.cordova.camera" />
- <gap:plugin name="org.apache.cordova.media-capture" />
- <gap:plugin name="org.apache.cordova.console" />
- <gap:plugin name="org.apache.cordova.contacts" />
- <gap:plugin name="org.apache.cordova.device" />
- <gap:plugin name="org.apache.cordova.device-motion" />
- <gap:plugin name="org.apache.cordova.device-orientation" />
- <gap:plugin name="org.apache.cordova.dialogs" />
- <gap:plugin name="org.apache.cordova.file" />
- <gap:plugin name="org.apache.cordova.file-transfer" />
- <gap:plugin name="org.apache.cordova.geolocation" />
- <gap:plugin name="org.apache.cordova.globalization" />
- <gap:plugin name="org.apache.cordova.inappbrowser" />
- <gap:plugin name="org.apache.cordova.media" />
- <gap:plugin name="org.apache.cordova.network-information" />
- <gap:plugin name="org.apache.cordova.splashscreen" />
- <gap:plugin name="org.apache.cordova.vibration" />
+ <!-- Plugins -->
+ <!--
+ <gap:plugin name="org.apache.cordova.battery-status" version="0.2.11" />
+ <gap:plugin name="org.apache.cordova.camera" version="0.3.2" />
+ <gap:plugin name="org.apache.cordova.console" version="0.2.11" />
+ <gap:plugin name="org.apache.cordova.contacts" version="0.2.13" />
+ <gap:plugin name="org.apache.cordova.device" version="0.2.12" />
+ <gap:plugin name="org.apache.cordova.device-motion" version="0.2.10" />
+ <gap:plugin name="org.apache.cordova.device-orientation" version="0.3.9" />
+ <gap:plugin name="org.apache.cordova.dialogs" version="0.2.10" />
+ <gap:plugin name="org.apache.cordova.file" version="1.3.1" />
+ <gap:plugin name="org.apache.cordova.file-transfer" version="0.4.6" />
+ <gap:plugin name="org.apache.cordova.geolocation" version="0.3.10" />
+ <gap:plugin name="org.apache.cordova.globalization" version="0.3.1" />
+ <gap:plugin name="org.apache.cordova.inappbrowser" version="0.5.2" />
+ <gap:plugin name="org.apache.cordova.media" version="0.2.13" />
+ <gap:plugin name="org.apache.cordova.media-capture" version="0.3.3" />
+ <gap:plugin name="org.apache.cordova.network-information" version="0.2.12" />
+ <gap:plugin name="org.apache.cordova.splashscreen" version="0.3.4" />
+ <gap:plugin name="org.apache.cordova.vibration" version="0.3.11" />
+ -->
<!-- Third party plugins -->
<!-- A list of available plugins are available at https://build.phonegap.com/plugins -->
@@ -76,32 +91,90 @@
<!-- Define app icon for each platform. -->
<icon src="icon.png" />
- <icon src="res/icon/android/icon-36-ldpi.png" gap:platform="android" gap:qualifier="ldpi" />
- <icon src="res/icon/android/icon-48-mdpi.png" gap:platform="android" gap:qualifier="mdpi" />
- <icon src="res/icon/android/icon-72-hdpi.png" gap:platform="android" gap:qualifier="hdpi" />
- <icon src="res/icon/android/icon-96-xhdpi.png" gap:platform="android" gap:qualifier="xhdpi" />
- <icon src="res/icon/blackberry/icon-80.png" gap:platform="blackberry" />
- <icon src="res/icon/blackberry/icon-80.png" gap:platform="blackberry" gap:state="hover"/>
- <icon src="res/icon/ios/icon-57.png" gap:platform="ios" width="57" height="57" />
- <icon src="res/icon/ios/icon-72.png" gap:platform="ios" width="72" height="72" />
- <icon src="res/icon/ios/icon-57-2x.png" gap:platform="ios" width="114" height="114" />
- <icon src="res/icon/ios/icon-72-2x.png" gap:platform="ios" width="144" height="144" />
- <icon src="res/icon/webos/icon-64.png" gap:platform="webos" />
- <icon src="res/icon/windows-phone/icon-48.png" gap:platform="winphone" />
- <icon src="res/icon/windows-phone/icon-173.png" gap:platform="winphone" gap:role="background" />
+
+ <!-- iOS -->
+ <!-- iPhone 6 / 6+ -->
+ <icon src="icon-60@3x.png" gap:platform="ios" width="180" height="180" />
+
+ <!-- iPhone / iPod Touch -->
+ <icon src="icon-60.png" gap:platform="ios" width="60" height="60" />
+ <icon src="icon-60@2x.png" gap:platform="ios" width="120" height="120" />
+
+ <!-- iPad -->
+ <icon src="icon-76.png" gap:platform="ios" width="76" height="76" />
+ <icon src="icon-76@2x.png" gap:platform="ios" width="152" height="152" />
+
+ <!-- Settings Icon -->
+ <icon src="icon-small.png" gap:platform="ios" width="29" height="29" />
+ <icon src="icon-small@2x.png" gap:platform="ios" width="58" height="58" />
+
+ <!-- Spotlight Icon -->
+ <icon src="icon-40.png" gap:platform="ios" width="40" height="40" />
+ <icon src="icon-40@2x.png" gap:platform="ios" width="80" height="80" />
+
+ <!-- iPhone / iPod Touch -->
+ <icon src="icon.png" gap:platform="ios" width="57" height="57" />
+ <icon src="icon@2x.png" gap:platform="ios" width="114" height="114" />
+
+ <!-- iPad -->
+ <icon src="icon-72.png" gap:platform="ios" width="72" height="72" />
+ <icon src="icon-72@2x.png" gap:platform="ios" width="144" height="144" />
+
+ <!-- iPhone Spotlight and Settings Icon -->
+ <icon src="icon-small.png" gap:platform="ios" width="29" height="29" />
+ <icon src="icon-small@2x.png" gap:platform="ios" width="58" height="58" />
+
+ <!-- iPad Spotlight and Settings Icon -->
+ <icon src="icon-50.png" gap:platform="ios" width="50" height="50" />
+ <icon src="icon-50@2x.png" gap:platform="ios" width="100" height="100" />
+
+ <!-- Android -->
+ <icon src="ldpi.png" gap:platform="android" gap:qualifier="ldpi" />
+ <icon src="mdpi.png" gap:platform="android" gap:qualifier="mdpi" />
+ <icon src="hdpi.png" gap:platform="android" gap:qualifier="hdpi" />
+ <icon src="xhdpi.png" gap:platform="android" gap:qualifier="xhdpi" />
+ <icon src="xxhdpi.png" gap:platform="android" gap:qualifier="xxhdpi" />
+ <icon src="fr-xxhdpi.png" gap:platform="android" gap:qualifier="fr-xxhdpi" />
+
+ <!-- Windows Phone -->
+ <icon src="icon.png" gap:platform="winphone" />
+ <icon src="tileicon.png" gap:platform="winphone" gap:role="background" />
<!-- Define app splash screen for each platform. -->
- <gap:splash src="res/screen/android/screen-ldpi-portrait.png" gap:platform="android" gap:qualifier="port-ldpi" />
- <gap:splash src="res/screen/android/screen-mdpi-portrait.png" gap:platform="android" gap:qualifier="port-mdpi" />
- <gap:splash src="res/screen/android/screen-hdpi-portrait.png" gap:platform="android" gap:qualifier="port-hdpi" />
- <gap:splash src="res/screen/android/screen-xhdpi-portrait.png" gap:platform="android" gap:qualifier="port-xhdpi" />
- <gap:splash src="res/screen/blackberry/screen-225.png" gap:platform="blackberry" />
- <gap:splash src="res/screen/ios/screen-iphone-portrait.png" gap:platform="ios" width="320" height="480" />
- <gap:splash src="res/screen/ios/screen-iphone-portrait-2x.png" gap:platform="ios" width="640" height="960" />
- <gap:splash src="res/screen/ios/screen-iphone-portrait-568h-2x.png" gap:platform="ios" width="640" height="1136" />
- <gap:splash src="res/screen/ios/screen-ipad-portrait.png" gap:platform="ios" width="768" height="1024" />
- <gap:splash src="res/screen/ios/screen-ipad-landscape.png" gap:platform="ios" width="1024" height="768" />
- <gap:splash src="res/screen/windows-phone/screen-portrait.jpg" gap:platform="winphone" />
+ <gap:splash src="splash.png" />
+
+ <!-- iOS -->
+ <!-- iPhone and iPod touch -->
+ <gap:splash src="Default.png" gap:platform="ios" width="320" height="480" />
+ <gap:splash src="Default@2x.png" gap:platform="ios" width="640" height="960" />
+
+ <!-- iPhone 5 / iPod Touch (5th Generation) -->
+ <gap:splash src="Default-568h@2x.png" gap:platform="ios" width="640" height="1136" />
+
+ <!-- iPhone 6 -->
+ <gap:splash src="Default-667h@2x.png" gap:platform="ios" width="750" height="1334" />
+ <gap:splash src="Default-Portrait-736h@3x.png" gap:platform="ios" width="1242" height="2208" />
+ <gap:splash src="Default-Landscape-736h@3x.png" gap:platform="ios" width="2208" height="1242" />
+
+ <!-- iPad -->
+ <gap:splash src="Default-Portrait.png" gap:platform="ios" width="768" height="1024" />
+ <gap:splash src="Default-Landscape.png" gap:platform="ios" width="1024" height="768" />
+
+ <!-- Retina iPad -->
+ <gap:splash src="Default-Portrait@2x.png" gap:platform="ios" width="1536" height="2048" />
+ <gap:splash src="Default-Landscape@2x.png" gap:platform="ios" width="2048" height="1536" />
+
+ <!-- Android -->
+ <gap:splash src="ldpi.png" gap:platform="android" gap:qualifier="ldpi" />
+ <gap:splash src="mdpi.png" gap:platform="android" gap:qualifier="mdpi" />
+ <gap:splash src="hdpi.png" gap:platform="android" gap:qualifier="hdpi" />
+ <gap:splash src="xhdpi.png" gap:platform="android" gap:qualifier="xhdpi" />
+ <gap:splash src="fr-xhdpi.png" gap:platform="android" gap:qualifier="fr-xhdpi" />
+ <gap:splash src="portrait-xxhdpi.png" gap:platform="android" gap:qualifier="port-xxhdpi" />
+ <gap:splash src="landscape-xxhdpi.png" gap:platform="android" gap:qualifier="land-xxhdpi" />
+
+ <!-- Windows Phone -->
+ <gap:splash src="splash/winphone/splash.jpg" gap:platform="winphone" />
<gap:config-file platform="ios" parent="CFBundleShortVersionString">
<string>100</string>
@@ -121,9 +194,11 @@
-->
<access origin="*"/>
- <!-- Added the following intents to support the removal of whitelist code from base cordova to a plugin -->
- <!-- Whitelist configuration. Refer to https://cordova.apache.org/docs/en/edge/guide_appdev_whitelist_index.md.html -->
+
+ <!-- Whitelist configuration. Refer to https://github.com/apache/cordova-plugin-whitelist -->
<plugin name="cordova-plugin-whitelist" version="1" />
+ <!-- Intent Whitelist -->
+ <!-- Controls which URLs the app is allowed to ask the system to open. By default, no external URLs are allowed. -->
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
diff --git a/cordova.js b/cordova.js
new file mode 100644
index 0000000..1aa58fd
--- /dev/null
+++ b/cordova.js
@@ -0,0 +1,3 @@
+// differentiates between a native Phonegap/Cordova app, and a web app
+// a Phonegap/Cordova build injects a native version of this file
+codeq.isWebApp = true; \ No newline at end of file
diff --git a/index.html b/index.html
index 6918bfa..bbba5f5 100644
--- a/index.html
+++ b/index.html
@@ -468,8 +468,6 @@
<script src="js/q.js"></script>
<!-- Bootstrap -->
<script src="js/bootstrap/bootstrap.min.js"></script>
- <!-- Cordova/PhoneGap -->
- <script type="text/javascript" src="cordova.js"></script>
<!-- CodeMirror stuff -->
<script src="js/codemirror/codemirror.js"></script>
<script src="js/codemirror/matchbrackets.js"></script>
@@ -478,6 +476,10 @@
<script src="js/codemirror/show-hint.js"></script>
<!-- codeq app -->
<script src="js/codeq/core.js"></script>
+ <!-- Cordova/PhoneGap -->
+ <script type="text/javascript" src="cordova.js"></script>
+ <!-- codeq app cont. -->
+ <script src="js/codeq/init.js"></script>
<script src="js/codeq/translation.js"></script>
<script src="js/codeq/statusbar.js"></script>
<script src="js/codeq/navigation.js"></script>
diff --git a/js/codeq/comms.js b/js/codeq/comms.js
index ad2376e..3671e95 100644
--- a/js/codeq/comms.js
+++ b/js/codeq/comms.js
@@ -198,7 +198,7 @@
},
ajaxPrefix, ajaxDataPrefix, ajaxResPrefix;
- ajaxPrefix = location.pathname;
+ ajaxPrefix = codeq.ajaxPrefix;
if (!ajaxPrefix) ajaxPrefix = '/';
else if (ajaxPrefix[ajaxPrefix.length - 1] !== '/') {
ajaxPrefix = ajaxPrefix.split('/');
@@ -233,7 +233,7 @@
else {
// create a new connection
connectPromise = deferred;
- socket = eio('ws://' + location.host, {
+ socket = eio(codeq.eioHost, {
'upgrade': true,
'path': '/ws',
'transports': ['polling', 'websocket']
diff --git a/js/codeq/core.js b/js/codeq/core.js
index 2d88f18..02bc2f0 100644
--- a/js/codeq/core.js
+++ b/js/codeq/core.js
@@ -393,6 +393,7 @@
'en': 'English',
'sl': 'Slovenščina'
},
+ 'isWebApp': false, // this is a PhoneGap/Cordova build, will be overridden in cordova.js for webapp
'getLang': function () {
return lang;
},
@@ -570,87 +571,4 @@
}
}
};
-
- var loadGuiTranslations = function () {
- var langs = codeq.availableLangs,
- loaders = [],
- loaderLangs = [],
- i, lang;
- for (i = langs.length - 1; i >= 0; i--) {
- lang = langs[i];
- loaders.push(codeq.comms.getGuiTranslation(lang));
- loaderLangs.push(lang);
- }
- return Q.all(loaders)
- .then(function (results) {
- // convert translations into something that the translation module can use
- var dictionary = {},
- i, json, key, lang, translations;
- for (i = results.length - 1; i >= 0; i--) {
- json = results[i];
- lang = loaderLangs[i];
- for (key in json) {
- if (!json.hasOwnProperty(key)) continue;
- translations = dictionary[key];
- if (translations) translations[lang] = json[key];
- else {
- translations = {};
- dictionary[key] = translations;
- translations[lang] = json[key];
- }
- }
- }
- // ensure each key contains all translations
- for (key in dictionary) {
- if (!dictionary.hasOwnProperty(key)) continue;
- translations = dictionary[key];
- for (i = langs.length - 1; i >= 0; i--) {
- lang = langs[i];
- if (!(lang in translations)) translations[lang] = "(Untranslated: " + lang + ")";
- }
- }
- // register with the system
- codeq.tr.registerDictionary('gui', dictionary);
- });
- };
-
- // ================================================================================
- // The boot sequence
- // ================================================================================
-
- $(document).ready(function () {
- // set the language
- var navigatorLang = navigator.language || navigator.browserLanguage, // language reported by browser
- lang = null, // the translation language that will be chosen
- key;
- if (typeof navigatorLang === 'string') {
- navigatorLang = navigatorLang.split('-')[0]; // truncate the language variant, in eg. en-US
- }
- else navigatorLang = 'en';
- for (key in codeq.supportedLangs) {
- if (!codeq.supportedLangs.hasOwnProperty(key)) continue;
- if (key === navigatorLang) lang = key; // we support the browser's language
- codeq.availableLangs.push(key);
- }
-
- // the boot chain of async handlers: must be a sequence of .then() terminated with a .fail().done()
- loadGuiTranslations()
- .then(codeq.comms.getResourceTree)
- .then(function (resourceTree) {
- resources = resourceTree; // save the loaded resource tree to the internal variable
-
- codeq.fire('init'); // tell any interested modules that we are now initialized, perhaps they want to initialize too
- codeq.setLang(lang || 'en'); // initial language setting, this also translates the GUI
- // go to login
- codeq.globalStateMachine.transition('login');
-
- //For performance reasons, the Tooltip and Popover data-apis are opt-in, meaning you must initialize them yourself.
- $('[data-toggle="popover"]').popover()
- })
- .fail(function (e) {
- codeq.log.error('CodeQ failed to start: ' + e, e);
- alert('CodeQ failed to start: ' + e);
- })
- .done();
- });
})();
diff --git a/js/codeq/init.js b/js/codeq/init.js
new file mode 100644
index 0000000..b7e903c
--- /dev/null
+++ b/js/codeq/init.js
@@ -0,0 +1,100 @@
+(function () {
+
+
+ var loadGuiTranslations = function () {
+ var langs = codeq.availableLangs,
+ loaders = [],
+ loaderLangs = [],
+ i, lang;
+ for (i = langs.length - 1; i >= 0; i--) {
+ lang = langs[i];
+ loaders.push(codeq.comms.getGuiTranslation(lang));
+ loaderLangs.push(lang);
+ }
+ return Q.all(loaders)
+ .then(function (results) {
+ // convert translations into something that the translation module can use
+ var dictionary = {},
+ i, json, key, lang, translations;
+ for (i = results.length - 1; i >= 0; i--) {
+ json = results[i];
+ lang = loaderLangs[i];
+ for (key in json) {
+ if (!json.hasOwnProperty(key)) continue;
+ translations = dictionary[key];
+ if (translations) translations[lang] = json[key];
+ else {
+ translations = {};
+ dictionary[key] = translations;
+ translations[lang] = json[key];
+ }
+ }
+ }
+ // ensure each key contains all translations
+ for (key in dictionary) {
+ if (!dictionary.hasOwnProperty(key)) continue;
+ translations = dictionary[key];
+ for (i = langs.length - 1; i >= 0; i--) {
+ lang = langs[i];
+ if (!(lang in translations)) translations[lang] = "(Untranslated: " + lang + ")";
+ }
+ }
+ // register with the system
+ codeq.tr.registerDictionary('gui', dictionary);
+ });
+ };
+
+ // ================================================================================
+ // The boot sequence
+ // ================================================================================
+
+ var Boot = function () {
+ // set the language
+ var navigatorLang = navigator.language || navigator.browserLanguage, // language reported by browser
+ lang = null, // the translation language that will be chosen
+ key;
+ if (typeof navigatorLang === 'string') {
+ navigatorLang = navigatorLang.split('-')[0]; // truncate the language variant, in eg. en-US
+ }
+ else navigatorLang = 'en';
+ for (key in codeq.supportedLangs) {
+ if (!codeq.supportedLangs.hasOwnProperty(key)) continue;
+ if (key === navigatorLang) lang = key; // we support the browser's language
+ codeq.availableLangs.push(key);
+ }
+
+ // the boot chain of async handlers: must be a sequence of .then() terminated with a .fail().done()
+ loadGuiTranslations()
+ .then(codeq.comms.getResourceTree)
+ .then(function (resourceTree) {
+ resources = resourceTree; // save the loaded resource tree to the internal variable
+
+ codeq.fire('init'); // tell any interested modules that we are now initialized, perhaps they want to initialize too
+ codeq.setLang(lang || 'en'); // initial language setting, this also translates the GUI
+ // go to login
+ codeq.globalStateMachine.transition('login');
+
+ //For performance reasons, the Tooltip and Popover data-apis are opt-in, meaning you must initialize them yourself.
+ $('[data-toggle="popover"]').popover()
+ })
+ .fail(function (e) {
+ codeq.log.error('CodeQ failed to start: ' + e, e);
+ alert('CodeQ failed to start: ' + e);
+ })
+ .done();
+ };
+
+ if (codeq.isWebApp) {
+ // we are a web app
+ $(window).on('load', Boot);
+ codeq.ajaxPrefix = location.pathname;
+ codeq.eioHost= 'ws://' + location.host;
+ }
+ else {
+ // we are a phonegap native app
+ document.addEventListener("deviceready", Boot, false);
+ codeq.ajaxPrefix = 'http://codeq.si/';
+ codeq.eioHost= 'ws://codeq.si';
+ }
+
+})();