From 028ace4143d46db4de6fe2f1f169eb9cc972e755 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Wed, 10 Mar 2010 23:13:25 +0000 Subject: [PATCH] Initial import. --- Ping.fm/LICENSE.txt | 31 + Ping.fm/app/assistants/main-assistant.js | 732 +++++++++++++++++++++ Ping.fm/app/assistants/stage-assistant.js | 8 + Ping.fm/app/helpers/base64.js | 86 +++ Ping.fm/app/views/main/key-dialog.html | 18 + Ping.fm/app/views/main/main-scene.html | 52 ++ Ping.fm/appinfo.json | 10 + Ping.fm/ect-logo.png | Bin 0 -> 13972 bytes Ping.fm/framework_config.json | 3 + Ping.fm/icon.png | Bin 0 -> 4037 bytes Ping.fm/images/mini-icon.png | Bin 0 -> 3699 bytes Ping.fm/index.html | 14 + Ping.fm/sources.json | 7 + Ping.fm/stylesheets/pingfm.css | 38 ++ images/icon48.png | Bin 0 -> 4632 bytes install.bat | 4 + make.bat | 3 + screenshots/1-pingfm_2010-10-03_083043.png | Bin 0 -> 30730 bytes screenshots/2-pingfm_2010-10-03_084737.png | Bin 0 -> 36153 bytes screenshots/3-pingfm_2010-10-03_041059.png | Bin 0 -> 58305 bytes screenshots/4-pingfm_2010-10-03_040109.png | Bin 0 -> 42657 bytes screenshots/pingfm.gif | Bin 0 -> 72711 bytes 22 files changed, 1006 insertions(+) create mode 100644 Ping.fm/LICENSE.txt create mode 100644 Ping.fm/app/assistants/main-assistant.js create mode 100644 Ping.fm/app/assistants/stage-assistant.js create mode 100644 Ping.fm/app/helpers/base64.js create mode 100644 Ping.fm/app/views/main/key-dialog.html create mode 100644 Ping.fm/app/views/main/main-scene.html create mode 100644 Ping.fm/appinfo.json create mode 100644 Ping.fm/ect-logo.png create mode 100644 Ping.fm/framework_config.json create mode 100644 Ping.fm/icon.png create mode 100644 Ping.fm/images/mini-icon.png create mode 100644 Ping.fm/index.html create mode 100644 Ping.fm/sources.json create mode 100644 Ping.fm/stylesheets/pingfm.css create mode 100644 images/icon48.png create mode 100644 install.bat create mode 100644 make.bat create mode 100644 screenshots/1-pingfm_2010-10-03_083043.png create mode 100644 screenshots/2-pingfm_2010-10-03_084737.png create mode 100644 screenshots/3-pingfm_2010-10-03_041059.png create mode 100644 screenshots/4-pingfm_2010-10-03_040109.png create mode 100644 screenshots/pingfm.gif diff --git a/Ping.fm/LICENSE.txt b/Ping.fm/LICENSE.txt new file mode 100644 index 0000000..3d5788a --- /dev/null +++ b/Ping.fm/LICENSE.txt @@ -0,0 +1,31 @@ +Software License Agreement (BSD License) + +Copyright (c) 2010, Erik C. Thauvin (http://erik.thauvin.net/) +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + Neither the name of the authors nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +$Id$ \ No newline at end of file diff --git a/Ping.fm/app/assistants/main-assistant.js b/Ping.fm/app/assistants/main-assistant.js new file mode 100644 index 0000000..4be02ee --- /dev/null +++ b/Ping.fm/app/assistants/main-assistant.js @@ -0,0 +1,732 @@ +// --------------------------------------------------------------------------- +// KeyDialogAssistant +// --------------------------------------------------------------------------- +function KeyDialogAssistant(sceneAssistant, focusField) +{ + this.sceneAssistant = sceneAssistant; + this.focusField = focusField; +} + +KeyDialogAssistant.prototype.setup = function(widget) +{ + this.widget = widget; + + this.sceneAssistant.controller.setupWidget('mobileKey', + { + hintText: 'Enter your Ping.fm mobile key...', + autoFocus: true, + limitResize: true, + autoReplace: false, + textCase: Mojo.Widget.steModeLowerCase, + focusMode: Mojo.Widget.focusAppendMode, + maxLength: 4 + }, this.mobileKeyModel = + { + value: '', + disabled: false + }); + + this.okButtonModel = + { + label: 'OK', + disabled: false + }; + + this.sceneAssistant.controller.setupWidget('okButton', + { + type: Mojo.Widget.activityButton + }, this.okButtonModel); + + this.okButton = this.sceneAssistant.controller.get('okButton'); + + this.checkKeyHandler = this.checkKey.bindAsEventListener(this); + this.sceneAssistant.controller.listen('okButton', Mojo.Event.tap, this.checkKeyHandler); + + this.handleKeyHandler = this.handleKeyEvent.bindAsEventListener(this); + this.sceneAssistant.controller.document.addEventListener('keyup', this.handleKeyHandler, true); + + this.cancelButtonModel = + { + label: 'Cancel', + disabled: false + }; + + this.sceneAssistant.controller.setupWidget('cancelButton', + { + type: Mojo.Widget.defaultButton + }, this.cancelButtonModel); + + this.sceneAssistant.controller.listen('cancelButton', Mojo.Event.tap, this.widget.mojo.close); +}; + +KeyDialogAssistant.prototype.checkKey = function() +{ + this.okButton.mojo.activate(); + this.okButtonModel.label = 'Validating Key'; + this.okButtonModel.disabled = true; + this.sceneAssistant.controller.modelChanged(this.okButtonModel); + + var params = new Hash( + { + 'api_key': this.sceneAssistant.api_key, + 'mobile_key': this.mobileKeyModel.value + }); + + Mojo.Log.info('checkKey: ' + params.toQueryString()); + + var request = new Ajax.Request('http://api.ping.fm/v1/user.key', + { + method: 'post', + parameters: params, + evalJSON: 'false', + onSuccess: this.checkKeySuccess.bind(this), + onFailure: this.checkKeyFailure.bind(this) + }); +}; + +KeyDialogAssistant.prototype.checkKeySuccess = function(transport) +{ + if (transport.responseXML === null) + { + Mojo.Controller.errorDialog("Invalid response from the Ping.fm API.", this.controller.window); + } + else + { + var rsp = transport.responseXML.getElementsByTagName('rsp'); + var status = rsp[0].getAttribute('status'); + + if (status == 'FAIL') + { + this.sceneAssistant.controller.get('keyDialogTitle').update('Invalid or Expired Key. Please Retry.'); + this.mobileKeyModel.value = ''; + this.sceneAssistant.controller.modelChanged(this.mobileKeyModel); + this.sceneAssistant.controller.get('mobileKey').mojo.focus(); + + Mojo.Log.info(transport.responseText); + + this.okButton.mojo.deactivate(); + this.okButtonModel.label = 'OK'; + this.okButtonModel.disabled = false; + this.sceneAssistant.controller.modelChanged(this.okButtonModel); + } + else + { + this.sceneAssistant.prefs.user_app_key = rsp[0].getElementsByTagName('key').item(0).textContent; + this.sceneAssistant.updateMethods(); + + this.okButton.mojo.deactivate(); + this.widget.mojo.close(); + } + } +}; + +KeyDialogAssistant.prototype.checkKeyFailure = function(transport) +{ + this.sceneAssistant.transportFailure('checkKeyFailure', transport); +}; + +KeyDialogAssistant.prototype.handleKeyEvent = function(event) +{ + if (Mojo.Char.isEnterKey(event.keyCode)) + { + if (event.srcElement.parentElement.id == 'mobileKey') + { + this.checkKey(); + } + } +}; + +KeyDialogAssistant.prototype.cleanup = function() +{ + this.sceneAssistant.controller.stopListening('okButton', Mojo.Event.tap, this.checkKeyHandler); + this.sceneAssistant.controller.stopListening('cancelButton', Mojo.Event.tap, this.widget.mojo.close); + this.sceneAssistant.controller.document.removeEventListener('keyup', this.handleKeyHandler, false); + + this.focusField.mojo.focus(); +}; + +KeyDialogAssistant.prototype.activate = function(event) +{ + this.sceneAssistant.controller.get('mobileKey').mojo.focus(); +}; + +// --------------------------------------------------------------------------- +// MainAssistant +// --------------------------------------------------------------------------- +function MainAssistant() +{ +} + +MainAssistant.prototype.setup = function() +{ + //$$('body')[0].addClassName('palm-dark'); + + this.hasConnectivity = false; + this.checkConnectivity(); + + this.debug = 0; + + this.cookieData = new Mojo.Model.Cookie('netThauvinErikWebOsPingFm'); + this.prefs = this.cookieData.get(); + + this.api_key = 'edb93979c2abd58781f72d96f042e3a4'; + this.messageMaxLen = 140; + + this.defaultMethods = [ + { + label: 'Default', + value: 'default' + }, + { + label: 'Micro-blogs', + value: 'microblog' + }, + { + label: 'Statuses', + value: 'status' + }, + { + label: 'Blogs', + value: 'blog' + }]; + + if (!this.prefs) + { + this.prefs = + { + version: 1, + user_app_key: null, + showTitle: false, + defaultMethod: this.defaultMethods[0].value, + methods: this.defaultMethods.clone() + }; + + this.cookieData.put(this.prefs); + } + + var hasNoMethods = (this.defaultMethods.length == this.prefs.methods.length); + + this.updatedMethods = + { + hasNoServices: hasNoMethods, + hasNoTargets: hasNoMethods + }; + + this.showTitleMenuItem = + { + label: '', + command: 'do-title' + }; + this.toggleTitleMenu(); + + this.appMenuModel = + { + visible: true, + items: [ + { + label: 'About #{title}...'.interpolate( + { + title: Mojo.Controller.appInfo.title + }), + command: 'do-about' + }, Mojo.Menu.editItem, this.showTitleMenuItem, + { + label: 'Refresh Methods', + command: 'do-methods-refresh' + }, + { + label: 'Reset Key...', + command: 'do-key-reset' + }] + }; + + this.controller.setupWidget(Mojo.Menu.appMenu, + { + omitDefaultItems: true + }, this.appMenuModel); + + this.controller.setupWidget('methodList', + { + label: 'Method' + }, this.methodModel = + { + choices: this.prefs.methods, + value: this.prefs.defaultMethod + + }); + + this.controller.setupWidget('titleField', + { + hintText: 'Type a title...', + focusMode: Mojo.Widget.focusAppendMode, + hide: true + }, this.titleModel = + { + value: '' + }); + + this.controller.setupWidget('messageField', + { + hintText: 'Type your message...', + multiline: true, + changeOnKeyPress: true, + focusMode: Mojo.Widget.focusAppendMode + }, this.messageModel = + { + value: '' + }); + + this.pingButton = this.controller.get('pingBtn'); + this.pingBtnModel = + { + label: 'Ping It!', + original: 'Ping It!', + disabled: true + }; + this.controller.setupWidget('pingBtn', + { + type: Mojo.Widget.activityButton + }, this.pingBtnModel); + + this.handleKeyHandler = this.handleKeyEvent.bindAsEventListener(this); + this.controller.listen('messageField', Mojo.Event.propertyChange, this.handleKeyHandler); + + this.pingItHandler = this.pingIt.bindAsEventListener(this); + this.controller.listen('pingBtn', Mojo.Event.tap, this.pingItHandler); + + this.activateWindowHandler = this.activateWindow.bindAsEventListener(this); + this.controller.listen(this.controller.stageController.document, Mojo.Event.activate, this.activateWindowHandler); +}; + +MainAssistant.prototype.activateWindow = function() +{ + this.askForKey(); +}; + +MainAssistant.prototype.toggleTitleMenu = function() +{ + if (!this.prefs.showTitle) + { + this.controller.get('titleRow').hide(); + this.focusField = this.controller.get('messageField'); + this.showTitleMenuItem.label = 'Show Title'; + } + else + { + this.controller.get('titleRow').show(); + this.focusField = this.controller.get('titleField'); + this.showTitleMenuItem.label = 'Hide Title'; + } +}; + +MainAssistant.prototype.togglePingButton = function() +{ + Mojo.Log.info("togglePingButton"); + + if (this.hasConnectivity) + { + this.pingBtnModel.disabled = (this.messageModel.value.length == 0); + } + else + { + this.pingBtnModel.disabled = true; + } + + this.controller.modelChanged(this.pingBtnModel); +}; + +MainAssistant.prototype.activate = function(event) +{ + //this.askForKey(); +}; + +MainAssistant.prototype.deactivate = function(event) +{ + this.cookieData.put(this.prefs); + //this.cookieData.remove(); +}; + +MainAssistant.prototype.cleanup = function() +{ + this.controller.stopListening('pingBtn', Mojo.Event.tap, this.pingItHandler); + this.controller.stopListening('messageField', Mojo.Event.propertyChange, this.handleKeyHandler); + this.controller.stopListening(this.controller.stageController.document, Mojo.Event.activate, this.activateWindowHandler); +}; + + +MainAssistant.prototype.handleCommand = function(event) +{ + if (event.type == Mojo.Event.command) + { + switch (event.command) + { + case 'do-about': + var currentScene = this.controller.stageController.activeScene(); + currentScene.showAlertDialog( + { + allowHTMLMessage: true, + onChoose: function(value) + { + }, + message: '#{title} v#{version}
© 2010, Erik C. Thauvin

This application uses the Ping.fm API but is not endorsed or certified by Ping.fm'.interpolate( + { + title: Mojo.Controller.appInfo.title, + version: Mojo.Controller.appInfo.version + }), + choices: [ + { + label: 'OK', + value: '' + }] + }); + break; + + case 'do-title': + this.prefs.showTitle = !this.prefs.showTitle; + this.toggleTitleMenu(); + + this.focusField.mojo.focus(); + + break; + + case 'do-methods-refresh': + this.resetMethods(); + this.updateMethods(); + + this.focusField.mojo.focus(); + break; + + case 'do-key-reset': + this.resetMethods(); + this.prefs.user_app_key = null; + + this.askForKey(); + break; + + default: + break; + + } + } +}; + +MainAssistant.prototype.handleKeyEvent = function(event) +{ + var len = this.messageMaxLen - this.messageModel.value.length; + + if (len < 0) + { + this.controller.get('cntLabel').update('' + len + ''); + } + else + { + this.controller.get('cntLabel').update(len); + } + + this.togglePingButton(); +}; + +MainAssistant.prototype.askForKey = function(event) +{ + if (this.prefs.user_app_key === null) + { + this.controller.showDialog( + { + template: 'main/key-dialog', + assistant: new KeyDialogAssistant(this, this.focusField) + }); + } +}; + +MainAssistant.prototype.pingIt = function() +{ + var message = this.messageModel.value; + + if (this.prefs.user_app_key === null) + { + this.pingButton.mojo.deactivate(); + this.askForKey(); + } + else if (message.length > 0) + { + this.pingBtnModel.label = 'Posting...'; + this.pingBtnModel.disabled = true; + this.controller.modelChanged(this.pingBtnModel); + + var method = this.methodModel.value; + var url = 'http://api.ping.fm/v1/user.post'; + + this.prefs.defaultMethod = method; + + var params = new Hash( + { + 'api_key': this.api_key, + 'user_app_key': this.prefs.user_app_key, + 'body': Base64.encode(message), + 'encoding': 'base64', + 'debug': this.debug + }); + + if (method.charAt(0) == '#') + { + url = 'http://api.ping.fm/v1/user.tpost'; + params.set('trigger', method.substring(1)); + } + else if (method.charAt(0) == '@') + { + params.set('service', method.substring(1)); + params.set('post_method', 'default'); + } + else + { + params.set('post_method', method); + } + + var title = this.titleModel.value; + if (title != '') + { + params.set('title', Base64.encode(title)); + } + + Mojo.Log.info('pingIt: ' + params.toQueryString()); + + var request = new Ajax.Request(url, + { + method: 'post', + parameters: params, + evalJSON: 'false', + onSuccess: this.pingItSuccess.bind(this), + onFailure: this.pingItFailure.bind(this) + }); + } + else + { + this.focusField.mojo.focus(); + this.pingButton.mojo.deactivate(); + } +}; + +MainAssistant.prototype.pingItSuccess = function(transport) +{ + this.pingButton.mojo.deactivate(); + this.pingBtnModel.label = this.pingBtnModel.original; + + if (transport.responseXML === null) + { + Mojo.Log.warn("pingItSuccess failure."); + Mojo.Controller.errorDialog("Invalid response from the Ping.fm API.", this.controller.window); + + this.pingBtnModel.disabled = false; + } + else + { + var rsp = transport.responseXML.getElementsByTagName('rsp'); + var status = rsp[0].getAttribute('status'); + + if (status == 'FAIL') + { + Mojo.Log.warn(transport.responseText); + Mojo.Controller.errorDialog(rsp[0].getElementsByTagName('message').item(0).textContent, this.controller.window); + this.pingBtnModel.disabled = false; + } + else + { + this.messageModel.value = ''; + this.titleModel.value = ''; + this.controller.modelChanged(this.messageModel); + this.controller.modelChanged(this.titleModel); + this.controller.get('cntLabel').update(this.messageMaxLen); + this.pingBtnModel.disabled = true; + + Mojo.Controller.getAppController().showBanner('Your message has been posted.', {}); + } + } + + this.controller.modelChanged(this.pingBtnModel); + this.focusField.mojo.focus(); + +}; + +MainAssistant.prototype.pingItFailure = function(transport) +{ + this.pingButton.mojo.deactivate(); + this.pingBtnModel.label = this.pingBtnModel.original; + this.pingBtnModel.disabled = false; + this.controller.modelChanged(this.pingBtnModel); + + this.transportFailure('pingItFailure', transport); +}; + +MainAssistant.prototype.resetMethods = function() +{ + this.updatedMethods.hasNoServices = true; + this.updatedMethods.hasNoTargets = true; + + this.prefs.methods.clear(); + for (var i = 0; i < this.defaultMethods.length; i++) + { + this.prefs.methods.push(this.defaultMethods[i]); + } + this.prefs.defaultMethod = this.defaultMethods[0].value; + + this.methodModel.value = this.prefs.defaultMethod; + this.controller.modelChanged(this.methodModel); +}; + +MainAssistant.prototype.updateMethods = function() +{ + if (this.prefs.user_app_key && this.hasConnectivity) + { + var request; + + if (this.updatedMethods.hasNoServices) + { + request = new Ajax.Request('http://api.ping.fm/v1/user.services', + { + method: 'post', + parameters: + { + 'api_key': this.api_key, + 'user_app_key': this.prefs.user_app_key + }, + evalJSON: 'false', + onSuccess: this.updateMethodsSuccess.bind(this), + onFailure: this.updateMethodsFailure.bind(this) + }); + } + + if (this.updatedMethods.hasNoTargets) + { + request = new Ajax.Request('http://api.ping.fm/v1/user.triggers', + { + method: 'post', + parameters: + { + 'api_key': this.api_key, + 'user_app_key': this.prefs.user_app_key + }, + evalJSON: 'false', + onSuccess: this.updateTriggersSuccess.bind(this), + onFailure: this.updateTriggersFailure.bind(this) + }); + } + } +}; + +MainAssistant.prototype.updateMethodsSuccess = function(transport) +{ + if (transport.responseXML === null) + { + Mojo.Log.warn("updateMethodsSuccess failure."); + this.updateMethods(); + } + else + { + this.updateMethods.hasNoServices = false; + + var services = transport.responseXML.getElementsByTagName('service'); + for (var i = 0; i < services.length; i++) + { + var id = '@' + services[i].getAttribute('id'); + var name = services[i].getAttribute('name'); + var trigger = services[i].getElementsByTagName('trigger').item(0).textContent; + + this.prefs.methods.push( + { + label: name + ' (' + trigger + ')', + value: id + }); + + if (this.prefs.defaultMethod == id) + { + this.methodModel.value = id; + this.controller.modelChanged(this.methodModel); + } + } + + Mojo.Controller.getAppController().showBanner('Methods successfully updated.', {}); + } +}; + + +MainAssistant.prototype.updateMethodsFailure = function(transport) +{ + this.transportFailure('updateMethodFailure', transport); +}; + +MainAssistant.prototype.updateTriggersSuccess = function(transport) +{ + if (transport.responseXML === null) + { + Mojo.Log.warn("updateTriggersSuccess failure."); + this.updateMethods(); + } + else + { + this.updateMethods.hasNoTargets = false; + + var triggers = transport.responseXML.getElementsByTagName('trigger'); + + for (var i = 0; i < triggers.length; i++) + { + var id = '#' + triggers[i].getAttribute('id'); + //var method = triggers[i].getAttribute('method'); + + this.prefs.methods.unshift( + { + label: id, + value: id + }); + + if (this.prefs.defaultMethod == id) + { + this.methodModel.value = id; + this.controller.modelChanged(this.methodModel); + } + } + } +}; + +MainAssistant.prototype.updateTriggersFailure = function(transport) +{ + this.transportFailure('updateTriggersFailure', transport); +}; + + +MainAssistant.prototype.handleConnectivity = function(status) +{ + if (status.isInternetConnectionAvailable === true) + { + this.hasConnectivity = true; + } + else + { + this.hasConnectivity = false; + Mojo.Controller.getAppController().showBanner('No connectivity to the Internet.', {}); + } + + this.togglePingButton(); +}; + +MainAssistant.prototype.checkConnectivity = function() +{ + this.controller.serviceRequest('palm://com.palm.connectionmanager', + { + method: 'getstatus', + parameters: + { + subscribe: true + }, + onSuccess: this.handleConnectivity.bind(this) + }); +}; + +MainAssistant.prototype.transportFailure = function(caller, transport) +{ + Mojo.Log.error(caller + ': ' + transport.responseText); + Mojo.Controller.errorDialog('Error status #{status} returned from Ping.fm API request.'.interpolate( + { + status: transport.status + }), this.controller.window); +}; + diff --git a/Ping.fm/app/assistants/stage-assistant.js b/Ping.fm/app/assistants/stage-assistant.js new file mode 100644 index 0000000..6eed90b --- /dev/null +++ b/Ping.fm/app/assistants/stage-assistant.js @@ -0,0 +1,8 @@ +function StageAssistant() +{ +} + +StageAssistant.prototype.setup = function() +{ + this.controller.pushScene('main'); +}; diff --git a/Ping.fm/app/helpers/base64.js b/Ping.fm/app/helpers/base64.js new file mode 100644 index 0000000..0221530 --- /dev/null +++ b/Ping.fm/app/helpers/base64.js @@ -0,0 +1,86 @@ +// --------------------------------------------------------------------------- +// Base64 +// +// Encodes binary files into base64 strings. +// Taken from the Palm's Data sample application. +// --------------------------------------------------------------------------- +var Base64 = + { + // private property + _keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', + + // public method for encoding + encode: function(input) + { + var output = ''; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 0; + + while (i < input.length) + { + + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) + { + enc3 = enc4 = 64; + } + else if (isNaN(chr3)) + { + enc4 = 64; + } + + output = output + + this._keyStr.charAt(enc1) + + this._keyStr.charAt(enc2) + + this._keyStr.charAt(enc3) + + this._keyStr.charAt(enc4); + + } + + return output; + }, + + // public method for decoding + decode: function(input) + { + var output = ''; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); + + while (i < input.length) + { + + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) + { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) + { + output = output + String.fromCharCode(chr3); + } + } + return output; + } + }; diff --git a/Ping.fm/app/views/main/key-dialog.html b/Ping.fm/app/views/main/key-dialog.html new file mode 100644 index 0000000..1ea5907 --- /dev/null +++ b/Ping.fm/app/views/main/key-dialog.html @@ -0,0 +1,18 @@ +
+
+ Enter Ping.fm Mobile Key +
+
+ Get your Mobile Key +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ping.fm/app/views/main/main-scene.html b/Ping.fm/app/views/main/main-scene.html new file mode 100644 index 0000000..77ee30c --- /dev/null +++ b/Ping.fm/app/views/main/main-scene.html @@ -0,0 +1,52 @@ +
+
+
+
+ Ping.fm +
+
+
+
+ Ping My +
+
+
+
+
+
+
+
+
+
+
+
+ Your Message +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 140 +
+
+
+
+
+
+
+
+
diff --git a/Ping.fm/appinfo.json b/Ping.fm/appinfo.json new file mode 100644 index 0000000..361a8f4 --- /dev/null +++ b/Ping.fm/appinfo.json @@ -0,0 +1,10 @@ +{ + "id": "net.thauvin.erik.webos.pingfm", + "version": "1.0.0", + "vendor": "Erik C. Thauvin", + "type": "web", + "theme": "light", + "main": "index.html", + "title": "Ping.fm", + "icon": "icon.png" +} diff --git a/Ping.fm/ect-logo.png b/Ping.fm/ect-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..64abdfc048f7288328e4698996c504203a43b96b GIT binary patch literal 13972 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 literal 0 HcmV?d00001 diff --git a/Ping.fm/framework_config.json b/Ping.fm/framework_config.json new file mode 100644 index 0000000..078e742 --- /dev/null +++ b/Ping.fm/framework_config.json @@ -0,0 +1,3 @@ +{ + "logLevel":0 +} \ No newline at end of file diff --git a/Ping.fm/icon.png b/Ping.fm/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..860e428fd173d9349adc48501e89b849cea08215 GIT binary patch literal 4037 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 RBzph=002ovPDHLkV1k7k*0BHp literal 0 HcmV?d00001 diff --git a/Ping.fm/index.html b/Ping.fm/index.html new file mode 100644 index 0000000..1da9438 --- /dev/null +++ b/Ping.fm/index.html @@ -0,0 +1,14 @@ + + + + + Ping.fm +