Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f6c41765e | ||
|
|
518cb6aba3 | ||
|
|
6094506ec5 |
No files matched your search
@@ -1,4 +1,2 @@
|
||||
secrets.js
|
||||
.DS_Store
|
||||
framework_config.json
|
||||
_bin/
|
||||
@@ -1,6 +1,3 @@
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
echo copying latest common components
|
||||
cp $DIR/../../webos-common/Mojo/updater-model.js $DIR/../app/models/updater-model.js
|
||||
cp $DIR/../../webos-common/Mojo/com.wosa.mojo.additions.js $DIR/../app/com.wosa.mojo.additions.js
|
||||
mkdir -p $DIR/../_bin
|
||||
palm-package $DIR/../ -o $DIR/../_bin
|
||||
palm-package $DIR/../ -o $DIR/../_bin
|
||||
@@ -1,5 +1,5 @@
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
echo copying latest common components
|
||||
cp $DIR/../../webos-common/Mojo/updater-model.js $DIR/../app/models/updater-model.js
|
||||
cp $DIR/../../webos-common/Mojo/com.wosa.mojo.additions.js $DIR/../app/com.wosa.mojo.additions.js
|
||||
palm-run $DIR/../
|
||||
palm-package simplechat-app simplechat-service simplechat-package
|
||||
palm-install com.jonandnic.simplechat_2.0.0_all.ipk
|
||||
palm-launch com.jonandnic.simplechat
|
||||
palm-log -f com.jonandnic.simplechat.app
|
||||
@@ -1,40 +0,0 @@
|
||||
# Simple Chat client app for webOS
|
||||
|
||||

|
||||
|
||||
SimpleChat client for legacy Palm/HP webOS devices, depends on back-end services:
|
||||
|
||||
+ [simplechat-service](https://github.com/codepoet80/simplechat-service)
|
||||
|
||||
+ [simplechat-discordbot](https://github.com/codepoet80/simplechat-discordbot) (Optional)
|
||||
|
||||
You can also self-host the services.
|
||||
|
||||
## What is This?
|
||||
|
||||
This is an app for the defunct mobile webOS platform, made by Palm and later acquired by HP. It runs on devices like the Palm Pre or Pixi, or the HP
|
||||
Pre3 or TouchPad.
|
||||
|
||||
webOS technology was acquired by LG and repurposed for TVs and IoT devices, but they made significant changes and this app will not run on those platforms.
|
||||
|
||||
Releases of this app, and many other new and restored apps, can be found in the [webOS Archive App Museum](http://appcatalog.webosarchive.org).
|
||||
|
||||
## Why?
|
||||
|
||||
Aside from being a fan of the platform, the author thinks consumers have lost out now that the smart phone ecosystem has devolved into a duopoly.
|
||||
Apple and Google take turns copying each other, and consumers line up to buy basically the same new phone every year. The era when webOS, Blackberry and
|
||||
Windows Phone were serious competitors was marked by creativity in form factor and software development, which has been lost. This app represents a (futile)
|
||||
attempt to keep webOS mobile devices useful for as long as possible.
|
||||
|
||||
The website [http://www.webosarchive.org](http://www.webosarchive.org) recovers, archives and maintains material related to development, and hosts services
|
||||
that restore functionality to webOS devices. A small but active [community](http://www.webosarchive.org/discord) of users take advantage of these services to keep their retro devices alive.
|
||||
|
||||
## How?
|
||||
|
||||
Mobile webOS was truly a web-derived platform. Based on Linux, and able to run properly compiled Linux binaries, developers could get raw resources access (including GPU) through a PDK (Plug-in Development Kit) but most apps were written in some flavor of Javascript, interacting with a WebKit-based browser. The toolkits were heavily optimized for the devices, and web-based apps usually felt pretty close to native. Services could be written using NodeJS and talk to each other through API calls structured to look like web service calls. App front-ends were usually written in either the Mojo (pre-tablet) or Enyo (tablet and newer phones) Javascript frameworks. Enyo apps can often be run with only minor modification in any WebKit based browser (eg: Safari or Chrome).
|
||||
|
||||
You can learn more about these frameworks at the restored [SDK](http://sdk.webosarchive.org).
|
||||
|
||||
webOS devices can be found cheaply on eBay, and while the phones will cease to be useful as phones when the 3G shutdown is through, both the phones and the Touchpad can be used around the home for a variety of [fun and useful things](http://www.webosarchive.org/docs/thingstotry/).
|
||||
|
||||
If you have a device, instructions for activating, getting online and getting apps installed can be found in the [webOS Archive Docs section](http://www.webosarchive.org/docs/activate/).
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
In the app assistant, we setup some app-wide global objects and handle different kinds of launches, creating and delegating to the main stage
|
||||
*/
|
||||
var appModel = null;
|
||||
var updaterModel = null;
|
||||
var systemModel = null;
|
||||
var MainStageName = "main";
|
||||
var welcomed = false;
|
||||
Mojo.Additions = Additions;
|
||||
|
||||
function AppAssistant() {
|
||||
appModel = new AppModel();
|
||||
updaterModel = new UpdaterModel();
|
||||
systemModel = new SystemModel();
|
||||
serviceModel = new ServiceModel();
|
||||
}
|
||||
|
||||
//This function will handle relaunching the app when an alarm goes off(see the device/alarm scene)
|
||||
AppAssistant.prototype.handleLaunch = function(params) {
|
||||
Mojo.Log.info("SimpleChat is Launching! Launch params: " + JSON.stringify(params));
|
||||
|
||||
//Load preferences
|
||||
appModel.LoadSettings();
|
||||
Mojo.Log.info("settings now: " + JSON.stringify(appModel.AppSettingsCurrent));
|
||||
if (!appModel.AppSettingsCurrent["BackgroundUpdate"]) {
|
||||
appModel.AppSettingsCurrent["BackgroundUpdate"] = "00:30:00";
|
||||
appModel.SaveSettings();
|
||||
}
|
||||
|
||||
//Reset alarms
|
||||
systemModel.ClearSystemAlarm("SimpleChat");
|
||||
if (appModel.AppSettingsCurrent["BackgroundUpdate"] && appModel.AppSettingsCurrent["BackgroundUpdate"] != "" && appModel.AppSettingsCurrent["BackgroundUpdate"] != -1)
|
||||
systemModel.SetSystemAlarmRelative("SimpleChat", appModel.AppSettingsCurrent["BackgroundUpdate"]);
|
||||
|
||||
var mainStage = this.controller.getStageProxy("main"); //get the proxy for the stage if it already exists (eg: app is currently open)
|
||||
if (mainStage) //If the stage exists, use it
|
||||
{
|
||||
Mojo.Log.info("Found existing main stage, app was already running");
|
||||
|
||||
var stageController = this.controller.getStageController("main");
|
||||
if (!params || params["action"] == undefined) //If no action parameters was passed, this is a normal launch
|
||||
{
|
||||
//if there was a share action, load with that
|
||||
if (params && params["newshare"] != undefined) {
|
||||
appModel.LaunchQuery = decodeURI(params["newshare"]);
|
||||
Mojo.Log.info("This is re-launch with share action: " + appModel.LaunchQuery);
|
||||
} else {
|
||||
Mojo.Log.info("This is a normal re-launch");
|
||||
}
|
||||
stageController.activate(); //bring existing stage into focus
|
||||
return;
|
||||
} else //If parameters were passed, this is a launch from a system alarm
|
||||
{
|
||||
Mojo.Log.warn("This is a re-launch with parameters: " + JSON.stringify(params) + ". Safe to ignore, since app is already running.");
|
||||
appModel.ShowNotificationStage();
|
||||
return;
|
||||
}
|
||||
} else //If no stage exists, determine if we should make one
|
||||
{
|
||||
Mojo.Log.info("Did not find existing main stage, app is not running");
|
||||
|
||||
if (!params || params["action"] == undefined) //If no action parameters was passed, this is a normal launch
|
||||
{
|
||||
var currVersion = Mojo.Controller.appInfo.version;
|
||||
//if there was a share action, load with that
|
||||
if (params && params["newshare"] != undefined) {
|
||||
appModel.LaunchQuery = decodeURI(params["newshare"]);
|
||||
Mojo.Log.info("This is launch with share action: " + appModel.LaunchQuery);
|
||||
} else {
|
||||
Mojo.Log.info("This is a normal launch of version " + currVersion);
|
||||
}
|
||||
|
||||
var stageArguments = { name: MainStageName, lightweight: true };
|
||||
this.controller.createStageWithCallback(stageArguments, function(stageController) {
|
||||
stageController.pushScene(MainStageName);
|
||||
}.bind(this));
|
||||
|
||||
return;
|
||||
} else //If parameters were passed, this is a launch from a system alarm
|
||||
{
|
||||
Mojo.Log.info("This is an alarm launch: " + JSON.stringify(params));
|
||||
appModel.ShowNotificationStage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,178 +0,0 @@
|
||||
function VersionAssistant(startup) {
|
||||
this.isStartup = startup;
|
||||
|
||||
// on first start, this message is displayed, along with the current version message from below
|
||||
this.startupMessage = Mojo.Controller.appInfo.startupMessage;
|
||||
|
||||
//New Features
|
||||
this.changelog = [
|
||||
{
|
||||
version: "Version 1.9.0",
|
||||
detail: [
|
||||
"Share images in the chat, right from your webOS device!",
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.8.6",
|
||||
detail: [
|
||||
"Fix a bug parsing certain kinds of links.",
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.8.5",
|
||||
detail: [
|
||||
"Add support for sharing from JustType and other apps.",
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.8.0",
|
||||
detail: [
|
||||
"Dark theme now available in Preferences!",
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.7.1",
|
||||
detail: [
|
||||
"Fix a bug where hardware mute switch wasn't respected. Show transmit indicator. Add ability to disable link and image parsing to speed things up on tiny devices.",
|
||||
]
|
||||
},{
|
||||
version: "Version 1.7.0",
|
||||
detail: [
|
||||
"Images from Discord are now supported! Inline rendering uses a thumbnail for efficiency; tap the image to load the fullsize, or tap elsewhere on the row to pull up the menu that lets you download the image to your device (it will be saved to /internal/downloads)",
|
||||
]
|
||||
},{
|
||||
version: "Version 1.6.0",
|
||||
detail: [
|
||||
"Added ability to parse Imgur album links and render via a service proxy.",
|
||||
]
|
||||
},{
|
||||
version: "Version 1.5.0",
|
||||
detail: [
|
||||
"Added ability to parse Share Services links and show thumbnails, configurable in Preferences.",
|
||||
]
|
||||
},{
|
||||
version: "Version 1.4.1",
|
||||
detail: [
|
||||
"Add support for some basic markdown",
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.4.0",
|
||||
detail: [
|
||||
"Enter key behavior as a Preference",
|
||||
"Even more silent background sync, won't sync if offline",
|
||||
"Swiping notifications resets missed message count",
|
||||
"Adjust tap target for collapsing controls"
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.3.2",
|
||||
detail: [
|
||||
"More sync timing options.",
|
||||
"Refactored some code to make forking easier."
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.3.1",
|
||||
detail: [
|
||||
"Enter key now sends message when Command menu buttons are hidden."
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.3.0",
|
||||
detail: [
|
||||
"Drastically improved background update and notifications."
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.2.0",
|
||||
detail: [
|
||||
"Converts image links to an image proxy so they can be viewed and scaled properly on tiny devices",
|
||||
"Improved background update, using a notification launch, no longer interupts Exhibition, video playback or One Night Stand"
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.1.3",
|
||||
detail: [
|
||||
"Bug fixes and general maintenance"
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.1.2",
|
||||
detail: [
|
||||
"Show/Hide the Command menu buttons by tapping the Compose area title bar",
|
||||
"Enable/Disable Discord Emojis in Preferences",
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.1.1",
|
||||
detail: [
|
||||
"Improved Discord integration, including showing Emojis!<span class='emoji-outer emoji-sizer'><span class='emoji-inner emoji1f388'></span></span>",
|
||||
"Now with a smaller emoji file!",
|
||||
"Improved timeout logic.",
|
||||
"Trying different background sync logic."
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// setup command menu
|
||||
this.cmdMenuModel = {
|
||||
visible: false,
|
||||
items: [
|
||||
{},
|
||||
{
|
||||
label: $L("OK! Let's Go..."),
|
||||
command: 'do-continue'
|
||||
},
|
||||
{}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
VersionAssistant.prototype.setup = function() {
|
||||
this.titleElement = this.controller.get('title');
|
||||
this.dataElement = this.controller.get('data');
|
||||
|
||||
this.titleElement.innerHTML = $L('Version Info');
|
||||
|
||||
var html = '';
|
||||
html += '<div style="margin: 2px 12px 12px 12px">' + this.startupMessage + '</div>';
|
||||
|
||||
for (var i = 0; i < this.changelog.length; i++) {
|
||||
html += Mojo.View.render({ object: { title: this.changelog[i].version }, template: 'version/rowDivider' });
|
||||
html += '<ul>';
|
||||
|
||||
for (var j = 0; j < this.changelog[i].detail.length; j++) {
|
||||
html += '<li>' + this.changelog[i].detail[j] + '</li>';
|
||||
}
|
||||
html += '</ul>';
|
||||
}
|
||||
|
||||
// set data
|
||||
this.dataElement.innerHTML = html;
|
||||
|
||||
// setup menu
|
||||
this.controller.setupWidget(Mojo.Menu.appMenu, { omitDefaultItems: true }, { visible: false });
|
||||
|
||||
//if (this.isStartup) {
|
||||
// set command menu
|
||||
this.controller.setupWidget(Mojo.Menu.commandMenu, { menuClass: 'no-fade' }, this.cmdMenuModel);
|
||||
//}
|
||||
};
|
||||
|
||||
VersionAssistant.prototype.activate = function(event) {
|
||||
this.timer = this.controller.window.setTimeout(this.showContinue.bind(this), 2 * 1000);
|
||||
};
|
||||
VersionAssistant.prototype.deactivate = function(event) {};
|
||||
VersionAssistant.prototype.cleanup = function(event) {};
|
||||
|
||||
VersionAssistant.prototype.showContinue = function() {
|
||||
// show the command menu
|
||||
this.controller.setMenuVisible(Mojo.Menu.commandMenu, true);
|
||||
};
|
||||
|
||||
VersionAssistant.prototype.handleCommand = function(event) {
|
||||
if (event.type == Mojo.Event.command) {
|
||||
switch (event.command) {
|
||||
case 'do-continue':
|
||||
this.controller.stageController.popScene();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
App Model
|
||||
Version 0.4
|
||||
Created: 2018
|
||||
Author: Jon W
|
||||
License: MIT
|
||||
Description: Common functions for webOS apps, particularly for managing persisted options in cookies
|
||||
*/
|
||||
|
||||
var AppModel = function() {
|
||||
//Define your default scene (needed for settings management)
|
||||
this.DefaultScene = "main";
|
||||
|
||||
//Define your app-wide, non-persisted settings here
|
||||
this.UpdateCheckDone = false;
|
||||
this.LaunchQuery = "";
|
||||
this.ServiceEndpointBase = Mojo.Controller.appInfo.serviceURL;
|
||||
this.ClientId = secrets.clientid;
|
||||
this.LastMessageSelected = null;
|
||||
|
||||
//Define your app preferences (to be saved by OS)
|
||||
this.AppSettingsCurrent = null;
|
||||
this.AppSettingsDefaults = {
|
||||
ThemePreference: "palm-default",
|
||||
ForegroundUpdate: 10000,
|
||||
BackgroundUpdate: "00:30:00",
|
||||
AlertSound: "Subtle (short)",
|
||||
ShowEmojis: true,
|
||||
SkipParsing: false,
|
||||
ShowWOSAThumbs: true,
|
||||
EnterSubmits: "collapsed",
|
||||
UseClientAPIKey: false,
|
||||
UseCustomEndpoint: false,
|
||||
ClientAPIKey: "",
|
||||
EndpointURL: "",
|
||||
SenderName: "webOS User",
|
||||
FirstRun: true,
|
||||
MyMessages: null,
|
||||
LastKnownMessage: null,
|
||||
LastVersionRun: 0
|
||||
};
|
||||
}
|
||||
|
||||
AppModel.prototype.SetThemePreference = function(theController) {
|
||||
if (appModel.AppSettingsCurrent["ThemePreference"] != "system-theme") {
|
||||
theController.document.body.className = appModel.AppSettingsCurrent["ThemePreference"];
|
||||
Mojo.Log.info("Using local theme pref: " + appModel.AppSettingsCurrent["ThemePreference"]);
|
||||
} else {
|
||||
systemModel.LoadWOSAPrefs(function(response) {
|
||||
if (response) {
|
||||
Mojo.Log.error("Using system theme pref: " + systemModel.WOSAPrefs.theme);
|
||||
theController.document.body.className = systemModel.WOSAPrefs.theme;
|
||||
}
|
||||
}.bind(this))
|
||||
}
|
||||
}
|
||||
|
||||
AppModel.prototype.ShowNotificationStage = function() {
|
||||
Mojo.Log.info("App Model checking if we need to show Dashboard stage...");
|
||||
this.serviceEndpointBase = appModel.ServiceEndpointBase;
|
||||
if (appModel.AppSettingsCurrent["UseCustomEndpoint"] && appModel.AppSettingsCurrent["EndpointURL"]) {
|
||||
this.serviceEndpointBase = appModel.AppSettingsCurrent["EndpointURL"];
|
||||
}
|
||||
if (appModel.AppSettingsCurrent["UseClientAPIKey"] && appModel.AppSettingsCurrent["ClientAPIKey"]) {
|
||||
this.ClientId = appModel.AppSettingsCurrent["ClientAPIKey"];
|
||||
}
|
||||
//Check for connectivity, then check for messages
|
||||
systemModel.GetInternetConnectionState(this.checkForMessages.bind(this));
|
||||
}
|
||||
|
||||
AppModel.prototype.checkForMessages = function(connMgrResponse) {
|
||||
Mojo.Log.info("App Model got response from connection manager: " + JSON.stringify(connMgrResponse));
|
||||
if (connMgrResponse && connMgrResponse.isInternetConnectionAvailable) {
|
||||
Mojo.Log.info("Checking for new messages in App Model...");
|
||||
serviceModel.getChats(this.serviceEndpointBase, this.ClientId, function(response) {
|
||||
Mojo.Log.info("App Model got response from getChats: " + response);
|
||||
if (response != null && response != "") {
|
||||
var responseObj = JSON.parse(response);
|
||||
if (responseObj.status != "error") {
|
||||
if (responseObj.messages && responseObj.messages.length > 0) {
|
||||
var newMessageCount = this.findNewMessageCount(appModel.AppSettingsCurrent["LastKnownMessage"], responseObj.messages);
|
||||
if (newMessageCount > 0) {
|
||||
Mojo.Log.info("Found new chat on server during App Model message check!");
|
||||
this.actuallyShowNotificationStage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
AppModel.prototype.findNewMessageCount = function(LastKnownMessage, newMessages) {
|
||||
var actuallyNewMessages = [];
|
||||
var startCounting = false;
|
||||
for (var j = 0; j < newMessages.length; j++) {
|
||||
if (startCounting) {
|
||||
actuallyNewMessages.push(newMessages[j].uid);
|
||||
}
|
||||
if (newMessages[j].uid == LastKnownMessage) {
|
||||
startCounting = true;
|
||||
}
|
||||
}
|
||||
return actuallyNewMessages.length;
|
||||
}
|
||||
|
||||
AppModel.prototype.actuallyShowNotificationStage = function() {
|
||||
this.controller = Mojo.Controller.getAppController();
|
||||
var dashboardStage = this.controller.getStageProxy("dashboard");
|
||||
var pushDashScene = function(stageController) {
|
||||
stageController.pushScene('dashboard', "dashboard/dashboard-scene");
|
||||
}.bind(this);
|
||||
|
||||
if (!dashboardStage) {
|
||||
Mojo.Log.info("Dashboard stage not open, creating it...");
|
||||
this.controller.createStageWithCallback({
|
||||
name: 'dashboard',
|
||||
lightweight: true,
|
||||
height: 100,
|
||||
soundclass: "assets/silent.mp3"
|
||||
}, pushDashScene, 'dashboard');
|
||||
} else {
|
||||
Mojo.Log.info("Dashboard stage already open, activating it...");
|
||||
var dashboardStageController = this.controller.getStageController("dashboard");
|
||||
if (dashboardStageController) {
|
||||
dashboardStageController.activate();
|
||||
dashboardStageController.delegateToSceneAssistant("activate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppModel.prototype.CloseNotificationStage = function() {
|
||||
this.controller = Mojo.Controller.getAppController();
|
||||
var dashboardStage = this.controller.getStageProxy("dashboard");
|
||||
|
||||
if (!dashboardStage) {
|
||||
Mojo.Log.info("Dashboard stage not open, nothing to do");
|
||||
} else {
|
||||
Mojo.Log.info("Dashboard stage open, closing it...");
|
||||
this.controller.closeStage("dashboard");
|
||||
}
|
||||
}
|
||||
|
||||
//#region Inherited from common App Model
|
||||
|
||||
//You probably don't need to change the below functions since they all work against the Cookie defaults you defined above.
|
||||
// LoadSettings: call when your app starts, or you want to load previously persisted options.
|
||||
// SaveSettings: call any time you want to persist an option.
|
||||
// ResetSettings: call if you want to forget stored settings and return to defaults. Your default scene will be popped and re-pushed.
|
||||
AppModel.prototype.LoadSettings = function(safe) {
|
||||
this.AppSettingsCurrent = this.AppSettingsDefaults;
|
||||
var loadSuccess = false;
|
||||
var settingsCookie = new Mojo.Model.Cookie("settings");
|
||||
try {
|
||||
appSettings = settingsCookie.get();
|
||||
if ((typeof appSettings == "undefined" || appSettings == null) || (safe && !this.checkSettingsValid(appSettings))) {
|
||||
Mojo.Log.warn("** Using first run default settings");
|
||||
} else {
|
||||
Mojo.Log.info("** Using cookie settings!");
|
||||
this.loadCookieIntoCurrent(appSettings);
|
||||
loadSuccess = true;
|
||||
}
|
||||
} catch (ex) {
|
||||
settingsCookie.put(null);
|
||||
Mojo.Log.error("** Settings cookie were corrupt and have been purged!");
|
||||
Mojo.Log.error(ex);
|
||||
}
|
||||
return loadSuccess;
|
||||
}
|
||||
|
||||
AppModel.prototype.loadCookieIntoCurrent = function(cookieSettings) {
|
||||
this.AppSettingsCurrent = cookieSettings;
|
||||
}
|
||||
|
||||
AppModel.prototype.checkSettingsValid = function(loadedSettings) {
|
||||
var retValue = true;
|
||||
for (var key in this.AppSettingsDefaults) {
|
||||
if (typeof loadedSettings[key] === undefined || loadedSettings[key] == null) {
|
||||
Mojo.Log.warn("** An expected saved setting, " + key + ", was null or undefined.");
|
||||
retValue = false;
|
||||
}
|
||||
if (typeof loadedSettings[key] !== typeof this.AppSettingsDefaults[key]) {
|
||||
Mojo.Log.warn("** A saved setting, " + key + ", was of type " + typeof(loadedSettings[key]) + " but expected type " + typeof(this.AppSettingsDefaults[key]));
|
||||
retValue = false;
|
||||
}
|
||||
if (typeof this.AppSettingsDefaults[key] === "string" && this.AppSettingsDefaults[key].indexOf(this.BaseDateString) != -1 && loadedSettings[key].indexOf(this.BaseDateString)) {
|
||||
Mojo.Log.warn("** A saved setting could not be compared to an expected date value.");
|
||||
retValue = false;
|
||||
}
|
||||
if (typeof this.AppSettingsDefaults[key] === "string" && (this.AppSettingsDefaults[key] == "false" || this.AppSettingsDefaults[key] == "true")) {
|
||||
if (loadedSettings[key] != "false" && loadedSettings[key] != "true") {
|
||||
Mojo.Log.warn("** A saved setting did not have the expected boolean value.");
|
||||
retValue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
AppModel.prototype.SaveSettings = function() {
|
||||
var settingsCookie = new Mojo.Model.Cookie("settings");
|
||||
Mojo.Log.info("Saving settings as: " + JSON.stringify(appModel.AppSettingsCurrent));
|
||||
Mojo.Log.info("Default settings at Save time are: " + JSON.stringify(appModel.AppSettingsDefaults));
|
||||
|
||||
settingsCookie.put(appModel.AppSettingsCurrent);
|
||||
}
|
||||
|
||||
AppModel.prototype.ResetSettings = function() {
|
||||
Mojo.Log.info("resetting settings");
|
||||
//Tell main scene to drop settings
|
||||
this.AppSettingsCurrent = this.AppSettingsDefaults;
|
||||
this.SaveSettings();
|
||||
Mojo.Log.info("settings have been reset");
|
||||
|
||||
var stageController = Mojo.Controller.getAppController().getActiveStageController();
|
||||
stageController.popScene(this.DefaultScene);
|
||||
Mojo.Log.info("closed default scene");
|
||||
|
||||
//Restart main scene
|
||||
stageController.pushScene(this.DefaultScene);
|
||||
Mojo.Log.info("re-opened default scene");
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -1,175 +0,0 @@
|
||||
var ServiceModel = function() {
|
||||
|
||||
};
|
||||
|
||||
ServiceModel.prototype.makeServiceUrl = function(serviceBase, endPoint) {
|
||||
if (endPoint.indexOf(".php") == -1)
|
||||
endPoint = endPoint + ".php";
|
||||
return serviceBase + endPoint;
|
||||
}
|
||||
|
||||
ServiceModel.prototype.getChats = function(serviceBase, clientId, callback) {
|
||||
var serviceURL = serviceBase + "get-chat.php";
|
||||
Mojo.Log.info("Trying to get chats from: " + serviceURL);
|
||||
this.retVal = "";
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open("GET", serviceURL);
|
||||
xmlhttp.setRequestHeader("Client-Id", clientId);
|
||||
xmlhttp.send();
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||
if (callback)
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
ServiceModel.prototype.postChat = function(useSender, useMessage, serviceBase, clientId, callback) {
|
||||
var serviceURL = serviceBase + "post-chat.php";
|
||||
var msgToPost = {
|
||||
sender: useSender,
|
||||
message: useMessage
|
||||
}
|
||||
Mojo.Log.info("Posting chat to: " + serviceURL);
|
||||
Mojo.Log.info(JSON.stringify(msgToPost));
|
||||
|
||||
this.retVal = "";
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open("POST", serviceURL);
|
||||
xmlhttp.setRequestHeader("Client-Id", clientId);
|
||||
xmlhttp.timeout = 2000;
|
||||
xmlhttp.send(JSON.stringify(msgToPost));
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||
if (callback)
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}.bind(this);
|
||||
xmlhttp.ontimeout = function() {
|
||||
callback();
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
ServiceModel.prototype.editChat = function(useSender, useMessage, uid, editKey, serviceBase, clientId, callback) {
|
||||
var serviceURL = serviceBase + "edit-chat.php";
|
||||
var msgToPost = {
|
||||
sender: useSender,
|
||||
message: useMessage,
|
||||
uid: uid,
|
||||
editKey: editKey
|
||||
}
|
||||
Mojo.Log.info("Edit chat to: " + serviceURL);
|
||||
Mojo.Log.info(JSON.stringify(msgToPost));
|
||||
|
||||
this.retVal = "";
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open("POST", serviceURL);
|
||||
xmlhttp.setRequestHeader("Client-Id", clientId);
|
||||
xmlhttp.send(JSON.stringify(msgToPost));
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||
if (callback)
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
ServiceModel.prototype.uploadPhoto = function(fullFilePath, sender, serviceBase, clientId, callback, errorhandler) {
|
||||
var useURL = serviceBase + 'upload-attachment.php';
|
||||
Mojo.Log.info("Uploading photo: " + fullFilePath + " to " + useURL);
|
||||
return new Mojo.Service.Request('palm://com.palm.downloadmanager/', {
|
||||
method: 'upload',
|
||||
parameters: {
|
||||
fileName: fullFilePath,
|
||||
url: useURL,
|
||||
fileLabel: 'image',
|
||||
contentType: (function(p) {
|
||||
var e = p.split('.').pop().toLowerCase();
|
||||
return e === 'png' ? 'image/png' : e === 'gif' ? 'image/gif' : 'image/jpeg';
|
||||
}(fullFilePath)),
|
||||
postParameters: [
|
||||
{ key: 'sender', data: sender }
|
||||
],
|
||||
customHttpHeaders: ['Client-Id: ' + clientId],
|
||||
subscribe: true
|
||||
},
|
||||
onSuccess: function(e) {
|
||||
if (!e.completed) return;
|
||||
if (e.completionCode !== 0 || e.httpCode !== 200) {
|
||||
if (errorhandler) errorhandler('Upload failed: HTTP ' + e.httpCode + ', code ' + e.completionCode);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var result = JSON.parse(e.responseString);
|
||||
if (callback) callback(result);
|
||||
} catch (ex) {
|
||||
if (errorhandler) errorhandler('Bad response from upload server');
|
||||
}
|
||||
},
|
||||
onFailure: function(e) {
|
||||
if (errorhandler) errorhandler('Upload error: ' + JSON.stringify(e));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ServiceModel.prototype.postChatWithAttachment = function(useSender, attachments, serviceBase, clientId, callback) {
|
||||
var serviceURL = serviceBase + 'post-chat.php';
|
||||
var msgToPost = {
|
||||
sender: useSender,
|
||||
message: '',
|
||||
attachments: attachments
|
||||
};
|
||||
Mojo.Log.info("Posting chat with attachment to: " + serviceURL);
|
||||
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open("POST", serviceURL);
|
||||
xmlhttp.setRequestHeader("Client-Id", clientId);
|
||||
xmlhttp.timeout = 5000;
|
||||
xmlhttp.send(JSON.stringify(msgToPost));
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||
if (callback)
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}.bind(this);
|
||||
xmlhttp.ontimeout = function() {
|
||||
if (callback) callback();
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
ServiceModel.prototype.likeChat = function(uid, serviceBase, clientId, callback) {
|
||||
var serviceURL = serviceBase + "like-chat.php";
|
||||
var msgToPost = {
|
||||
uid: uid,
|
||||
like: "+1"
|
||||
}
|
||||
Mojo.Log.info("Like chat to: " + serviceURL);
|
||||
Mojo.Log.info(JSON.stringify(msgToPost));
|
||||
|
||||
this.retVal = "";
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open("POST", serviceURL);
|
||||
xmlhttp.setRequestHeader("Client-Id", clientId);
|
||||
xmlhttp.send(JSON.stringify(msgToPost));
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||
if (callback)
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"id": "com.palm.app.notalexnoyle.almostsimplechat",
|
||||
"version": "1.9.1",
|
||||
"vendor": "NotAlexNoyle",
|
||||
"type": "web",
|
||||
"main": "index.html",
|
||||
"noWindow": true,
|
||||
"title": "AlmostSimpleChat",
|
||||
"appMuseumTitle": "Almost webOS SimpleChat",
|
||||
"icon": "icon.png",
|
||||
"pageTitle": "Almost webOS SimpleChat",
|
||||
"startupMessage": "<img src='icon.png' style='float:left; margin-right:8px'>Welcome to SimpleChat! We're so excited you're here chatting with us more than 10 years after this platform was supposed to have died!<br>You can also join this chat from Discord: <a href='http://www.webosarchive.org/discord'>webosarchive.org/discord</a> or view the log on the web: <a href='http://chat.webosarchive.org'>chat.webosarchive.org</a>",
|
||||
"serviceURL": "http://chat.webosarchive.org/",
|
||||
"splashicon": "icon-256x256.png",
|
||||
"uiRevision": "2",
|
||||
"universalSearch" : {
|
||||
"action": {
|
||||
"displayName": "New Share",
|
||||
"url": "com.palm.app.notalexnoyle.almostsimplechat",
|
||||
"launchParam": {
|
||||
"newshare": "#{searchTerms}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1,25 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name='viewport' content='height=device-height'>
|
||||
<title>Simple Chat</title>
|
||||
<script src="/usr/palm/frameworks/mojo/mojo.js" type="text/javascript" x-mojo-version="1"></script>
|
||||
|
||||
<!-- load my additions -->
|
||||
<script src="app/com.wosa.mojo.additions.js" type="text/javascript"></script>
|
||||
|
||||
<!-- application stylesheet should come in after the one loaded by the framework -->
|
||||
<link href="assets/simplechat.css" media="screen" rel="stylesheet" type="text/css">
|
||||
<link href="assets/emoji.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!--
|
||||
<audio id="audioPlayer">
|
||||
<source src="/media/internal/ringtones/Subtle (short).mp3" type="audio/mp3">
|
||||
</audio>
|
||||
-->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Jon W
|
||||
Copyright (c) 2020 Jon W
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -0,0 +1,7 @@
|
||||
# Simple Chat client app for webOS
|
||||
|
||||
SimpleChat client for legacy Palm/HP webOS devices, depends on back-end services listed below.
|
||||
|
||||
Uses [simplechat-service](https://github.com/codepoet80/simplechat-service)
|
||||
|
||||
You can also self-host the services.
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
In the app assistant, we setup some app-wide global objects and handle different kinds of launches, creating and delegating to the main stage
|
||||
*/
|
||||
var appModel = null;
|
||||
var updaterModel = null;
|
||||
var systemModel = null;
|
||||
var MainStageName = "main";
|
||||
var welcomed = false;
|
||||
Mojo.Additions = Additions;
|
||||
|
||||
function AppAssistant() {
|
||||
appModel = new AppModel();
|
||||
updaterModel = new UpdaterModel();
|
||||
systemModel = new SystemModel();
|
||||
serviceModel = new ServiceModel();
|
||||
}
|
||||
|
||||
//This function will handle relaunching the app when an alarm goes off(see the device/alarm scene)
|
||||
AppAssistant.prototype.handleLaunch = function(params) {
|
||||
//Load preferences
|
||||
appModel.LoadSettings();
|
||||
Mojo.Log.info("settings now: " + JSON.stringify(appModel.AppSettingsCurrent));
|
||||
if (!appModel.AppSettingsCurrent["BackgroundUpdate"]) {
|
||||
appModel.AppSettingsCurrent["BackgroundUpdate"] = "00:30:00";
|
||||
appModel.SaveSettings();
|
||||
}
|
||||
|
||||
//get the proxy for the stage in the event it already exists (eg: app is currently open)
|
||||
var mainStage = this.controller.getStageProxy("main");
|
||||
Mojo.Log.info("SimpleChat is Launching! Launch params: " + JSON.stringify(params));
|
||||
|
||||
//Reset alarms
|
||||
systemModel.ClearSystemAlarm("SimpleChat");
|
||||
if (appModel.AppSettingsCurrent["BackgroundUpdate"] && appModel.AppSettingsCurrent["BackgroundUpdate"] != "" && appModel.AppSettingsCurrent["BackgroundUpdate"] != -1)
|
||||
systemModel.SetSystemAlarmRelative("SimpleChat", appModel.AppSettingsCurrent["BackgroundUpdate"]);
|
||||
|
||||
var AppRunning = false;
|
||||
if (mainStage) {
|
||||
Mojo.Log.info("Found existing stage, app was already running");
|
||||
AppRunning = true;
|
||||
} else {
|
||||
Mojo.Log.info("Did not find existing stage, this is a new app launch!");
|
||||
}
|
||||
|
||||
if (AppRunning) //If the stage exists, use it
|
||||
{
|
||||
var stageController = this.controller.getStageController("main");
|
||||
if (!params || params["action"] == undefined) //If no parameters were passed, this is a normal launch
|
||||
{
|
||||
Mojo.Log.info("This is a normal re-launch");
|
||||
stageController.activate(); //bring existing stage into focus
|
||||
return;
|
||||
} else //If parameters were passed, this is a launch from a system alarm
|
||||
{
|
||||
Mojo.Log.info("This is a re-launch with parameters: " + JSON.stringify(params) + ". Safe to ignore, since app is already running.");
|
||||
systemModel.ShowNotificationStage("dashboard", "dashboard/dashboard-scene", 60, false, false);
|
||||
return;
|
||||
}
|
||||
} else //If not, determine if we should make one
|
||||
{
|
||||
if (!params || params["action"] == undefined) //If no parameters were passed, this is a normal launch
|
||||
{
|
||||
var currVersion = Mojo.Controller.appInfo.version;
|
||||
Mojo.Log.info("This is a normal launch of version " + currVersion);
|
||||
|
||||
var stageArguments = { name: MainStageName, lightweight: true };
|
||||
this.controller.createStageWithCallback(stageArguments, function(stageController) {
|
||||
stageController.pushScene(MainStageName);
|
||||
}.bind(this));
|
||||
return;
|
||||
} else //If parameters were passed, this is a launch from a system alarm
|
||||
{
|
||||
|
||||
Mojo.Log.info("This is an alarm launch: " + JSON.stringify(params));
|
||||
/*
|
||||
|
||||
return;*/
|
||||
|
||||
var pushClass0AlertScene = function(stageController) {
|
||||
stageController.pushScene('dashboard', "dashboard/dashboard-scene");
|
||||
}.bind(this);
|
||||
|
||||
Mojo.Controller.getAppController().showBanner("New messages in the chat!", { source: 'notification' });
|
||||
//var stageArguments = { name: MainStageName, lightweight: true };
|
||||
//this.controller.createStageWithCallback(stageArguments, function(stageController) {
|
||||
// Mojo.Controller.appController.closeStage("main");
|
||||
|
||||
//}.bind(this));
|
||||
|
||||
this.controller.createStageWithCallback({
|
||||
name: 'dashboard',
|
||||
lightweight: true,
|
||||
height: 100,
|
||||
soundclass: "assets/silent.mp3"
|
||||
}, pushClass0AlertScene, 'popupalert');
|
||||
|
||||
//systemModel.ShowNotificationStage("dashboard", "dashboard/dashboard-scene", 60, false, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
SystemModel.prototype.ShowNotificationStage = function(stageName, sceneName, heightToUse, sound, vibrate) {
|
||||
Mojo.Log.info("Showing notification stage.");
|
||||
//Determine what sound to use
|
||||
var soundToUse;
|
||||
if (!sound)
|
||||
soundToUse = "assets/silent.mp3";
|
||||
else if (sound == true || sound == "")
|
||||
soundToUse = "/media/internal/ringtones/Dulcimer (short).mp3"
|
||||
else
|
||||
soundToUse = sound;
|
||||
if (vibrate)
|
||||
this.Vibrate(vibrate);
|
||||
|
||||
var stageCallBack = function(stageController) {
|
||||
stageController.pushScene({ name: stageName, sceneTemplate: sceneName });
|
||||
}.bind(this);
|
||||
var appController = Mojo.Controller.getAppController();
|
||||
var stageController = appController.getStageController(stageName);
|
||||
if (stageController) {
|
||||
stageCallBack(stageController);
|
||||
} else {
|
||||
Mojo.Controller.getAppController().createStageWithCallback({
|
||||
name: stageName,
|
||||
lightweight: true,
|
||||
height: heightToUse,
|
||||
sound: soundToUse,
|
||||
clickableWhenLocked: true
|
||||
}, stageCallBack, 'dashboard');
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -5,12 +5,11 @@ chance of successfully changing the settings. We can then close this window. All
|
||||
*/
|
||||
function DashboardAssistant(argFromPusher) {
|
||||
this.passedArguments = argFromPusher;
|
||||
this.lastMessageCount = 0;
|
||||
}
|
||||
|
||||
DashboardAssistant.prototype.setup = function() {
|
||||
Mojo.Log.info("Dashboard notification stage setup at " + new Date());
|
||||
this.displayDashboard(Mojo.Controller.appInfo.title, "Checking for new messages...");
|
||||
Mojo.Log.info("Notification stage setup at " + new Date());
|
||||
this.displayDashboard("SimpleChat", "Checking for new messages...");
|
||||
|
||||
this.serviceEndpointBase = appModel.ServiceEndpointBase;
|
||||
if (appModel.AppSettingsCurrent["UseCustomEndpoint"] && appModel.AppSettingsCurrent["EndpointURL"]) {
|
||||
@@ -19,60 +18,42 @@ DashboardAssistant.prototype.setup = function() {
|
||||
if (!appModel.AppSettingsCurrent["AlertSound"] || appModel.AppSettingsCurrent["AlertSound"] == "") {
|
||||
appModel.AppSettingsCurrent["AlertSound"] = "Subtle (short)";
|
||||
}
|
||||
|
||||
//Event handlers
|
||||
Mojo.Event.listen(this.controller.get("dashboardinfo"), Mojo.Event.tap, this.handleTap.bind(this));
|
||||
}
|
||||
|
||||
DashboardAssistant.prototype.activate = function(event) {
|
||||
Mojo.Log.info("Dashboard activating!");
|
||||
this.clientId = appModel.ClientId;
|
||||
if (appModel.AppSettingsCurrent["UseClientAPIKey"] && appModel.AppSettingsCurrent["ClientAPIKey"]) {
|
||||
this.clientId = appModel.AppSettingsCurrent["ClientAPIKey"];
|
||||
}
|
||||
this.checkForMessages();
|
||||
}
|
||||
|
||||
DashboardAssistant.prototype.checkForMessages = function() {
|
||||
Mojo.Log.info("Checking for new messages in Dashboard...");
|
||||
serviceModel.getChats(this.serviceEndpointBase, this.clientId, function(response) {
|
||||
serviceModel.getChats(this.serviceEndpointBase, function(response) {
|
||||
var appController = Mojo.Controller.getAppController();
|
||||
if (response != null && response != "") {
|
||||
var responseObj = JSON.parse(response);
|
||||
if (responseObj.status == "error") {
|
||||
Mojo.Log.error("Error message from server during Dashboard message check: " + responseObj.msg);
|
||||
appController.closeStage("dashboard");
|
||||
Mojo.Log.error("Error message from server during background check: " + responseObj.msg);
|
||||
appController.closeAllStages();
|
||||
} else {
|
||||
if (responseObj.messages && responseObj.messages.length > 0) {
|
||||
var newMessageCount = this.findNewMessageCount(appModel.AppSettingsCurrent["LastKnownMessage"], responseObj.messages);
|
||||
if (newMessageCount > 0) {
|
||||
Mojo.Log.info("Found new chat on server during Dashboard message check!");
|
||||
|
||||
Mojo.Log.info("Found new chat on server during background check!");
|
||||
this.displayDashboard("SimpleChat", "New messages in the chat!", newMessageCount);
|
||||
//If the main app window is open, it will play a sound. If not, play a sound here.
|
||||
var appController = Mojo.Controller.getAppController();
|
||||
var mainStage = appController.getStageController("main");
|
||||
if (!mainStage) { //If the main app window is open,
|
||||
if (newMessageCount > this.lastMessageCount) {
|
||||
systemModel.PlayAlertSound(appModel.AppSettingsCurrent["AlertSound"]);
|
||||
this.lastMessageCount = newMessageCount;
|
||||
}
|
||||
this.displayDashboard(Mojo.Controller.appInfo.title, "New messages have arrived!", newMessageCount);
|
||||
} else {
|
||||
this.displayDashboard(Mojo.Controller.appInfo.title, "New messages have arrived!");
|
||||
if (!mainStage) {
|
||||
systemModel.PlayAlertSound(appModel.AppSettingsCurrent["AlertSound"]);
|
||||
}
|
||||
} else {
|
||||
Mojo.Log.info("No new chats on server during Dashboard message check.");
|
||||
Mojo.Log.info("No new chats on server during background check.");
|
||||
appController.closeStage("dashboard");
|
||||
}
|
||||
} else {
|
||||
Mojo.Log.warn("Chat results were empty during scheduled Dashboard message check. This is unlikely; server, API or connectivity problem possible");
|
||||
Mojo.Log.warn("Chat results were empty during scheduled background check. This is unlikely; server, API or connectivity problem possible");
|
||||
appController.closeStage("dashboard");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Mojo.Log.error("No usable response from server during Dashboard message check: " + response);
|
||||
Mojo.Log.error("No usable response from server during background check: " + response);
|
||||
appController.closeStage("dashboard");
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
//Event handlers
|
||||
Mojo.Event.listen(this.controller.get("dashboardinfo"), Mojo.Event.tap, this.handleTap.bind(this));
|
||||
}
|
||||
|
||||
DashboardAssistant.prototype.findNewMessageCount = function(LastKnownMessage, newMessages) {
|
||||
@@ -82,7 +63,6 @@ DashboardAssistant.prototype.findNewMessageCount = function(LastKnownMessage, ne
|
||||
if (startCounting) {
|
||||
actuallyNewMessages.push(newMessages[j].uid);
|
||||
appModel.AppSettingsCurrent["LastKnownMessage"] = newMessages[j].uid;
|
||||
Mojo.Log.info("Dashboard counting: " + newMessages[j].uid);
|
||||
}
|
||||
if (newMessages[j].uid == LastKnownMessage) {
|
||||
startCounting = true;
|
||||
@@ -117,13 +97,8 @@ DashboardAssistant.prototype.handleDragEnd = function(event) {
|
||||
|
||||
DashboardAssistant.prototype.displayDashboard = function(title, message, count) {
|
||||
var infoElement = this.controller.get("dashboardinfo");
|
||||
var info = { title: title, message: message };
|
||||
if (count) {
|
||||
info.count = count;
|
||||
info.showCount = "inline";
|
||||
} else {
|
||||
info.showCount = "none";
|
||||
}
|
||||
|
||||
var info = { title: title, message: message, count: count };
|
||||
var renderedInfo = Mojo.View.render({ object: info, template: "dashboard/item-info" });
|
||||
infoElement.innerHTML = renderedInfo;
|
||||
this.controller.getSceneScroller().mojo.revealTop(true);
|
||||
@@ -135,6 +110,5 @@ DashboardAssistant.prototype.deactivate = function(event) {
|
||||
|
||||
// Cleanup anything we did in setup function
|
||||
DashboardAssistant.prototype.cleanup = function() {
|
||||
Mojo.Log.info("Dashboard notification stage closing at " + new Date());
|
||||
appModel.SaveSettings();
|
||||
Mojo.Log.info("notification stage closing at " + new Date());
|
||||
}
|
||||
@@ -56,7 +56,9 @@ EmoticonPickerDialogAssistant.prototype.setup = function(widget) {
|
||||
|
||||
EmoticonPickerDialogAssistant.prototype.insertCell = function(row, emoticon) {
|
||||
var cell = row.insertCell(0);
|
||||
cell.innerHTML = Mojo.Format.runTextIndexer(emoticon.escapeHTML());
|
||||
var MojoHTML = Mojo.Format.runTextIndexer(emoticon.escapeHTML());
|
||||
MojoHTML = MojoHTML.replace("file:///usr/palm/", "");
|
||||
cell.innerHTML = MojoHTML;
|
||||
cell.setAttribute("emo", emoticon);
|
||||
cell.style.height = "40px";
|
||||
};
|
||||
@@ -11,14 +11,10 @@ function MainAssistant() {
|
||||
this.doingMessageEdit = false;
|
||||
this.serverRetries = 0;
|
||||
this.serverGiveUp = 4;
|
||||
this.maximized = false;
|
||||
}
|
||||
|
||||
MainAssistant.prototype.setup = function() {
|
||||
appModel.SetThemePreference(this.controller);
|
||||
|
||||
// title
|
||||
this.controller.get('spnTitle').innerHTML = Mojo.Controller.appInfo.pageTitle;
|
||||
// setup message field
|
||||
this.messageFieldModel = {
|
||||
'original': ''
|
||||
@@ -41,16 +37,14 @@ MainAssistant.prototype.setup = function() {
|
||||
this.messageFieldModel.attributes,
|
||||
this.messageFieldModel
|
||||
);
|
||||
//Spinners
|
||||
// with global members for easy toggling later
|
||||
//Loading spinner - with global members for easy toggling later
|
||||
this.spinnerAttrs = {
|
||||
spinnerSize: Mojo.Widget.spinnerSmall
|
||||
};
|
||||
//Posting spinner
|
||||
this.spinnerWorkModel = {
|
||||
this.spinnerModel = {
|
||||
spinning: false
|
||||
}
|
||||
this.controller.setupWidget('workingSpinner', this.spinnerAttrs, this.spinnerWorkModel);
|
||||
this.controller.setupWidget('workingSpinner', this.spinnerAttrs, this.spinnerModel);
|
||||
//Chat Log List (starts empty)
|
||||
this.listElement = this.controller.get('chatList');
|
||||
this.listInfoModel = {
|
||||
@@ -75,22 +69,15 @@ MainAssistant.prototype.setup = function() {
|
||||
friction: 'low'
|
||||
};
|
||||
this.controller.setupWidget('chatScroller', {}, this.scrollerModel);
|
||||
//Detect device type for UI layout decisions (Pixi/Veer lack 480px or 800px dimension)
|
||||
var isTiny = Mojo.Environment.DeviceInfo.platformVersionMajor < 3 &&
|
||||
this.controller.window.screen.width !== 800 &&
|
||||
this.controller.window.screen.height !== 800 &&
|
||||
this.controller.window.screen.width !== 480 &&
|
||||
this.controller.window.screen.height !== 480;
|
||||
//Menu
|
||||
this.appMenuAttributes = { omitDefaultItems: true };
|
||||
this.appMenuModel = {
|
||||
label: "Settings",
|
||||
items: [
|
||||
Mojo.Menu.editItem,
|
||||
{ label: Mojo.Controller.appInfo.title + " Info", command: 'do-Info' },
|
||||
{ label: "SimpleChat Info", command: 'do-Info' },
|
||||
{ label: "Change Username", command: 'do-Username' },
|
||||
{ label: "Preferences", command: 'do-Preferences' },
|
||||
{ label: "Share Image", command: 'do-ShareImage' },
|
||||
{ label: "About", command: 'do-myAbout' }
|
||||
]
|
||||
};
|
||||
@@ -100,13 +87,12 @@ MainAssistant.prototype.setup = function() {
|
||||
spacerHeight: 0,
|
||||
menuClass: 'no-fade'
|
||||
};
|
||||
var leftButtons = [{ label: 'Emoticon', iconPath: 'assets/emoticon.png', command: 'do-Emoticon' }];
|
||||
if (!isTiny)
|
||||
leftButtons.push({ label: 'Photo', command: 'do-ShareImage' });
|
||||
this.cmdMenuModel = {
|
||||
visible: true,
|
||||
items: [{
|
||||
items: leftButtons
|
||||
items: [
|
||||
{ label: 'Emoticon', iconPath: 'assets/emoticon.png', command: 'do-Emoticon' }
|
||||
]
|
||||
},
|
||||
{
|
||||
items: [
|
||||
@@ -122,14 +108,6 @@ MainAssistant.prototype.setup = function() {
|
||||
Mojo.Event.listen(this.controller.get("chatList"), Mojo.Event.listTap, this.handleListClick.bind(this));
|
||||
Mojo.Event.listen(this.controller.stageController.document, Mojo.Event.stageActivate, this.activateWindow.bind(this));
|
||||
Mojo.Event.listen(this.controller.stageController.document, Mojo.Event.stageDeactivate, this.deactivateWindow.bind(this));
|
||||
Mojo.Event.listenForFocusChanges(this.controller.get("txtMessage"), this.handleTextFocus.bind(this));
|
||||
|
||||
// Non-Mojo handlers
|
||||
this.keyupHandler = this.handleKeyUp.bindAsEventListener(this);
|
||||
this.controller.document.addEventListener("keyup", this.keyupHandler, true);
|
||||
//this.controller.document.getElementById("divComposeTitle").addEventListener("click", this.toggleCommandMenu.bind(this));
|
||||
this.controller.document.getElementById("spanCompose").addEventListener("click", this.toggleCommandMenu.bind(this));
|
||||
this.controller.document.getElementById("imgTwisty").addEventListener("click", this.toggleCommandMenu.bind(this));
|
||||
|
||||
//Check for updates
|
||||
this.checkForUpdates();
|
||||
@@ -145,8 +123,23 @@ MainAssistant.prototype.activate = function(event) {
|
||||
if (appModel.AppSettingsCurrent["UseClientAPIKey"] && appModel.AppSettingsCurrent["ClientAPIKey"]) {
|
||||
this.clientId = appModel.AppSettingsCurrent["ClientAPIKey"];
|
||||
}
|
||||
//Get settings or load defaults
|
||||
this.initDefaultSettings();
|
||||
//Set an alert sound
|
||||
if (!appModel.AppSettingsCurrent["AlertSound"] || appModel.AppSettingsCurrent["AlertSound"] == "") {
|
||||
appModel.AppSettingsCurrent["AlertSound"] = "Subtle (short)";
|
||||
}
|
||||
//Check for Emoji option
|
||||
if (appModel.AppSettingsCurrent["ShowEmojis"] == null) {
|
||||
Mojo.Log.info("Adding Emoji setting with default value!")
|
||||
appModel.AppSettingsCurrent["ShowEmojis"] = appModel.AppSettingsDefaults["ShowEmojis"];
|
||||
appModel.SaveSettings();
|
||||
}
|
||||
//Init Message memory
|
||||
if (!appModel.AppSettingsCurrent["MyMessages"]) {
|
||||
appModel.AppSettingsCurrent["MyMessages"] = [];
|
||||
}
|
||||
if (appModel.AppSettingsCurrent["LastKnownMessages"]) { //This was the old way, clean it up
|
||||
appModel.AppSettingsCurrent["LastKnownMessages"] = null;
|
||||
}
|
||||
|
||||
//Find out what kind of device this is
|
||||
if (Mojo.Environment.DeviceInfo.platformVersionMajor >= 3) {
|
||||
@@ -164,21 +157,14 @@ MainAssistant.prototype.activate = function(event) {
|
||||
Mojo.Log.warn("Device detected as Pixi or Veer");
|
||||
}
|
||||
}
|
||||
//Set some variables
|
||||
this.maximized = true;
|
||||
|
||||
//systemModel.PreventDisplaySleep();
|
||||
this.serverRetries = 0;
|
||||
this.pendingMessages = [];
|
||||
this.firstPoll = this.listInfoModel.items.length === 0;
|
||||
|
||||
//Disable background sync
|
||||
Mojo.Log.info("Switching to foreground sync")
|
||||
this.firstPoll = true;
|
||||
this.startPollingServer();
|
||||
systemModel.ClearSystemAlarm("SimpleChat");
|
||||
|
||||
//Get ready for input
|
||||
this.handleTextFocus();
|
||||
|
||||
//Determine if we should show any startup messages
|
||||
var currVersion = Mojo.Controller.appInfo.version;
|
||||
if (!welcomed && (!appModel.AppSettingsCurrent["LastVersionRun"] || appModel.AppSettingsCurrent["LastVersionRun"] != currVersion)) {
|
||||
this.pausePollingServer();
|
||||
@@ -191,6 +177,11 @@ MainAssistant.prototype.activate = function(event) {
|
||||
this.controller.window.addEventListener('resize', this.orientationChanged.bind(this)); //we have to do this for TouchPad because it does not get orientationChanged events
|
||||
this.orientationChanged();
|
||||
|
||||
//Add event handlers
|
||||
Mojo.Event.listen(this.controller.get("chatList"), Mojo.Event.listTap, this.handleListClick.bind(this));
|
||||
Mojo.Event.listenForFocusChanges(this.controller.get("txtMessage"), this.handleTextFocus.bind(this));
|
||||
this.controller.document.getElementById("divComposeTitle").addEventListener("click", this.toggleCommandMenu.bind(this));
|
||||
|
||||
//Figure out if this is our first time
|
||||
if (appModel.AppSettingsCurrent["FirstRun"] || !appModel.AppSettingsCurrent["SenderName"] || (appModel.AppSettingsCurrent["SenderName"] && appModel.AppSettingsCurrent["SenderName"].toLowerCase() == "webos user")) {
|
||||
appModel.AppSettingsCurrent["FirstRun"] = false;
|
||||
@@ -220,7 +211,7 @@ MainAssistant.prototype.orientationChanged = function() {
|
||||
this.scaleScroller("wide");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MainAssistant.prototype.scaleScroller = function(orientation) {
|
||||
if (!this.lastOrientation || orientation != this.lastOrientation) {
|
||||
@@ -250,8 +241,9 @@ MainAssistant.prototype.adustScrollerForKeyboard = function(orientation) {
|
||||
else
|
||||
this.scaledHeight = Math.floor(Mojo.Environment.DeviceInfo.screenWidth / this.scalingFactor) - bottomBuffer;
|
||||
|
||||
//Mojo.Log.info(this.DeviceType + " orientation is " + orientation + " bottom buffer is: " + bottomBuffer + " scaled height: " + this.scaledHeight);
|
||||
Mojo.Log.info(this.DeviceType + " orientation is " + orientation + " bottom buffer is: " + bottomBuffer + " scaled height: " + this.scaledHeight);
|
||||
this.chatScroller.style.height = this.scaledHeight + "px";
|
||||
//this.scrollToBottom();
|
||||
|
||||
setTimeout(fixScroll = function() {
|
||||
this.controller.getSceneScroller().mojo.revealTop(true);
|
||||
@@ -274,51 +266,32 @@ MainAssistant.prototype.pausePollingServer = function() {
|
||||
}
|
||||
|
||||
/* UI Handlers */
|
||||
|
||||
//Handles the enter key
|
||||
MainAssistant.prototype.handleKeyUp = function(event) {
|
||||
if (event && Mojo.Char.isEnterKey(event.keyCode)) {
|
||||
if (event.srcElement.parentElement.id == "txtMessage") {
|
||||
if (appModel.AppSettingsCurrent["EnterSubmits"] == "always") {
|
||||
Mojo.Log.info("Doing submit on enter because Preference is always");
|
||||
this.handleSendMessage();
|
||||
} else if (!this.menuOn && appModel.AppSettingsCurrent["EnterSubmits"] == "collapsed") {
|
||||
Mojo.Log.info("Doing submit on enter because collapsed and Preference is collapsed");
|
||||
this.handleSendMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MainAssistant.prototype.handleListClick = function(event) {
|
||||
appModel.LastMessageSelected = event.item;
|
||||
this.listTarget = event.originalEvent.target;
|
||||
if (this.listTarget.tagName != "A" && this.listTarget.tagName != "IMG") { //don't pop-up menu if they tapped a hyperlink or image
|
||||
//Decide what items to put in pop-up menu
|
||||
var popupMenuItems = [];
|
||||
var isMine = false;
|
||||
for (var m = 0; m < appModel.AppSettingsCurrent["MyMessages"].length; m++) {
|
||||
if (appModel.AppSettingsCurrent["MyMessages"][m].uid == appModel.LastMessageSelected.uid)
|
||||
isMine = true;
|
||||
}
|
||||
if (isMine)
|
||||
popupMenuItems.push({ label: 'Edit Message', command: 'do-editMessage' });
|
||||
else {
|
||||
if (event.item.links != null) {
|
||||
popupMenuItems.push({ label: 'Copy Link', command: 'do-copyLink' });
|
||||
popupMenuItems.push({ label: 'Follow Link', command: 'do-followLink' });
|
||||
}
|
||||
popupMenuItems.push({ label: 'Copy Message', command: 'do-copy' });
|
||||
if (event.item.attachments && event.item.attachments.length > 0)
|
||||
popupMenuItems.push({ label: 'Save Attachments', command: 'do-saveAttachments' });
|
||||
popupMenuItems.push({ label: 'Like', command: 'do-like' });
|
||||
}
|
||||
this.controller.popupSubmenu({
|
||||
onChoose: this.handlePopupChoose.bind(this, event.item),
|
||||
placeNear: this.listTarget,
|
||||
items: popupMenuItems
|
||||
});
|
||||
|
||||
//Decide what items to put in pop-up menu
|
||||
var popupMenuItems = [];
|
||||
var isMine = false;
|
||||
for (var m = 0; m < appModel.AppSettingsCurrent["MyMessages"].length; m++) {
|
||||
if (appModel.AppSettingsCurrent["MyMessages"][m].uid == appModel.LastMessageSelected.uid)
|
||||
isMine = true;
|
||||
}
|
||||
if (isMine)
|
||||
popupMenuItems.push({ label: 'Edit Message', command: 'do-editMessage' });
|
||||
else {
|
||||
if (event.item.links != null) {
|
||||
popupMenuItems.push({ label: 'Copy Link', command: 'do-copyLink' });
|
||||
popupMenuItems.push({ label: 'Follow Link', command: 'do-followLink' });
|
||||
}
|
||||
popupMenuItems.push({ label: 'Copy Message', command: 'do-copy' });
|
||||
popupMenuItems.push({ label: 'Like', command: 'do-like' });
|
||||
}
|
||||
this.controller.popupSubmenu({
|
||||
onChoose: this.handlePopupChoose.bind(this, event.item),
|
||||
placeNear: this.listTarget,
|
||||
items: popupMenuItems
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -352,14 +325,6 @@ MainAssistant.prototype.handlePopupChoose = function(message, command) {
|
||||
}
|
||||
systemModel.LaunchApp("com.palm.app.browser", parameters);
|
||||
break;
|
||||
case "do-saveAttachments":
|
||||
var attachments = appModel.LastMessageSelected.attachments;
|
||||
for (var i=0; i< attachments.length; i++) {
|
||||
var attach = attachments[i];
|
||||
var url = serviceModel.makeServiceUrl(this.serviceEndpointBase, "attachment.php?") + attach.filename;
|
||||
systemModel.DownloadFile(url, "image/" + attach.extension, "downloads", attach.filename, true);
|
||||
}
|
||||
break;
|
||||
case "do-editMessage":
|
||||
this.doEditMessage(message);
|
||||
break;
|
||||
@@ -397,14 +362,11 @@ MainAssistant.prototype.handleCommand = function(event) {
|
||||
stageController.pushScene({ name: "version", disableSceneScroller: false });
|
||||
break;
|
||||
case 'do-myAbout':
|
||||
Mojo.Additions.ShowDialogBox(Mojo.Controller.appInfo.title + " - " + Mojo.Controller.appInfo.version, "AlmostSimpleChat client for webOS. Fork by NotAlexNoyle. Based on SimpleChat, Copyright 2022, Jon W. Distributed under an MIT License.<br>Fork source: https://git.trueog.net/NotAlexNoyle/AlmostSimpleChat<br>Upstream source: https://github.com/codepoet80/webos-simplechat");
|
||||
break;
|
||||
case 'do-ShareImage':
|
||||
this.handleShareImage();
|
||||
Mojo.Additions.ShowDialogBox("SimpleChat - " + Mojo.Controller.appInfo.version, "SimpleChat client for webOS. Copyright 2021, Jon Wise. Distributed under an MIT License.<br>Source code available at: https://github.com/codepoet80/webos-simplechat");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MainAssistant.prototype.doEditMessage = function(message) {
|
||||
this.controller.get('txtMessage').mojo.setValue(appModel.LastMessageSelected.message);
|
||||
@@ -432,56 +394,6 @@ MainAssistant.prototype.doLikeMessage = function(message) {
|
||||
}
|
||||
|
||||
/* Server Interactions */
|
||||
MainAssistant.prototype.handleShareImage = function() {
|
||||
var self = this;
|
||||
Mojo.FilePicker.pickFile({
|
||||
kind: 'image',
|
||||
actionName: 'Share',
|
||||
onSelect: function(file) {
|
||||
Mojo.Log.info("Photo selected: " + file.fullPath);
|
||||
Mojo.Controller.getAppController().showBanner({ messageText: 'Uploading image...' }, { source: 'notification' });
|
||||
self.disableUI();
|
||||
serviceModel.uploadPhoto(
|
||||
file.fullPath,
|
||||
appModel.AppSettingsCurrent["SenderName"],
|
||||
self.serviceEndpointBase,
|
||||
self.clientId,
|
||||
function(attachment) {
|
||||
self.postPhotoToService(attachment);
|
||||
},
|
||||
function(errorText) {
|
||||
self.enableUI();
|
||||
Mojo.Log.error("Photo upload failed: " + errorText);
|
||||
Mojo.Controller.getAppController().showBanner({ messageText: 'Upload failed' }, { source: 'notification' });
|
||||
}
|
||||
);
|
||||
}
|
||||
}, this.controller.stageController);
|
||||
};
|
||||
|
||||
MainAssistant.prototype.postPhotoToService = function(attachment) {
|
||||
serviceModel.postChatWithAttachment(
|
||||
appModel.AppSettingsCurrent["SenderName"],
|
||||
[attachment],
|
||||
this.serviceEndpointBase,
|
||||
this.clientId,
|
||||
function(response) {
|
||||
this.enableUI();
|
||||
try {
|
||||
var responseObj = JSON.parse(response);
|
||||
if (responseObj.error) {
|
||||
Mojo.Log.error("Server error posting photo: " + responseObj.error);
|
||||
Mojo.Controller.getAppController().showBanner({ messageText: 'Server error posting image' }, { source: 'notification' });
|
||||
} else {
|
||||
Mojo.Log.info("Photo posted: " + responseObj.posted);
|
||||
}
|
||||
} catch (e) {
|
||||
Mojo.Log.error("Failed to parse photo post response");
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
};
|
||||
|
||||
MainAssistant.prototype.handleSendMessage = function(event) {
|
||||
this.controller.get('txtMessage').mojo.blur();
|
||||
var newMessage = this.controller.get('txtMessage').mojo.getValue();
|
||||
@@ -509,11 +421,14 @@ MainAssistant.prototype.postMessageToService = function(newMessage) {
|
||||
Mojo.Log.info("Message accepted by server: " + responseObj.posted); //{ "posted": "604529e19fb7f", "senderKey": "604529e19fb99" }
|
||||
if (responseObj.posted) {
|
||||
Mojo.Log.info("responseObj: " + JSON.stringify(responseObj));
|
||||
var MojoHTML = Mojo.Format.runTextIndexer(newMessage);
|
||||
MojoHTML = MojoHTML.replace("file:///usr/palm/", "");
|
||||
|
||||
var newMsg = {
|
||||
uid: responseObj.posted,
|
||||
sender: appModel.AppSettingsCurrent["SenderName"],
|
||||
message: newMessage,
|
||||
formattedMessage: Mojo.Format.runTextIndexer(newMessage),
|
||||
formattedMessage: MojoHTML,
|
||||
timestamp: this.convertTimeStamp(new Date(), false),
|
||||
color: "gray"
|
||||
};
|
||||
@@ -560,7 +475,11 @@ MainAssistant.prototype.editMessageToService = function(newMessage) {
|
||||
for (var i = 0; i < thisWidgetSetup.model.items.length; i++) {
|
||||
if (thisWidgetSetup.model.items[i].uid == appModel.LastMessageSelected.uid) {
|
||||
thisWidgetSetup.model.items[i].message = newMessage;
|
||||
thisWidgetSetup.model.items[i].formattedMessage = Mojo.Format.runTextIndexer(newMessage);
|
||||
|
||||
var MojoHTML = Mojo.Format.runTextIndexer(newMessage);
|
||||
MojoHTML = MojoHTML.replace("file:///usr/palm/", "");
|
||||
|
||||
thisWidgetSetup.model.items[i].formattedMessage = MojoHTML;
|
||||
thisWidgetSetup.model.items[i].color = "gray";
|
||||
this.controller.get('chatList').mojo.noticeUpdatedItems(i, [thisWidgetSetup.model.items[i]]);
|
||||
}
|
||||
@@ -607,11 +526,8 @@ MainAssistant.prototype.likeMessageToService = function() {
|
||||
|
||||
//Send a request to Service to get chat messages
|
||||
MainAssistant.prototype.getChats = function() {
|
||||
//show transmitting
|
||||
this.controller.get('imgTransmit').style.display = "block";
|
||||
|
||||
if (this.serverRetries <= this.serverGiveUp) {
|
||||
serviceModel.getChats(this.serviceEndpointBase, this.clientId, function(response) {
|
||||
serviceModel.getChats(this.serviceEndpointBase, function(response) {
|
||||
//Mojo.Log.info("getChat response: " + response);
|
||||
if (response != null && response != "") {
|
||||
var responseObj = JSON.parse(response);
|
||||
@@ -623,7 +539,8 @@ MainAssistant.prototype.getChats = function() {
|
||||
this.serverRetries = 0;
|
||||
this.updateChatsList(responseObj.messages);
|
||||
} else {
|
||||
Mojo.Log.warn("Server returned empty message list.");
|
||||
Mojo.Log.warn("Search results were empty. This is unlikely; server, API or connectivity problem possible");
|
||||
Mojo.Additions.ShowDialogBox("No results", "The server did not report any matches for the search.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -634,9 +551,6 @@ MainAssistant.prototype.getChats = function() {
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
//hide transmitting
|
||||
this.controller.get('imgTransmit').style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,25 +563,18 @@ MainAssistant.prototype.updateChatsList = function(results) {
|
||||
//now make the new list
|
||||
var newMessages = [];
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
var useLinks;
|
||||
var formattedMessage = results[i].message;
|
||||
if (!appModel.AppSettingsCurrent["SkipParsing"]) {
|
||||
formattedMessage = Mojo.Format.runTextIndexer(results[i].message);
|
||||
if (formattedMessage.length < 1)
|
||||
formattedMessage = results[i].message;
|
||||
formattedMessage = this.expandAttachments(formattedMessage, results[i]);
|
||||
useLinks = this.detectURLs(results[i].message);
|
||||
}
|
||||
var MojoHTML = Mojo.Format.runTextIndexer(results[i].message);
|
||||
MojoHTML = MojoHTML.replace("file:///usr/palm/", "");
|
||||
|
||||
newMessages.push({
|
||||
uid: results[i].uid,
|
||||
sender: results[i].sender,
|
||||
message: results[i].message,
|
||||
formattedMessage: formattedMessage,
|
||||
formattedMessage: MojoHTML,
|
||||
postedFrom: results[i].postedFrom,
|
||||
links: useLinks,
|
||||
links: this.detectURLs(results[i].message),
|
||||
timestamp: this.convertTimeStamp(results[i].timestamp, true),
|
||||
likes: results[i].likes,
|
||||
attachments: results[i].attachments,
|
||||
color: "black"
|
||||
});
|
||||
}
|
||||
@@ -694,14 +601,21 @@ MainAssistant.prototype.updateChatsList = function(results) {
|
||||
for (var m = 0; m < thisWidgetSetup.model.items.length; m++) {
|
||||
for (var n = 0; n < newMessages.length; n++) {
|
||||
if (newMessages[n].uid == thisWidgetSetup.model.items[m].uid) {
|
||||
var changed = false;
|
||||
if (newMessages[n].message != thisWidgetSetup.model.items[m].message ||
|
||||
newMessages[n].likes != thisWidgetSetup.model.items[m].likes ||
|
||||
newMessages[n].color != thisWidgetSetup.model.items[m].color) {
|
||||
Mojo.Log.info("Updating message from list at position " + m);
|
||||
Mojo.Log.info("Old Message: " + JSON.stringify(thisWidgetSetup.model.items[m]));
|
||||
thisWidgetSetup.model.items[m] = newMessages[n];
|
||||
this.controller.get('chatList').mojo.noticeUpdatedItems(m, [thisWidgetSetup.model.items[m]]);
|
||||
updated = true;
|
||||
changed = true;
|
||||
Mojo.Log.info("New Message should be: " + JSON.stringify(newMessages[n]));
|
||||
Mojo.Log.info("New Message is : " + JSON.stringify(thisWidgetSetup.model.items[m]));
|
||||
}
|
||||
}
|
||||
if (changed)
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
//Insert new messages
|
||||
@@ -727,7 +641,7 @@ MainAssistant.prototype.updateChatsList = function(results) {
|
||||
if (inserted.length > 0 || updated || deleted) {
|
||||
if (inserted.length > 0) {
|
||||
if (!this.firstPoll) {
|
||||
this.doNotification();
|
||||
systemModel.PlayAlertSound(appModel.AppSettingsCurrent["AlertSound"]);
|
||||
var offset = thisWidgetSetup.model.items.length - 1;
|
||||
for (var i = 0; i < inserted.length; i++) {
|
||||
thisWidgetSetup.model.items.push(inserted[i]);
|
||||
@@ -735,6 +649,7 @@ MainAssistant.prototype.updateChatsList = function(results) {
|
||||
this.controller.get('chatList').mojo.noticeAddedItems(offset, inserted);
|
||||
} else {
|
||||
thisWidgetSetup.model.items = inserted;
|
||||
|
||||
}
|
||||
this.controller.modelChanged(thisWidgetSetup.model);
|
||||
this.scrollToBottom();
|
||||
@@ -743,8 +658,6 @@ MainAssistant.prototype.updateChatsList = function(results) {
|
||||
Mojo.Log.info("No changes to apply to list.")
|
||||
}
|
||||
this.firstPoll = false;
|
||||
//hide transmitting
|
||||
this.controller.get('imgTransmit').style.display = "none";
|
||||
|
||||
//Also clean-up MyMessage history
|
||||
for (var m = 0; m < appModel.AppSettingsCurrent["MyMessages"].length; m++) {
|
||||
@@ -759,21 +672,9 @@ MainAssistant.prototype.updateChatsList = function(results) {
|
||||
}
|
||||
}
|
||||
|
||||
//Called by Mojo once the list has been painted, gives us an opportunity to force HTML changes in the message
|
||||
//Called by Mojo once the list has been painted, gives us an opportunity to force HTML into the message
|
||||
MainAssistant.prototype.handleItemRendered = function(listWidget, itemModel, itemNode) {
|
||||
itemNode.innerHTML = this.unescapeEntities(itemNode.innerHTML);
|
||||
if (!appModel.AppSettingsCurrent["SkipParsing"]) {
|
||||
itemNode.innerHTML = this.replaceImageLinks(itemNode.innerHTML);
|
||||
itemNode.innerHTML = this.parseShareSpaceLinks(itemNode.innerHTML);
|
||||
itemNode.innerHTML = this.parseImgurLinks(itemNode.innerHTML);
|
||||
}
|
||||
if (appModel.AppSettingsCurrent["ShowEmojis"]) {
|
||||
itemNode.innerHTML = this.renderTwimoji(itemNode.innerHTML);
|
||||
}
|
||||
if (itemNode.innerHTML.indexOf("</span> </div>") != -1) {
|
||||
itemNode.innerHTML = itemModel.message;
|
||||
Mojo.Log.warn("**** EMPTY MESSAGE RENDERED! " + JSON.stringify(itemModel));
|
||||
}
|
||||
|
||||
//Hide emojis if app settings say to do so
|
||||
if (!appModel.AppSettingsCurrent["ShowEmojis"]) {
|
||||
@@ -786,7 +687,7 @@ MainAssistant.prototype.handleItemRendered = function(listWidget, itemModel, ite
|
||||
|
||||
//Used to show or hide command menu buttons
|
||||
MainAssistant.prototype.toggleCommandMenu = function(show) {
|
||||
Mojo.Log.info("Toggling command menu");
|
||||
Mojo.Log.warn("Toggling command menu");
|
||||
var stageController = Mojo.Controller.getAppController().getActiveStageController();
|
||||
if (stageController) {
|
||||
this.controller = stageController.activeScene();
|
||||
@@ -807,39 +708,17 @@ MainAssistant.prototype.toggleCommandMenu = function(show) {
|
||||
}
|
||||
|
||||
/* Helper Functions */
|
||||
MainAssistant.prototype.doNotification = function() {
|
||||
systemModel.PlayAlertSound(appModel.AppSettingsCurrent["AlertSound"]);
|
||||
if (!this.maximized)
|
||||
appModel.ShowNotificationStage();
|
||||
else {}
|
||||
}
|
||||
|
||||
MainAssistant.prototype.checkForUpdates = function() {
|
||||
if (!appModel.UpdateCheckDone) {
|
||||
//First check for old version
|
||||
var oldFound = false;
|
||||
systemModel.GetInstalledApps(function(response) {
|
||||
if (response && response.apps) {
|
||||
for (var a = 0; a < response.apps.length; a++) {
|
||||
if (response.apps[a].id == "com.notalexnoyle.simplechat") {
|
||||
oldFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldFound) {
|
||||
Mojo.Additions.ShowDialogBox("Deprecated App Found", "It looks like you have both the old and the new SimpleChat apps installed. This will cause problems with notifications. It is strongly recommended that you delete the old version of SimpleChat -- the old icon looks like this:<p align='center' style='margin:0px'><img src='assets/oldicon.png'></p>");
|
||||
} else {
|
||||
appModel.UpdateCheckDone = true;
|
||||
updaterModel.CheckForUpdate(Mojo.Controller.appInfo.appMuseumTitle, function(responseObj) {
|
||||
if (responseObj && responseObj.updateFound) {
|
||||
updaterModel.PromptUserForUpdate(function(response) {
|
||||
if (response)
|
||||
updaterModel.InstallUpdate();
|
||||
}.bind(this));
|
||||
}
|
||||
appModel.UpdateCheckDone = true;
|
||||
updaterModel.CheckForUpdate("webOS SimpleChat", function(responseObj) {
|
||||
if (responseObj && responseObj.updateFound) {
|
||||
updaterModel.PromptUserForUpdate(function(response) {
|
||||
if (response)
|
||||
updaterModel.InstallUpdate();
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this))
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,157 +752,6 @@ MainAssistant.prototype.scrollToPosition = function(scrollPos) {
|
||||
MainAssistant.prototype.unescapeEntities = function(str) {
|
||||
str = str.replace(/>/g, ">");
|
||||
str = str.replace(/</g, "<");
|
||||
str = str
|
||||
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
|
||||
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
|
||||
.replace(/^~~ (.*$)/gim, '<strike>$1</strike>')
|
||||
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
|
||||
.replace(/^\> (.*$)/gim, '<blockquote>$1</blockquote>')
|
||||
.replace(/\*\*(.*)\*\*/gim, '<b>$1</b>')
|
||||
.replace(/\*(.*?)\*/gim, '<i>$1</i>')
|
||||
.replace(/\`(.*)\`/gim, '<code>$1</code>')
|
||||
.replace(/\[(.*?)\]\((.*?)\)/gim, "<a href='$2'>$1</a>")
|
||||
return str;
|
||||
}
|
||||
|
||||
MainAssistant.prototype.renderTwimoji = function(html) {
|
||||
if (!html) return html;
|
||||
var parts = html.split(/(<[^>]+>)/g);
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
if (parts[i].indexOf("<") !== 0) {
|
||||
parts[i] = this.replaceEmojis(parts[i]);
|
||||
}
|
||||
}
|
||||
return parts.join("");
|
||||
}
|
||||
|
||||
MainAssistant.prototype.replaceEmojis = function(text) {
|
||||
if (!text) return text;
|
||||
return text.replace(this.getEmojiRegex(), function(match) {
|
||||
return this.buildTwimojiSpan(match);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
MainAssistant.prototype.buildTwimojiSpan = function(emojiText) {
|
||||
var codepoints = [];
|
||||
for (var i = 0; i < emojiText.length; i++) {
|
||||
var code = emojiText.charCodeAt(i);
|
||||
if (code >= 0xD800 && code <= 0xDBFF && i + 1 < emojiText.length) {
|
||||
var high = code;
|
||||
var low = emojiText.charCodeAt(i + 1);
|
||||
if (low >= 0xDC00 && low <= 0xDFFF) {
|
||||
code = ((high - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
codepoints.push(code.toString(16));
|
||||
}
|
||||
var className = "emoji" + codepoints.join("");
|
||||
return "<span name=\"emoji\" class=\"emoji-outer emoji-sizer\"><span class=\"emoji-inner " + className + "\">" + emojiText + "</span></span>";
|
||||
}
|
||||
|
||||
MainAssistant.prototype.getEmojiRegex = function() {
|
||||
if (this.emojiRegex) {
|
||||
return this.emojiRegex;
|
||||
}
|
||||
var basicEmoji = "[\\u203C\\u2049\\u2122\\u2139\\u2194-\\u2199\\u21A9-\\u21AA\\u231A-\\u231B\\u2328\\u23CF\\u23E9-\\u23F3\\u23F8-\\u23FA\\u24C2\\u25AA-\\u25FE\\u2600-\\u27BF\\u2934-\\u2935\\u2B05-\\u2B55\\u3030\\u303D\\u3297\\u3299]";
|
||||
var surrogateEmoji = "[\\uD83C-\\uDBFF][\\uDC00-\\uDFFF]";
|
||||
var emojiChar = "(?:" + basicEmoji + "|" + surrogateEmoji + ")";
|
||||
var variation = "[\\uFE0E\\uFE0F]?";
|
||||
var modifier = "(?:\\uD83C[\\uDFFB-\\uDFFF])?";
|
||||
var zwj = "(?:\\u200D" + emojiChar + variation + modifier + ")*";
|
||||
var keycap = "[#*0-9]\\uFE0F?\\u20E3";
|
||||
var flag = "\\uD83C[\\uDDE6-\\uDDFF]\\uD83C[\\uDDE6-\\uDDFF]";
|
||||
this.emojiRegex = new RegExp(flag + "|" + keycap + "|" + emojiChar + variation + modifier + zwj, "g");
|
||||
return this.emojiRegex;
|
||||
}
|
||||
|
||||
MainAssistant.prototype.replaceImageLinks = function(str) {
|
||||
if (typeof btoa === 'undefined')
|
||||
return str;
|
||||
|
||||
var urlBase = serviceModel.makeServiceUrl(this.serviceEndpointBase, "image.php") + "?";
|
||||
|
||||
var pattern = /href=\"(http)?:?(\/\/[^"']*\.(?:png|jpg|jpeg|gif|png|svg))/g;
|
||||
str = str.replace(pattern, function(match, protocol, url) {
|
||||
return "href=\"" + urlBase + btoa("http:" + url);
|
||||
});
|
||||
|
||||
var pattern = /href=\"(https)?:?(\/\/[^"']*\.(?:png|jpg|jpeg|gif|png|svg))/g;
|
||||
str = str.replace(pattern, function(match, protocol, url) {
|
||||
return "href=\"" + urlBase + btoa("https:" + url);
|
||||
});
|
||||
return str;
|
||||
}
|
||||
|
||||
MainAssistant.prototype.parseShareSpaceLinks = function(str) {
|
||||
if (appModel.AppSettingsCurrent["ShowWOSAThumbs"] == undefined) {
|
||||
Mojo.Log.warn("Thumbnail setting missing, adding with default value: " + appModel.AppSettingsDefaults["ShowWOSAThumbs"]);
|
||||
appModel.AppSettingsCurrent["ShowWOSAThumbs"] = appModel.AppSettingsDefaults["ShowWOSAThumbs"];
|
||||
appModel.SaveSettings();
|
||||
}
|
||||
if (appModel.AppSettingsCurrent["ShowWOSAThumbs"] == true) {
|
||||
if (str.indexOf("share.wosa.link") != -1) {
|
||||
Mojo.Log.info("Found WOSA link to parse! " + str);
|
||||
if (str.indexOf("download.php")) {
|
||||
str = str.replace("download.php", "image.php");
|
||||
var linkPortion = str.split("image.php?");
|
||||
if (Array.isArray(linkPortion) && linkPortion.length > 1) {
|
||||
linkPortion = linkPortion[1];
|
||||
linkPortion = linkPortion.replace("\"", " ");
|
||||
linkPortion = linkPortion.replace("'", " ");
|
||||
linkPortion = linkPortion.replace("<", " ");
|
||||
linkPortion = linkPortion.replace(">", " ");
|
||||
linkPortion = linkPortion.split(" ");
|
||||
linkPortion = linkPortion[0];
|
||||
if (str.indexOf("t.php") != -1) {
|
||||
linkPortion = "http://share.wosa.link/tthumb.php?" + linkPortion;
|
||||
} else {
|
||||
linkPortion = "http://share.wosa.link/ithumb.php?" + linkPortion;
|
||||
}
|
||||
var thumbnail = "<img src=\"" + linkPortion + "\" style=\"float:right; width: 64px; height: 64px; margin-top: -2px;\"> "
|
||||
str = thumbnail + str;
|
||||
Mojo.Log.warn("Parsed WOSA link html: " + str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
MainAssistant.prototype.parseImgurLinks = function(str) {
|
||||
var newStr = str;
|
||||
if (str.indexOf("https://imgur.com") != -1) {
|
||||
Mojo.Log.error("Found Imgur link to parse!");
|
||||
var urlBase = serviceModel.makeServiceUrl(this.serviceEndpointBase, "imgurproxy.php");
|
||||
urlBase = urlBase + "?maxwidth=" + Mojo.Environment.DeviceInfo.screenWidth + "&album=";
|
||||
|
||||
links = this.detectURLs(str);
|
||||
for (var l=0;l<links.length;l++) {
|
||||
if (links[l].indexOf("imgur.com") != -1 && links[l].indexOf("imgurproxy.php") == -1) {
|
||||
var newLink = links[l].replace(links[l], urlBase + links[l]);
|
||||
Mojo.Log.error("Replaced Imgur link " + links[l] + " with " + newLink);
|
||||
newStr = newStr.replace(links[l], newLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newStr;
|
||||
}
|
||||
|
||||
MainAssistant.prototype.expandAttachments = function(str, itemData) {
|
||||
var linkBase = serviceModel.makeServiceUrl(this.serviceEndpointBase, "attachment.php?");
|
||||
var imgBase = serviceModel.makeServiceUrl(this.serviceEndpointBase, "thumb.php") + "?image=";
|
||||
var supportedAttachments = ['jpg', 'jpeg', 'png', 'gif'];
|
||||
if (itemData.attachments) {
|
||||
str += "<br>";
|
||||
Mojo.Log.info("Attachments found: " + itemData.attachments.length);
|
||||
for (var i=0;i<itemData.attachments.length;i++) {
|
||||
if (supportedAttachments.indexOf(itemData.attachments[i].extension.toLowerCase()) != -1) {
|
||||
str += "<a href='" + linkBase + itemData.attachments[i].filename + "'>";
|
||||
str += "<img src='" + imgBase + itemData.attachments[i].filename + "&size=64'></a>";
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -1046,45 +774,19 @@ MainAssistant.prototype.detectURLs = function(message) {
|
||||
|
||||
MainAssistant.prototype.disableUI = function(statusValue) {
|
||||
//start spinner
|
||||
if (!this.spinnerWorkModel.spinning) {
|
||||
this.spinnerWorkModel.spinning = true;
|
||||
this.controller.modelChanged(this.spinnerWorkModel);
|
||||
if (!this.spinnerModel.spinning) {
|
||||
this.spinnerModel.spinning = true;
|
||||
this.controller.modelChanged(this.spinnerModel);
|
||||
}
|
||||
}
|
||||
|
||||
MainAssistant.prototype.enableUI = function() {
|
||||
//stop spinner
|
||||
this.spinnerWorkModel.spinning = false;
|
||||
this.controller.modelChanged(this.spinnerWorkModel);
|
||||
this.spinnerModel.spinning = false;
|
||||
this.controller.modelChanged(this.spinnerModel);
|
||||
this.controller.get('txtMessage').mojo.focus();
|
||||
}
|
||||
|
||||
MainAssistant.prototype.initDefaultSettings = function() {
|
||||
//Set an alert sound
|
||||
if (!appModel.AppSettingsCurrent["AlertSound"] || appModel.AppSettingsCurrent["AlertSound"] == "") {
|
||||
appModel.AppSettingsCurrent["AlertSound"] = "Subtle (short)";
|
||||
}
|
||||
//Check for Enter option
|
||||
if (appModel.AppSettingsCurrent["EnterSubmits"] == null) {
|
||||
Mojo.Log.info("Adding EnterSubmits setting with default value!")
|
||||
appModel.AppSettingsCurrent["EnterSubmits"] = appModel.AppSettingsDefaults["EnterSubmits"];
|
||||
appModel.SaveSettings();
|
||||
}
|
||||
//Check for Emoji option
|
||||
if (appModel.AppSettingsCurrent["ShowEmojis"] == null) {
|
||||
Mojo.Log.info("Adding Emoji setting with default value!")
|
||||
appModel.AppSettingsCurrent["ShowEmojis"] = appModel.AppSettingsDefaults["ShowEmojis"];
|
||||
appModel.SaveSettings();
|
||||
}
|
||||
//Init Message memory
|
||||
if (!appModel.AppSettingsCurrent["MyMessages"]) {
|
||||
appModel.AppSettingsCurrent["MyMessages"] = [];
|
||||
}
|
||||
if (appModel.AppSettingsCurrent["LastKnownMessages"]) { //This was the old way, clean it up
|
||||
appModel.AppSettingsCurrent["LastKnownMessages"] = null;
|
||||
}
|
||||
}
|
||||
|
||||
MainAssistant.prototype.rememberLastMessage = function() {
|
||||
var thisWidgetSetup = this.controller.getWidgetSetup("chatList");
|
||||
if (thisWidgetSetup.model.items.length > 0) {
|
||||
@@ -1095,44 +797,26 @@ MainAssistant.prototype.rememberLastMessage = function() {
|
||||
|
||||
/* Mojo Lifecycle Stuff */
|
||||
MainAssistant.prototype.activateWindow = function(event) {
|
||||
Mojo.Log.info("SimpleChat being maximized!");
|
||||
this.maximized = true;
|
||||
this.rememberLastMessage();
|
||||
appModel.CloseNotificationStage();
|
||||
//If we were re-launched with some share text, insert that
|
||||
if (appModel.LaunchQuery != "") {
|
||||
Mojo.Log.info("using launch action: " + appModel.LaunchQuery);
|
||||
this.controller.get('txtMessage').mojo.setValue(appModel.LaunchQuery);
|
||||
appModel.LaunchQuery = "";
|
||||
}
|
||||
};
|
||||
|
||||
MainAssistant.prototype.deactivateWindow = function(event) {
|
||||
Mojo.Log.info("SimpleChat being minimized!");
|
||||
this.maximized = false;
|
||||
this.rememberLastMessage();
|
||||
};
|
||||
|
||||
MainAssistant.prototype.deactivate = function(event) {
|
||||
/* remove any event handlers you added in activate and do any other cleanup that should happen before
|
||||
this scene is popped or another scene is pushed on top */
|
||||
Mojo.Log.info("Main scene deactivating " + Mojo.Controller.appInfo.id);
|
||||
this.maximized = false;
|
||||
Mojo.Log.info("Main scene deactivated " + Mojo.Controller.appInfo.id);
|
||||
|
||||
//Get ready for background sync
|
||||
Mojo.Log.info("Switching to background sync");
|
||||
//Remember last known messages
|
||||
this.pausePollingServer();
|
||||
this.rememberLastMessage();
|
||||
systemModel.ClearSystemAlarm("SimpleChat");
|
||||
if (appModel.AppSettingsCurrent["BackgroundUpdate"] && appModel.AppSettingsCurrent["BackgroundUpdate"] != "" && appModel.AppSettingsCurrent["BackgroundUpdate"] != -1)
|
||||
systemModel.SetSystemAlarmRelative("SimpleChat", appModel.AppSettingsCurrent["BackgroundUpdate"]);
|
||||
|
||||
//Detach UI handlers
|
||||
//Detach UI
|
||||
Mojo.Event.stopListening(this.controller.get("chatList"), Mojo.Event.listTap, this.handleListClick);
|
||||
this.controller.window.removeEventListener('resize', this.orientationChanged);
|
||||
//this.controller.document.getElementById("divComposeTitle").removeEventListener("click", this.toggleCommandMenu.bind(this));
|
||||
this.controller.document.getElementById("spanCompose").removeEventListener("click", this.toggleCommandMenu.bind(this));
|
||||
this.controller.document.getElementById("imgTwisty").removeEventListener("click", this.toggleCommandMenu.bind(this));
|
||||
this.controller.document.getElementById("divComposeTitle").removeEventListener("click", this.toggleCommandMenu.bind(this));
|
||||
|
||||
Mojo.Event.stopListening(this.controller.stageController.document, Mojo.Event.stageActivate, this.activateWindow);
|
||||
Mojo.Event.stopListening(this.controller.stageController.document, Mojo.Event.stageDeactivate, this.deactivateWindow);
|
||||
@@ -1143,4 +827,4 @@ MainAssistant.prototype.cleanup = function(event) {
|
||||
a result of being popped off the scene stack */
|
||||
var appController = Mojo.Controller.getAppController();
|
||||
appController.closeAllStages();
|
||||
};
|
||||
};
|
||||
@@ -8,16 +8,6 @@ function PreferencesAssistant() {
|
||||
PreferencesAssistant.prototype.setup = function() {
|
||||
/* setup widgets here */
|
||||
|
||||
//Theme picker
|
||||
this.controller.setupWidget("listThemePreference",
|
||||
{label: $L({value:"Theme", key:"theme"}),
|
||||
labelPlacement: Mojo.Widget.labelPlacementLeft,
|
||||
choices: [
|
||||
{label: $L({value:"Light", key:"themeLight"}), value: "palm-default"},
|
||||
{label: $L({value:"Dark", key:"themeDark"}), value: "palm-dark"},
|
||||
{label: $L({value:"System Pref", key:"themeSystem"}), value: "system-theme"}
|
||||
]},
|
||||
{ value: appModel.AppSettingsCurrent["ThemePreference"] });
|
||||
//Timeout picker
|
||||
this.controller.setupWidget("listForegroundUpdate",
|
||||
this.attributes = {
|
||||
@@ -25,7 +15,6 @@ PreferencesAssistant.prototype.setup = function() {
|
||||
choices: [
|
||||
{ label: "5 seconds", value: 5000 },
|
||||
{ label: "10 seconds", value: 10000 },
|
||||
{ label: "20 seconds", value: 20000 },
|
||||
{ label: "30 second", value: 30000 },
|
||||
{ label: "1 minute", value: 60000 },
|
||||
{ label: "2 minutes", value: 120000 },
|
||||
@@ -47,14 +36,9 @@ PreferencesAssistant.prototype.setup = function() {
|
||||
label: $L("Background Update"),
|
||||
choices: [
|
||||
{ label: "Off", value: -1 },
|
||||
{ label: "5 minutes", value: "00:05:00" },
|
||||
{ label: "10 minutes", value: "00:10:00" },
|
||||
{ label: "15 minutes", value: "00:15:00" },
|
||||
{ label: "30 minutes", value: "00:30:00" },
|
||||
{ label: "45 minutes", value: "00:45:00" },
|
||||
{ label: "1 Hour", value: "01:00:00" },
|
||||
{ label: "2 Hours", value: "02:00:00" },
|
||||
{ label: "3 Hours", value: "02:00:00" },
|
||||
{ label: "5 Hours", value: "05:00:00" },
|
||||
]
|
||||
},
|
||||
@@ -63,21 +47,6 @@ PreferencesAssistant.prototype.setup = function() {
|
||||
disabled: false
|
||||
}
|
||||
);
|
||||
//Enter Action listEnterSubmits
|
||||
this.controller.setupWidget("listEnterSubmits",
|
||||
this.attributes = {
|
||||
label: $L("Enter Submits"),
|
||||
choices: [
|
||||
{ label: "Never", value: "never" },
|
||||
{ label: "Collapsed", value: "collapsed" },
|
||||
{ label: "Always", value: "always" }
|
||||
]
|
||||
},
|
||||
this.model = {
|
||||
value: appModel.AppSettingsCurrent["EnterSubmits"],
|
||||
disabled: false
|
||||
}
|
||||
);
|
||||
//Emoji toggle
|
||||
this.controller.setupWidget("toggleEmojis",
|
||||
this.attributes = {
|
||||
@@ -89,28 +58,6 @@ PreferencesAssistant.prototype.setup = function() {
|
||||
disabled: false
|
||||
}
|
||||
);
|
||||
//Link toggle
|
||||
this.controller.setupWidget("toggleParsing",
|
||||
this.attributes = {
|
||||
trueValue: true,
|
||||
falseValue: false
|
||||
},
|
||||
this.model = {
|
||||
value: appModel.AppSettingsCurrent["SkipParsing"],
|
||||
disabled: false
|
||||
}
|
||||
);
|
||||
//Thumbnail toggle
|
||||
this.controller.setupWidget("toggleThumbs",
|
||||
this.attributes = {
|
||||
trueValue: true,
|
||||
falseValue: false
|
||||
},
|
||||
this.model = {
|
||||
value: appModel.AppSettingsCurrent["ShowWOSAThumbs"],
|
||||
disabled: false
|
||||
}
|
||||
);
|
||||
//Setup sound picker
|
||||
this.soundChoices = {
|
||||
choices: [
|
||||
@@ -197,13 +144,9 @@ PreferencesAssistant.prototype.setup = function() {
|
||||
this.controller.setupWidget(Mojo.Menu.appMenu, this.appMenuAttributes, this.appMenuModel);
|
||||
|
||||
/* add event handlers to listen to events from widgets */
|
||||
Mojo.Event.listen(this.controller.get("listThemePreference"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
Mojo.Event.listen(this.controller.get("listForegroundUpdate"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
Mojo.Event.listen(this.controller.get("listBackgroundUpdate"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
Mojo.Event.listen(this.controller.get("toggleEmojis"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
Mojo.Event.listen(this.controller.get("toggleParsing"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
Mojo.Event.listen(this.controller.get("toggleThumbs"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
Mojo.Event.listen(this.controller.get("listEnterSubmits"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
Mojo.Event.listen(this.controller.get("listAlertSound"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
Mojo.Event.listen(this.controller.get("txtClientAPI"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
Mojo.Event.listen(this.controller.get("txtEndpointURL"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
|
||||
@@ -226,17 +169,8 @@ PreferencesAssistant.prototype.handleValueChange = function(event) {
|
||||
|
||||
Mojo.Log.info(event.srcElement.id + " value changed to " + event.value);
|
||||
switch (event.srcElement.id) {
|
||||
case "listThemePreference":
|
||||
appModel.AppSettingsCurrent["ThemePreference"] = event.value;
|
||||
appModel.SetThemePreference(this.controller);
|
||||
break;
|
||||
case "toggleParsing":
|
||||
Mojo.Controller.getAppController().showBanner({ messageText: "Re-launch app to apply this setting" }, "", "");
|
||||
break;
|
||||
case "toggleEmojis":
|
||||
Mojo.Controller.getAppController().showBanner({ messageText: "Re-launch app to apply this setting" }, "", "");
|
||||
break;
|
||||
case "toggleThumbs":
|
||||
Mojo.Log.info("Should show banner!");
|
||||
Mojo.Controller.getAppController().showBanner({ messageText: "Re-launch app to apply this setting" }, "", "");
|
||||
break;
|
||||
case "listAlertSound":
|
||||
@@ -340,17 +274,17 @@ PreferencesAssistant.prototype.okClick = function(event) {
|
||||
PreferencesAssistant.prototype.deactivate = function(event) {
|
||||
/* remove any event handlers you added in activate and do any other cleanup that should happen before
|
||||
this scene is popped or another scene is pushed on top */
|
||||
Mojo.Event.stopListening(this.controller.get("listThemePreference"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
|
||||
systemModel.ClearSystemAlarm("SimpleChat");
|
||||
if (appModel.AppSettingsCurrent["BackgroundUpdate"] && appModel.AppSettingsCurrent["BackgroundUpdate"] != "" && appModel.AppSettingsCurrent["BackgroundUpdate"] != -1)
|
||||
systemModel.SetSystemAlarmRelative("SimpleChat", appModel.AppSettingsCurrent["BackgroundUpdate"]);
|
||||
|
||||
Mojo.Event.stopListening(this.controller.get("listForegroundUpdate"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("listBackgroundUpdate"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("toggleEmojis"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("toggleParsing"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("toggleThumbs"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("listEnterSubmits"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("listAlertSound"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("txtClientAPI"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("toggleClientAPI"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("toggleCustomEndPoint"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("txtClientAPI"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("txtEndpointURL"), Mojo.Event.propertyChange, this.handleValueChange);
|
||||
Mojo.Event.stopListening(this.controller.get("btnOK"), Mojo.Event.tap, this.okClick.bind(this));
|
||||
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
function VersionAssistant(startup) {
|
||||
this.isStartup = startup;
|
||||
|
||||
// on first start, this message is displayed, along with the current version message from below
|
||||
this.startupMessage = $L("<img src='icon.png' style='float:left; margin-right:8px'>Welcome to SimpleChat! We're so excited you're here chatting with us 10 years after this platform was supposed to have died!<br>You can also join this chat from Discord: <a href='discord.gg/7NrrT8exrn'>discord.gg/7NrrT8exrn</a> or view the log on the web: <a href='http://chat.webosarchive.com'>chat.webosarchive.com</a>");
|
||||
|
||||
//New Features
|
||||
this.changelog = [{
|
||||
version: "Version 1.1.3",
|
||||
detail: [
|
||||
"Bug fixes and general maintenance"
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.1.2",
|
||||
detail: [
|
||||
"Show/Hide the Command menu buttons by tapping the Compose area title bar",
|
||||
"Enable/Disable Discord Emojis in Preferences",
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.1.1",
|
||||
detail: [
|
||||
"Improved Discord integration, including showing Emojis!<span class='emoji-outer emoji-sizer'><span class='emoji-inner emoji1f388'></span></span>",
|
||||
"Now with a smaller emoji file!",
|
||||
"Improved timeout logic.",
|
||||
"Trying different background sync logic."
|
||||
]
|
||||
}];
|
||||
|
||||
// setup command menu
|
||||
this.cmdMenuModel = {
|
||||
visible: false,
|
||||
items: [
|
||||
{},
|
||||
{
|
||||
label: $L("OK! Let's Go..."),
|
||||
command: 'do-continue'
|
||||
},
|
||||
{}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
VersionAssistant.prototype.setup = function() {
|
||||
this.titleElement = this.controller.get('title');
|
||||
this.dataElement = this.controller.get('data');
|
||||
|
||||
this.titleElement.innerHTML = $L('Version Info');
|
||||
|
||||
var html = '';
|
||||
html += '<div style="margin: 2px 12px 12px 12px">' + this.startupMessage + '</div>';
|
||||
|
||||
for (var i = 0; i < this.changelog.length; i++) {
|
||||
html += Mojo.View.render({ object: { title: this.changelog[i].version }, template: 'version/rowDivider' });
|
||||
html += '<ul>';
|
||||
|
||||
for (var j = 0; j < this.changelog[i].detail.length; j++) {
|
||||
html += '<li>' + this.changelog[i].detail[j] + '</li>';
|
||||
}
|
||||
html += '</ul>';
|
||||
}
|
||||
|
||||
// set data
|
||||
this.dataElement.innerHTML = html;
|
||||
|
||||
// setup menu
|
||||
this.controller.setupWidget(Mojo.Menu.appMenu, { omitDefaultItems: true }, { visible: false });
|
||||
|
||||
//if (this.isStartup) {
|
||||
// set command menu
|
||||
this.controller.setupWidget(Mojo.Menu.commandMenu, { menuClass: 'no-fade' }, this.cmdMenuModel);
|
||||
//}
|
||||
};
|
||||
|
||||
VersionAssistant.prototype.activate = function(event) {
|
||||
this.timer = this.controller.window.setTimeout(this.showContinue.bind(this), 2 * 1000);
|
||||
};
|
||||
VersionAssistant.prototype.deactivate = function(event) {};
|
||||
VersionAssistant.prototype.cleanup = function(event) {};
|
||||
|
||||
VersionAssistant.prototype.showContinue = function() {
|
||||
// show the command menu
|
||||
this.controller.setMenuVisible(Mojo.Menu.commandMenu, true);
|
||||
};
|
||||
|
||||
VersionAssistant.prototype.handleCommand = function(event) {
|
||||
if (event.type == Mojo.Event.command) {
|
||||
switch (event.command) {
|
||||
case 'do-continue':
|
||||
this.controller.stageController.popScene();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2,18 +2,14 @@
|
||||
Mojo Additions
|
||||
Version 0.3e
|
||||
Created: 2018
|
||||
Author: Jon W
|
||||
Author: Jonathan Wise
|
||||
License: MIT
|
||||
Description: Functions I use often, that probably should have been part of Mojo.
|
||||
They either fix bugs in Mojo or make it easier to use.
|
||||
*/
|
||||
|
||||
//** Note: If you synced this file from a common repository, local edits may be over-written! */
|
||||
|
||||
this.Additions = function() {}
|
||||
|
||||
console.log("** Mojo Additions loaded **");
|
||||
|
||||
Additions.ShowDialogBox = function(title, message) {
|
||||
var stageController = Mojo.Controller.getAppController().getActiveStageController();
|
||||
if (stageController) {
|
||||
@@ -24,6 +20,7 @@ Additions.ShowDialogBox = function(title, message) {
|
||||
title: title,
|
||||
message: message,
|
||||
choices: [{ label: 'OK', value: 'OK' }],
|
||||
preventCancel: true,
|
||||
allowHTMLMessage: true
|
||||
});
|
||||
}
|
||||
@@ -65,16 +62,6 @@ Additions.SetWidgetLabel = function(widgetName, newvalue) {
|
||||
}
|
||||
}
|
||||
|
||||
Additions.GetWidgetLabel = function(widgetName) {
|
||||
var stageController = Mojo.Controller.getAppController().getActiveStageController();
|
||||
if (stageController) {
|
||||
this.controller = stageController.activeScene();
|
||||
|
||||
var thisWidgetModel = this.controller.getWidgetSetup(widgetName).model;
|
||||
return thisWidgetModel.label;
|
||||
}
|
||||
}
|
||||
|
||||
Additions.SetToggleState = function(widgetName, toggledValue) {
|
||||
var stageController = Mojo.Controller.getAppController().getStageController("");
|
||||
if (stageController) {
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
App Model
|
||||
Version 0.4
|
||||
Created: 2018
|
||||
Author: Jonathan Wise
|
||||
License: MIT
|
||||
Description: Common functions for webOS apps, particularly for managing persisted options in cookies
|
||||
*/
|
||||
|
||||
var AppModel = function() {
|
||||
//Define your default scene (needed for settings management)
|
||||
this.DefaultScene = "main";
|
||||
|
||||
//Define your app-wide, non-persisted settings here
|
||||
this.UpdateCheckDone = false;
|
||||
this.LaunchQuery = "";
|
||||
this.ServiceEndpointBase = "http://chat.webosarchive.com/";
|
||||
this.ClientId = secrets.clientid;
|
||||
this.LastMessageSelected = null;
|
||||
|
||||
//Define your app preferences (to be saved by OS)
|
||||
this.AppSettingsCurrent = null;
|
||||
this.AppSettingsDefaults = {
|
||||
ForegroundUpdate: 10000,
|
||||
BackgroundUpdate: "00:30:00",
|
||||
AlertSound: "Subtle (short)",
|
||||
ShowEmojis: true,
|
||||
UseClientAPIKey: false,
|
||||
UseCustomEndpoint: false,
|
||||
ClientAPIKey: "",
|
||||
EndpointURL: "",
|
||||
SenderName: "webOS User",
|
||||
FirstRun: true,
|
||||
MyMessages: null,
|
||||
LastKnownMessage: null,
|
||||
LastVersionRun: 0
|
||||
};
|
||||
}
|
||||
|
||||
//You probably don't need to change the below functions since they all work against the Cookie defaults you defined above.
|
||||
// LoadSettings: call when your app starts, or you want to load previously persisted options.
|
||||
// SaveSettings: call any time you want to persist an option.
|
||||
// ResetSettings: call if you want to forget stored settings and return to defaults. Your default scene will be popped and re-pushed.
|
||||
AppModel.prototype.LoadSettings = function(safe) {
|
||||
this.AppSettingsCurrent = this.AppSettingsDefaults;
|
||||
var loadSuccess = false;
|
||||
var settingsCookie = new Mojo.Model.Cookie("settings");
|
||||
try {
|
||||
appSettings = settingsCookie.get();
|
||||
if ((typeof appSettings == "undefined" || appSettings == null) || (safe && !this.checkSettingsValid(appSettings))) {
|
||||
Mojo.Log.warn("** Using first run default settings");
|
||||
} else {
|
||||
Mojo.Log.info("** Using cookie settings!");
|
||||
this.loadCookieIntoCurrent(appSettings);
|
||||
loadSuccess = true;
|
||||
}
|
||||
} catch (ex) {
|
||||
settingsCookie.put(null);
|
||||
Mojo.Log.error("** Settings cookie were corrupt and have been purged!");
|
||||
Mojo.Log.error(ex);
|
||||
}
|
||||
return loadSuccess;
|
||||
}
|
||||
|
||||
AppModel.prototype.loadCookieIntoCurrent = function(cookieSettings) {
|
||||
this.AppSettingsCurrent = cookieSettings;
|
||||
}
|
||||
|
||||
AppModel.prototype.checkSettingsValid = function(loadedSettings) {
|
||||
var retValue = true;
|
||||
for (var key in this.AppSettingsDefaults) {
|
||||
if (typeof loadedSettings[key] === undefined || loadedSettings[key] == null) {
|
||||
Mojo.Log.warn("** An expected saved setting, " + key + ", was null or undefined.");
|
||||
retValue = false;
|
||||
}
|
||||
if (typeof loadedSettings[key] !== typeof this.AppSettingsDefaults[key]) {
|
||||
Mojo.Log.warn("** A saved setting, " + key + ", was of type " + typeof(loadedSettings[key]) + " but expected type " + typeof(this.AppSettingsDefaults[key]));
|
||||
retValue = false;
|
||||
}
|
||||
if (typeof this.AppSettingsDefaults[key] === "string" && this.AppSettingsDefaults[key].indexOf(this.BaseDateString) != -1 && loadedSettings[key].indexOf(this.BaseDateString)) {
|
||||
Mojo.Log.warn("** A saved setting could not be compared to an expected date value.");
|
||||
retValue = false;
|
||||
}
|
||||
if (typeof this.AppSettingsDefaults[key] === "string" && (this.AppSettingsDefaults[key] == "false" || this.AppSettingsDefaults[key] == "true")) {
|
||||
if (loadedSettings[key] != "false" && loadedSettings[key] != "true") {
|
||||
Mojo.Log.warn("** A saved setting did not have the expected boolean value.");
|
||||
retValue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
AppModel.prototype.SaveSettings = function() {
|
||||
var settingsCookie = new Mojo.Model.Cookie("settings");
|
||||
Mojo.Log.info("Saving settings as: " + JSON.stringify(appModel.AppSettingsCurrent));
|
||||
Mojo.Log.info("Default settings at Save time are: " + JSON.stringify(appModel.AppSettingsDefaults));
|
||||
|
||||
settingsCookie.put(appModel.AppSettingsCurrent);
|
||||
}
|
||||
|
||||
AppModel.prototype.ResetSettings = function() {
|
||||
Mojo.Log.info("resetting settings");
|
||||
//Tell main scene to drop settings
|
||||
this.AppSettingsCurrent = this.AppSettingsDefaults;
|
||||
this.SaveSettings();
|
||||
Mojo.Log.info("settings have been reset");
|
||||
|
||||
var stageController = Mojo.Controller.getAppController().getActiveStageController();
|
||||
stageController.popScene(this.DefaultScene);
|
||||
Mojo.Log.info("closed default scene");
|
||||
|
||||
//Restart main scene
|
||||
stageController.pushScene(this.DefaultScene);
|
||||
Mojo.Log.info("re-opened default scene");
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
var ServiceModel = function() {
|
||||
|
||||
};
|
||||
|
||||
ServiceModel.prototype.getChats = function(serviceBase, callback) {
|
||||
serviceURL = serviceBase + "get-chat.php";
|
||||
Mojo.Log.info("Trying to get chats from: " + serviceURL);
|
||||
this.retVal = "";
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open("GET", serviceURL);
|
||||
xmlhttp.send();
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||
if (callback)
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
ServiceModel.prototype.postChat = function(useSender, useMessage, serviceBase, clientId, callback) {
|
||||
serviceURL = serviceBase + "post-chat.php";
|
||||
var msgToPost = {
|
||||
sender: useSender,
|
||||
message: useMessage
|
||||
}
|
||||
Mojo.Log.info("Posting chat to: " + serviceURL);
|
||||
Mojo.Log.info(JSON.stringify(msgToPost));
|
||||
|
||||
this.retVal = "";
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open("POST", serviceURL);
|
||||
xmlhttp.setRequestHeader("Client-Id", clientId);
|
||||
xmlhttp.timeout = 2000;
|
||||
xmlhttp.send(JSON.stringify(msgToPost));
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
Mojo.Log.info("ready state: " + xmlhttp.readyState);
|
||||
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||
if (callback)
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}.bind(this);
|
||||
xmlhttp.ontimeout = function() {
|
||||
callback();
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
ServiceModel.prototype.editChat = function(useSender, useMessage, uid, editKey, serviceBase, clientId, callback) {
|
||||
serviceURL = serviceBase + "edit-chat.php";
|
||||
var msgToPost = {
|
||||
sender: useSender,
|
||||
message: useMessage,
|
||||
uid: uid,
|
||||
editKey: editKey
|
||||
}
|
||||
Mojo.Log.info("Edit chat to: " + serviceURL);
|
||||
Mojo.Log.info(JSON.stringify(msgToPost));
|
||||
|
||||
this.retVal = "";
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open("POST", serviceURL);
|
||||
xmlhttp.setRequestHeader("Client-Id", clientId);
|
||||
xmlhttp.send(JSON.stringify(msgToPost));
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||
if (callback)
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
ServiceModel.prototype.likeChat = function(uid, serviceBase, clientId, callback) {
|
||||
serviceURL = serviceBase + "like-chat.php";
|
||||
var msgToPost = {
|
||||
uid: uid,
|
||||
like: "+1"
|
||||
}
|
||||
Mojo.Log.info("Like chat to: " + serviceURL);
|
||||
Mojo.Log.info(JSON.stringify(msgToPost));
|
||||
|
||||
this.retVal = "";
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.open("POST", serviceURL);
|
||||
xmlhttp.setRequestHeader("Client-Id", clientId);
|
||||
xmlhttp.send(JSON.stringify(msgToPost));
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
||||
if (callback)
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
@@ -1,42 +1,16 @@
|
||||
/*
|
||||
System Model
|
||||
Version 1.6
|
||||
Created: 2022
|
||||
Author: Jon W
|
||||
Version 1.2
|
||||
Created: 2021
|
||||
Author: Jonathan Wise
|
||||
License: MIT
|
||||
Description: A generic and re-usable model for accessing webOS system features more easily
|
||||
Privileged functions can only be called if your App ID starts with com.palm
|
||||
*/
|
||||
|
||||
//** Note: If you synced this file from a common repository, local edits may be over-written! */
|
||||
|
||||
var SystemModel = function() {
|
||||
var SystemModel = function() {
|
||||
|
||||
};
|
||||
SystemModel.WOSAPrefs = {};
|
||||
|
||||
//You should probably use Mojo.Environment.DeviceInfo for this
|
||||
// http://sdk.webosarchive.org/docs/docs.html#reference/mojo/classes/mojo-environment.html#summary
|
||||
SystemModel.prototype.DetectDevice = function() {
|
||||
//find out what kind of device this is
|
||||
var deviceType;
|
||||
if (Mojo.Environment.DeviceInfo.platformVersionMajor >= 3) {
|
||||
deviceType = "TouchPad";
|
||||
Mojo.Log.info("Device detected as TouchPad");
|
||||
} else {
|
||||
if (window.screen.width == 800 || window.screen.height == 800) {
|
||||
deviceType = "Pre3";
|
||||
Mojo.Log.info("Device detected as Pre3");
|
||||
} else if ((window.screen.width == 480 || window.screen.height == 480) && (window.screen.width == 320 || window.screen.height == 320)) {
|
||||
deviceType = "Pre";
|
||||
Mojo.Log.info("Device detected as Pre or Pre2");
|
||||
} else {
|
||||
deviceType = "Tiny";
|
||||
Mojo.Log.info("Device detected as Pixi or Veer");
|
||||
}
|
||||
}
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
//Create a named System Alarm using relative time ("in")
|
||||
SystemModel.prototype.SetSystemAlarmRelative = function(alarmName, alarmTime) {
|
||||
@@ -108,20 +82,15 @@ SystemModel.prototype.ClearSystemAlarm = function(alarmName) {
|
||||
|
||||
//Allow the display to sleep
|
||||
SystemModel.prototype.AllowDisplaySleep = function(stageController) {
|
||||
try {
|
||||
if (!stageController)
|
||||
stageController = Mojo.Controller.getAppController().getActiveStageController();
|
||||
if (!stageController)
|
||||
stageController = Mojo.Controller.getAppController().getActiveStageController();
|
||||
|
||||
//Tell the System it doesn't have to stay awake any more
|
||||
Mojo.Log.info("Allowing display sleep");
|
||||
//Tell the System it doesn't have to stay awake any more
|
||||
Mojo.Log.info("Allowing display sleep");
|
||||
|
||||
stageController.setWindowProperties({
|
||||
blockScreenTimeout: false
|
||||
});
|
||||
} catch(e) {
|
||||
//If the stage has already gone away, this function will return an error
|
||||
// But it doesn't matter because webOS will perform this function anyway during stage clean-up
|
||||
}
|
||||
stageController.setWindowProperties({
|
||||
blockScreenTimeout: false
|
||||
});
|
||||
}
|
||||
|
||||
//Prevent the display from sleeping
|
||||
@@ -139,7 +108,6 @@ SystemModel.prototype.PreventDisplaySleep = function(stageController) {
|
||||
|
||||
//Show a notification window in its own small stage
|
||||
// Launches with sound: pass true for default, false for no sound, or pass the path to a specific sound file
|
||||
// Note: This implementation will not work for pure background notifications as it requires the app to be active
|
||||
SystemModel.prototype.ShowNotificationStage = function(stageName, sceneName, heightToUse, sound, vibrate) {
|
||||
Mojo.Log.info("Showing notification stage.");
|
||||
//Determine what sound to use
|
||||
@@ -185,34 +153,14 @@ SystemModel.prototype.PlaySound = function(soundName) {
|
||||
}
|
||||
|
||||
//Play an alert sound
|
||||
//Note: If you want more control, include an HTML5 audio tag with the id "audioPlayer"
|
||||
// Otherwise a system function will be used
|
||||
SystemModel.prototype.PlayAlertSound = function(sound) {
|
||||
if (!sound || sound == "") {
|
||||
sound = "Subtle (short)";
|
||||
}
|
||||
if (sound != "off") {
|
||||
var soundPath = "/media/internal/ringtones/" + sound + ".mp3";
|
||||
if (sound.indexOf("/") != -1)
|
||||
soundPath = sound;
|
||||
|
||||
var audioPlayer = document.getElementById("audioPlayer");
|
||||
if (audioPlayer) {
|
||||
Mojo.Log.info("Playing notification sound " + soundPath + " using audioPlayer element");
|
||||
if (soundPath) {
|
||||
Mojo.Log.info("trying to play audio: " + soundPath);
|
||||
audioPlayer.src = soundPath;
|
||||
audioPlayer.load();
|
||||
}
|
||||
audioPlayer.play();
|
||||
} else {
|
||||
Mojo.Log.warn("No audio element named audioPlayer, using notification sound to play " + soundPath);
|
||||
if (!sound || sound == "") {
|
||||
sound = "Subtle (short)";
|
||||
}
|
||||
Mojo.Log.info("trying to play: " + soundPath);
|
||||
Mojo.Controller.getAppController().playSoundNotification("media", soundPath, 2500);
|
||||
}
|
||||
Mojo.Log.info("trying to play: " + soundPath);
|
||||
Mojo.Controller.getAppController().playSoundNotification("media", soundPath, 2500);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,26 +176,11 @@ SystemModel.prototype.Vibrate = function(vibrate) {
|
||||
} else
|
||||
vibeMax = Number(vibrate);
|
||||
if (vibeMax > 0)
|
||||
vibeInterval = window.setInterval(doVibrate, 500);
|
||||
vibeInterval = setInterval(doVibrate, 500);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//Lock the physical volume buttons to the media volume (instead of default, notification volume)
|
||||
SystemModel.prototype.LockVolumeKeys = function() {
|
||||
Mojo.Log.info("Locking media volume to hardware buttons");
|
||||
this.wakeupRequest = new Mojo.Service.Request("palm://com.palm.audio/media", {
|
||||
method: "lockVolumeKeys",
|
||||
onSuccess: function(response) {
|
||||
Mojo.Log.info("Lock Volume Keys Success", JSON.stringify(response));
|
||||
},
|
||||
onFailure: function(response) {
|
||||
Mojo.Log.error("Lock Volume Keys Failure: ", JSON.stringify(response));
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
//Launch an app
|
||||
SystemModel.prototype.LaunchApp = function(appName, params) {
|
||||
if (!params)
|
||||
@@ -261,148 +194,12 @@ SystemModel.prototype.LaunchApp = function(appName, params) {
|
||||
Mojo.Log.info("App Launch Success", appName, JSON.stringify(response));
|
||||
},
|
||||
onFailure: function(response) {
|
||||
Mojo.Log.error("App Launch Failure", appName, JSON.stringify(response));
|
||||
Mojo.Log.error("Alarm Launch Failure", appName, JSON.stringify(response));
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
//Use in combination with a Touch2Share launch to send a URI to a tapped device
|
||||
SystemModel.prototype.SendDataForTouch2Share = function(url, callback) {
|
||||
if (!url) {
|
||||
Mojo.Log.error("Share URL not supplied");
|
||||
return false;
|
||||
}
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
var params = {data: { target: url, type: "rawdata", mimetype: "text/html" }};
|
||||
Mojo.Log.info("Touch2Share payload is ", JSON.stringify(params));
|
||||
|
||||
this.shareRequest = new Mojo.Service.Request("palm://com.palm.stservice", {
|
||||
method: "shareData",
|
||||
parameters: params,
|
||||
subscribe: true,
|
||||
onSuccess: function(response) {
|
||||
Mojo.Log.info("Touch2Share Success!", JSON.stringify(response));
|
||||
if (callback) {
|
||||
callback(response);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onFailure: function(response) {
|
||||
Mojo.Log.error("Touch2Share Failure: ", JSON.stringify(response));
|
||||
if (callback) {
|
||||
callback(response);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
//Download a file
|
||||
//A fire-and-forget way to interact with the DownloadManager. The user will get a generic notification when the download is complete.
|
||||
SystemModel.prototype.DownloadFile = function (url, mimetype, pathFromInteral, fileName, subscribe, callback) {
|
||||
if (!url) {
|
||||
Mojo.Log.error("Download URL not supplied");
|
||||
return false;
|
||||
}
|
||||
if (!pathFromInteral){
|
||||
Mojo.Log.error("Save path not supplied");
|
||||
return false;
|
||||
}
|
||||
if (callback)
|
||||
callback = callback.bind(this);
|
||||
|
||||
//Figure out what extension to use
|
||||
var ext = "";
|
||||
mimetype = mimetype.toLowerCase();
|
||||
if (mimetype.indexOf("image/") != -1) {
|
||||
if (mimetype == "image/jpeg")
|
||||
ext = "jpg"
|
||||
else {
|
||||
ext = mimetype.split("/");
|
||||
ext = ext[ext.length - 1];
|
||||
}
|
||||
} else if (mimetype == "text/plain") {
|
||||
ext = "txt";
|
||||
} else if (mimetype == "application/json") {
|
||||
ext = "json";
|
||||
} else {
|
||||
if (mimetype.indexOf("/") != -1) {
|
||||
ext = mimetype.split("/");
|
||||
ext = ext[1];
|
||||
}
|
||||
}
|
||||
ext = "." + ext;
|
||||
|
||||
this.downloadRequest = new Mojo.Service.Request('palm://com.palm.downloadmanager/', {
|
||||
method: 'download',
|
||||
parameters: {
|
||||
target: url,
|
||||
mime: mimetype,
|
||||
targetDir : "/media/internal/" + pathFromInteral,
|
||||
targetFilename : fileName + ext,
|
||||
keepFilenameOnRedirect: true,
|
||||
subscribe: subscribe
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
Mojo.Log.info("Download Success!", JSON.stringify(response));
|
||||
if (callback) {
|
||||
callback(response);
|
||||
return true;
|
||||
} else {
|
||||
if (response.completed == true) {
|
||||
Mojo.Controller.getAppController().showBanner({ messageText: "Content downloaded!" }, "", "");
|
||||
}
|
||||
}
|
||||
},
|
||||
onFailure: function(response) {
|
||||
Mojo.Log.error("Download Failure: ", JSON.stringify(response));
|
||||
if (callback) {
|
||||
callback(response);
|
||||
return false;
|
||||
} else {
|
||||
Mojo.Controller.getAppController().showBanner({ messageText: "Download error:" + JSON.stringify(response) }, "", "");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SystemModel.prototype.LoadWOSAPrefs = function (callback) {
|
||||
if (callback)
|
||||
callback.bind(this);
|
||||
var req = new Ajax.Request("/media/internal/.wosaprefs", {
|
||||
method: 'get',
|
||||
onFailure: function() {
|
||||
Mojo.Log.warn("Could not load .wosaprefs file. Preferences cannot be opened.");
|
||||
callback(null);
|
||||
},
|
||||
on404: function() {
|
||||
Mojo.Log.warn("Could not find .wosaprefs file. Preferences cannot be opened.");
|
||||
callback(null);
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
if (response && response.responseText) {
|
||||
Mojo.Log.info("Loaded .wosaprefs file: " + JSON.stringify(response.responseText));
|
||||
try {
|
||||
prefsObj = JSON.parse(response.responseText);
|
||||
this.WOSAPrefs = prefsObj.preferences;
|
||||
} catch(ex) {
|
||||
Mojo.Log.warn("Could not parse .wosaprefs file. Preferences cannot be opened. " + ex);
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
callback(prefsObj);
|
||||
return;
|
||||
} else {
|
||||
Mojo.Log.warn("Could not read .wosaprefs file. Preferences cannot be opened.");
|
||||
}
|
||||
callback(null);
|
||||
}.bind(this)
|
||||
});
|
||||
}
|
||||
|
||||
//Helper Functions
|
||||
var vibeInterval;
|
||||
var vibeCount = 0;
|
||||
@@ -559,7 +356,7 @@ SystemModel.prototype.SetDisplayState = function(state) {
|
||||
}
|
||||
|
||||
//Set the Notifications-When-Locked state
|
||||
SystemModel.prototype.SetShowNotificationsWhenLocked = function(value) {
|
||||
SystemModel.prototype.setShowNotificationsWhenLocked = function(value) {
|
||||
if (Mojo.Controller.appInfo.id.indexOf("com.palm") != -1) {
|
||||
Mojo.Log.info("Setting Notifications When Locked to " + value);
|
||||
this.service_identifier = 'palm://com.palm.systemservice';
|
||||
@@ -575,7 +372,7 @@ SystemModel.prototype.SetShowNotificationsWhenLocked = function(value) {
|
||||
}
|
||||
|
||||
//Set the LED Notification state
|
||||
SystemModel.prototype.SetLEDLightNotifications = function(value) {
|
||||
SystemModel.prototype.setLEDLightNotifications = function(value) {
|
||||
if (Mojo.Controller.appInfo.id.indexOf("com.palm") != -1) {
|
||||
Mojo.Log.info("Setting LED Notifications to " + value);
|
||||
this.service_identifier = 'palm://com.palm.systemservice';
|
||||
@@ -597,7 +394,7 @@ SystemModel.prototype.GetInternetConnectionState = function(callback) {
|
||||
throw ("Privileged system service call not allowed for this App ID!");
|
||||
}
|
||||
Mojo.Log.info("Requesting Internet connection state from Connection Manager");
|
||||
this.connectedRequest = new Mojo.Service.Request("palm://com.palm.connectionmanager", {
|
||||
this.connectedRequest = new Mojo.Service.Request("palm://com.palm.connectionamanager", {
|
||||
method: "getStatus",
|
||||
parameters: {
|
||||
subscribe: false
|
||||
@@ -608,7 +405,7 @@ SystemModel.prototype.GetInternetConnectionState = function(callback) {
|
||||
}
|
||||
|
||||
//Set the WAN state
|
||||
SystemModel.prototype.SetWANEnabled = function(value) {
|
||||
SystemModel.prototype.setWANEnabled = function(value) {
|
||||
var state = value ? 'off' : 'on';
|
||||
if (Mojo.Controller.appInfo.id.indexOf("com.palm") != -1) {
|
||||
Mojo.Log.info("Setting WAN State to " + value);
|
||||
@@ -627,7 +424,7 @@ SystemModel.prototype.SetWANEnabled = function(value) {
|
||||
}
|
||||
|
||||
//Set the WIFI state
|
||||
SystemModel.prototype.SetWifiEnabled = function(value) {
|
||||
SystemModel.prototype.setWifiEnabled = function(value) {
|
||||
var state = value ? 'enabled' : 'disabled';
|
||||
if (Mojo.Controller.appInfo.id.indexOf("com.palm") != -1) {
|
||||
Mojo.Log.info("Setting WIFI State to " + state);
|
||||
@@ -660,7 +457,6 @@ SystemModel.prototype.SetBluetoothEnabled = function(value) {
|
||||
}
|
||||
}
|
||||
|
||||
//Helper for Bluetooth functions, do not call directly
|
||||
SystemModel.prototype.bluetoothControlService = function(url, params, cb) {
|
||||
return new Mojo.Service.Request(url, {
|
||||
onSuccess: cb,
|
||||
@@ -669,16 +465,14 @@ SystemModel.prototype.bluetoothControlService = function(url, params, cb) {
|
||||
});
|
||||
}
|
||||
|
||||
SystemModel.prototype.GetInstalledApps = function(callback) {
|
||||
if (callback)
|
||||
callback.bind(this);
|
||||
SystemModel.prototype.GetInstalledApps = function(callBack) {
|
||||
if (Mojo.Controller.appInfo.id.indexOf("com.palm") != -1) {
|
||||
Mojo.Log.info("Getting list of installed apps.");
|
||||
Mojo.Log.info("Getting list of running apps.");
|
||||
this.appRequest = new Mojo.Service.Request("palm://com.palm.applicationManager/listApps", {
|
||||
method: "",
|
||||
parameters: {},
|
||||
onSuccess: callback,
|
||||
onFailure: callback
|
||||
onSuccess: callBack,
|
||||
onFailure: callBack
|
||||
});
|
||||
} else {
|
||||
Mojo.Log.error("Privileged system services can only be called by apps with an ID that starts with 'com.palm'!");
|
||||
@@ -711,121 +505,6 @@ SystemModel.prototype.KillApp = function(appId) {
|
||||
onFailure: function(response) { Mojo.Log.warn("App was not killed!", JSON.stringify(response)); }
|
||||
});
|
||||
} else {
|
||||
Mojo.Log.error("Privileged system services can only be called by apps with an ID that starts with 'com.palm'!");
|
||||
throw ("Privileged system service call not allowed for this App ID!");
|
||||
}
|
||||
}
|
||||
|
||||
SystemModel.prototype.ListHandlersForURL = function(url, callback) {
|
||||
|
||||
if (Mojo.Controller.appInfo.id.indexOf("com.palm") != -1) {
|
||||
if (callback)
|
||||
callback.bind(this);
|
||||
Mojo.Log.info("Listing handlers for URL: " + url);
|
||||
|
||||
this.serviceRequest = new Mojo.Service.Request("palm://com.palm.applicationManager", {
|
||||
method: "listAllHandlersForUrl",
|
||||
parameters: {
|
||||
"url": url
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
//Mojo.Log.info("Handler list success: " + JSON.stringify(response));
|
||||
if (response && response.redirectHandlers) {
|
||||
if (callback)
|
||||
callback(response.redirectHandlers);
|
||||
} else {
|
||||
Mojo.Log.error("Unexpected payload in system service request");
|
||||
}
|
||||
}.bind(this),
|
||||
onFailure: function(response) {
|
||||
Mojo.Log.error("Handler list failure: " + JSON.stringify(response));
|
||||
if (callback)
|
||||
callback(response);
|
||||
}.bind(this)
|
||||
});
|
||||
} else {
|
||||
|
||||
Mojo.Log.error("Privileged system services can only be called by apps with an ID that starts with 'com.palm'!");
|
||||
throw ("Privileged system service call not allowed for this App ID!");
|
||||
}
|
||||
}
|
||||
|
||||
SystemModel.prototype.AddHandlerForURL = function(urlPattern, appId, callback) {
|
||||
|
||||
if (Mojo.Controller.appInfo.id.indexOf("com.palm") != -1) {
|
||||
if (!urlPattern)
|
||||
throw "No urlPattern specified";
|
||||
if (callback)
|
||||
callback.bind(this);
|
||||
if (!appId)
|
||||
appId = Mojo.Controller.appInfo.id;
|
||||
Mojo.Log.info("Add handler for URL: " + urlPattern + " with app " + appId);
|
||||
|
||||
if (urlPattern && urlPattern != "" && appId && appId != "" && appId.indexOf(".") > -1) {
|
||||
this.serviceRequest = new Mojo.Service.Request("palm://com.palm.applicationManager", {
|
||||
method: "addRedirectHandler",
|
||||
parameters: {
|
||||
"appId": appId,
|
||||
"urlPattern": urlPattern,
|
||||
"schemeForm": false,
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
Mojo.Log.info("Handler registration success: " + JSON.stringify(response));
|
||||
if (callback)
|
||||
callback(response);
|
||||
else
|
||||
Mojo.Controller.getAppController().showBanner("URL Helper added: " + appId + ".", { source: 'notification' });
|
||||
}.bind(this),
|
||||
onFailure: function(response) {
|
||||
Mojo.Log.error("Handler registration failure: " + JSON.stringify(response));
|
||||
if (callback)
|
||||
callback(response);
|
||||
else
|
||||
Mojo.Controller.getAppController().showBanner("URL Helper failed: " + appId + ".", { source: 'notification' });
|
||||
|
||||
}.bind(this)
|
||||
});
|
||||
} else {
|
||||
Mojo.Log.error("Invalid parameters specified. Not attempting to add Redirect Handler!");
|
||||
}
|
||||
} else {
|
||||
|
||||
Mojo.Log.error("Privileged system services can only be called by apps with an ID that starts with 'com.palm'!");
|
||||
throw ("Privileged system service call not allowed for this App ID!");
|
||||
}
|
||||
}
|
||||
|
||||
SystemModel.prototype.RemoveHandlerForURL = function(appId, callback) {
|
||||
if (Mojo.Controller.appInfo.id.indexOf("com.palm") != -1) {
|
||||
|
||||
if (!appId)
|
||||
appId = Mojo.Controller.appInfo.id;
|
||||
if (callback)
|
||||
callback.bind(this);
|
||||
Mojo.Log.info("Remove URL handling for app: " + appId);
|
||||
|
||||
this.serviceRequest = new Mojo.Service.Request("palm://com.palm.applicationManager", {
|
||||
method: "removeHandlersForAppId",
|
||||
parameters: {
|
||||
"appId": appId
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
Mojo.Log.info("Handler remove success: " + JSON.stringify(response));
|
||||
if (callback)
|
||||
callback(response);
|
||||
else
|
||||
Mojo.Controller.getAppController().showBanner("URL Helper removed: " + appId + ".", { source: 'notification' });
|
||||
}.bind(this),
|
||||
onFailure: function(response) {
|
||||
Mojo.Log.error("Handler list failure: " + JSON.stringify(response));
|
||||
if (callback)
|
||||
callback(response)
|
||||
else
|
||||
Mojo.Controller.getAppController().showBanner("URL Helper failed: " + appId + ".", { source: 'notification' });
|
||||
}.bind(this)
|
||||
});
|
||||
} else {
|
||||
|
||||
Mojo.Log.error("Privileged system services can only be called by apps with an ID that starts with 'com.palm'!");
|
||||
throw ("Privileged system service call not allowed for this App ID!");
|
||||
}
|
||||
@@ -1,122 +1,35 @@
|
||||
/*
|
||||
Updater Model - Mojo
|
||||
Version 1.0
|
||||
Created: 2022
|
||||
Author: Jon W
|
||||
Version 0.3
|
||||
Created: 2020
|
||||
Author: Jonathan Wise
|
||||
License: MIT
|
||||
Description: A model to check for and get updates from App Museum II web service.
|
||||
Does not require App Museum to be installed, but does require internet access, and Preware to do the actual install.
|
||||
Source: Find the latest version of this library and info on how to use it on GitHub:
|
||||
https://github.com/webosarchive/webos-common
|
||||
Source: Find the latest version of this library and clean samples of how to use it on GitHub:
|
||||
https://github.com/codepoet80/webos-catalog-frontend/tree/main/Examples
|
||||
*/
|
||||
|
||||
//** Note: If you synced this file from a common repository, local edits may be over-written! */
|
||||
|
||||
var UpdaterModel = function() {
|
||||
this.updateURL = "http://appcatalog.webosarchive.org/WebService/getLatestVersionInfo.php?app=";
|
||||
this.updateURL = "http://appcatalog.webosarchive.com/WebService/getLatestVersionInfo.php?app=";
|
||||
this.lastUpdateResponse = null;
|
||||
};
|
||||
|
||||
/* "Public" Updater functions */
|
||||
|
||||
//Gather information and Check App Museum II web service to see if there are any updates
|
||||
//Check App Museum II web service to see if there are any updates
|
||||
UpdaterModel.prototype.CheckForUpdate = function(appName, callback) {
|
||||
|
||||
var currVersion = this.getVersionObject(Mojo.Controller.appInfo.version);
|
||||
Mojo.Log.info("UpdaterModel identified current app " + appName + " version: " + JSON.stringify(currVersion));
|
||||
|
||||
this.deviceInfoRequest = new Mojo.Service.Request("palm://com.palm.preferences/systemProperties", {
|
||||
method: "Get",
|
||||
parameters:{"key": "com.palm.properties.nduid" },
|
||||
onSuccess: this.performIdentifiedUpdateCheck.bind(this, appName, currVersion, callback),
|
||||
onFailure: this.performIdentifiedUpdateCheck.bind(this, appName, currVersion, callback)
|
||||
});
|
||||
}
|
||||
// TODO: It would be nice to use the AppID, instead of an arbitrary name, but the performance
|
||||
// implications are overwhelming since the AppID is not a part of the masterData file.
|
||||
// We could get that from the app with: Mojo.Controller.appInfo.id
|
||||
var updateURL = this.updateURL + encodeURI(appName);
|
||||
|
||||
//You can optionally call this function if you don't want to handle the user interaction related to prompting for an update
|
||||
// Pass the function to be called back with the user's response
|
||||
// Optionally pass a message to the user if you don't like the automatically constructed one
|
||||
UpdaterModel.prototype.PromptUserForUpdate = function(callback, message) {
|
||||
if (!this.lastUpdateResponse) {
|
||||
Mojo.Log.warn("UpdaterModel: Not prompting user for update when no update has been discovered.");
|
||||
} else {
|
||||
if (!message)
|
||||
message = "An update for " + Mojo.Controller.appInfo.title + " was found in App Museum II:<br>" + this.lastUpdateResponse.versionNote + "<br>Do you want to update now?";
|
||||
|
||||
if (callback) // set scope for xmlhttp anonymous function callback
|
||||
callBack = callback.bind(this);
|
||||
|
||||
var stageController = Mojo.Controller.getAppController().getActiveStageController();
|
||||
if (stageController) {
|
||||
this.controller = stageController.activeScene();
|
||||
|
||||
this.controller.showAlertDialog({
|
||||
onChoose: function(value) {
|
||||
if (value) {
|
||||
Mojo.Log.info("User requested update now");
|
||||
} else {
|
||||
Mojo.Log.info("User deferred update.");
|
||||
}
|
||||
if (callBack)
|
||||
callBack(value);
|
||||
},
|
||||
allowHTMLMessage: true,
|
||||
title: $L("Update Available!"),
|
||||
message: $L(message),
|
||||
choices: [
|
||||
{ label: $L('Update Now'), value: true, type: 'affirmative' },
|
||||
{ label: $L("Later"), value: false, type: 'negative' }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Ask Preware to actually install the update...
|
||||
UpdaterModel.prototype.InstallUpdate = function() {
|
||||
if (!this.lastUpdateResponse) {
|
||||
Mojo.Log.warn("UpdaterModel: Not performing update when no update has been discovered.");
|
||||
} else {
|
||||
var app = this.lastUpdateResponse.downloadURI;
|
||||
Mojo.Log.info("Asking PreWare to perform update to " + app);
|
||||
|
||||
this.InstallViaPreware(app);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
UpdaterModel.prototype.InstallViaPreware = function(app) {
|
||||
//Ask webOS to launch the PreWare with install url
|
||||
this.prewareRequest = new Mojo.Service.Request("palm://com.palm.applicationManager", {
|
||||
method: "open",
|
||||
parameters: {
|
||||
"id": "org.webosinternals.preware",
|
||||
params: { type: "install", file: app }
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
Mojo.Log.info("Preware launch success", JSON.stringify(response));
|
||||
}.bind(this),
|
||||
onFailure: function(response) {
|
||||
Mojo.Log.error("Preware launch failure, " + app + ":", JSON.stringify(response), response.errorText);
|
||||
}.bind(this)
|
||||
});
|
||||
}
|
||||
|
||||
/* "Private" helper functions */
|
||||
|
||||
//Internal Function that uses the resolved information to actually do the check
|
||||
UpdaterModel.prototype.performIdentifiedUpdateCheck = function(appName, currVersion, callback, response) {
|
||||
// Build appropriate URL for conditions
|
||||
var updateURL = this.updateURL + encodeURI(appName + "/" + Mojo.Controller.appInfo.version);
|
||||
// If we have a device identifier, use that
|
||||
if(response && JSON.stringify(response).indexOf("com.palm.properties.nduid") != -1) {
|
||||
updateURL = updateURL + "&clientid=" + response[Object.keys(response)[0]];
|
||||
}
|
||||
// Send some info about the device (could be used for compat checks)
|
||||
deviceData = Mojo.Environment.DeviceInfo.modelName + "/" + Mojo.Environment.DeviceInfo.platformVersion + "/" + (Mojo.Environment.DeviceInfo.carrierName || "WiFi") + "/" + Mojo.Locale.getCurrentLocale();
|
||||
updateURL = updateURL + "&device=" + encodeURIComponent(deviceData);
|
||||
|
||||
if (callback) // set scope for xmlhttp anonymous function callback
|
||||
// set scope for xmlhttp anonymous function callback
|
||||
if (callback)
|
||||
callBack = callback.bind(this);
|
||||
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
@@ -131,6 +44,7 @@ UpdaterModel.prototype.performIdentifiedUpdateCheck = function(appName, currVers
|
||||
var updateResponse = JSON.parse(xmlhttp.responseText);
|
||||
if (updateResponse.version != null) {
|
||||
var museumVersion = this.getVersionObject(updateResponse.version);
|
||||
//Mojo.Log.info("Museum version: " + JSON.stringify(museumVersion));
|
||||
if (this.isVersionHigher(currVersion, museumVersion)) {
|
||||
Mojo.Log.warn("UpdaterModel found an update in webOS App Museum II!");
|
||||
updateResponse.updateFound = true;
|
||||
@@ -143,13 +57,78 @@ UpdaterModel.prototype.performIdentifiedUpdateCheck = function(appName, currVers
|
||||
} else {
|
||||
Mojo.Log.info("UpdaterModel: No useable response from App Museum II update API");
|
||||
}
|
||||
if (callBack) {
|
||||
//Mojo.Log.info("New update response object: " + JSON.stringify(updateResponse));
|
||||
if (callback) {
|
||||
callBack(updateResponse);
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
//You can optionally call this function if you don't want to handle the user interaction related to prompting for an update
|
||||
// Pass the function to be called back with the user's response
|
||||
// Optionally pass a message to the user if you don't like the automatically constructed one
|
||||
UpdaterModel.prototype.PromptUserForUpdate = function(callback, message) {
|
||||
if (!this.lastUpdateResponse) {
|
||||
Mojo.Log.warn("UpdaterModel: Not prompting user for update when no update has been discovered.");
|
||||
} else {
|
||||
if (!message)
|
||||
message = "An update for " + Mojo.Controller.appInfo.title + " was found in App Museum II: <br>" + this.lastUpdateResponse.versionNote + "<br>Do you want to update now?";
|
||||
|
||||
var stageController = Mojo.Controller.getAppController().getActiveStageController();
|
||||
if (stageController) {
|
||||
this.controller = stageController.activeScene();
|
||||
|
||||
this.controller.showAlertDialog({
|
||||
onChoose: function(value) {
|
||||
if (value) {
|
||||
Mojo.Log.info("User requested update now");
|
||||
} else {
|
||||
Mojo.Log.info("User deferred update.");
|
||||
}
|
||||
if (callback)
|
||||
callback(value);
|
||||
},
|
||||
allowHTMLMessage: true,
|
||||
title: $L("Update Available!"),
|
||||
message: $L(message),
|
||||
choices: [
|
||||
{ label: $L('Update Now'), value: true, type: 'affirmative' },
|
||||
{ label: $L("Later"), value: false, type: 'negative' }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Ask Preware to actually install the update...
|
||||
UpdaterModel.prototype.InstallUpdate = function(callBack) {
|
||||
if (!this.lastUpdateResponse) {
|
||||
Mojo.Log.warn("UpdaterModel: Not performing update when no update has been discovered.");
|
||||
} else {
|
||||
var app = this.lastUpdateResponse.downloadURI;
|
||||
Mojo.Log.info("Asking PreWare to perform update to " + app);
|
||||
|
||||
this.prewareRequest = new Mojo.Service.Request("palm://com.palm.applicationManager", {
|
||||
method: "open",
|
||||
parameters: {
|
||||
"id": "org.webosinternals.preware",
|
||||
params: { type: "install", file: app }
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
Mojo.Log.info("Preware launch success", JSON.stringify(response));
|
||||
},
|
||||
onFailure: function(response) {
|
||||
Mojo.Log.error("Preware launch failure, " + app + ":",
|
||||
JSON.stringify(response), response.errorText);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* "Private" helper functions */
|
||||
|
||||
//Turn a version string into an object with three independent number values
|
||||
UpdaterModel.prototype.getVersionObject = function(versionNum) {
|
||||
versionNumParts = versionNum.split(".");
|
||||
@@ -179,4 +158,4 @@ UpdaterModel.prototype.isVersionHigher = function(currVersion, compareVersion) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
<div class="dashboard-notification-module">
|
||||
<div class="palm-dashboard-icon-container">
|
||||
<div class="dashboard-newitem" style="display:#{showCount}">
|
||||
|
||||
<div class="dashboard-newitem">
|
||||
<span>#{count}</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="dashboard-icon" class="palm-dashboard-icon dashboard-icon-chat">
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="palm-row" style="min-height: 68px;">
|
||||
<div class="palm-row" x-mojo-tap-highlight='momentary'>
|
||||
<div class="palm-row-wrapper">
|
||||
<div id="divMsg-#{uid}" class="chat-log" style="color:#{color}"><span class="sender #{postedFrom}">#{sender}:</span> #{formattedMessage}</div>
|
||||
<div class="chat-time">#{timestamp} <span class="likes">#{likes}</span></div>
|
||||
@@ -1,8 +1,7 @@
|
||||
<div class="palm-page-header multi-line">
|
||||
<div class="palm-page-header">
|
||||
<div class="header-icon preferences"></div>
|
||||
<div id="imgTransmit" style="float:right;width:32px;height:32px;margin-top:-24px;margin-right:-12px; background: url('assets/transmit.png') no-repeat; background-size: 32px 32px;"></div>
|
||||
<div class="header-text">
|
||||
<span x-mojo-loc='' style="text-transform:none;" id="spnTitle">webOS SimpleChat</span>
|
||||
<span x-mojo-loc='' style="text-transform:none;">webOS SimpleChat 2</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +16,7 @@
|
||||
|
||||
<div class="palm-group" style="min-height:64px">
|
||||
<div class="palm-group-title" id="divComposeTitle"><span x-mojo-loc='' id="spanCompose">Compose</span> <img src="assets/twisty-down.png" id="imgTwisty"></div>
|
||||
<div x-mojo-element="TextField" id="txtMessage" class="textFieldClass" name="txtMessage"></div>
|
||||
<div x-mojo-element="TextField" id="txtMessage" class="textFieldClass" name="txtMessage" style="min-height:56px; background-color:white;border: 1px solid dimgray"></div>
|
||||
<div id="divSpinnerContainer" style="width: 30px;margin-left: auto;margin-right: auto; align-items: center; margin-top:-25px;">
|
||||
<div x-mojo-element="Spinner" class="spinnerClass" id="workingSpinner" name="workingSpinner"></div>
|
||||
</div>
|
||||
@@ -11,12 +11,6 @@
|
||||
|
||||
<div class="palm-list" id="divTest">
|
||||
<div class="palm-row first">
|
||||
<div class="palm-row-wrapper">
|
||||
<div x-mojo-element="ListSelector" title="ThemePreference" id="listThemePreference"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="palm-row">
|
||||
<div class="palm-row-wrapper">
|
||||
<div id="listForegroundUpdate" x-mojo-element="ListSelector" title="ForegroundUpdate" class="right"></div>
|
||||
</div>
|
||||
@@ -28,13 +22,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="palm-row">
|
||||
<div class="palm-row-wrapper">
|
||||
<div x-mojo-element="ToggleButton" id="toggleParsing" title="SkipParsing"></div>
|
||||
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Skip Parsing</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="palm-row">
|
||||
<div class="palm-row-wrapper">
|
||||
<div x-mojo-element="ToggleButton" id="toggleEmojis" title="ShowEmojis"></div>
|
||||
@@ -42,19 +29,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="palm-row">
|
||||
<div class="palm-row-wrapper">
|
||||
<div x-mojo-element="ToggleButton" id="toggleThumbs" title="ShowWOSAThumbs"></div>
|
||||
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Share Thumbnails</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="palm-row">
|
||||
<div class="palm-row-wrapper">
|
||||
<div id="listEnterSubmits" x-mojo-element="ListSelector" title="EnterSubmits" class="right"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="palm-row last">
|
||||
<div class="palm-row-wrapper">
|
||||
<span x-mojo-loc="" id="SoundOptionLabel" width="100%" class="label truncating-text" style="float:left; min-width:120px; margin-left: 14px; margin-top: 14px;">Alert Sound</span>
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="palm-dialog-content">
|
||||
<div id="hue-title" class="palm-dialog-title multi-line">
|
||||
<div id="hue-title" class="palm-dialog-title">
|
||||
Getting Acquainted
|
||||
</div>
|
||||
<div class="palm-dialog-seperator" style="height: 8px;"></div>
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "com.jonandnic.simplechat.app",
|
||||
"version": "2.0.0",
|
||||
"vendor": "Jon Wise",
|
||||
"type": "web",
|
||||
"main": "index.html",
|
||||
"noWindow": true,
|
||||
"title": "SimpleChat",
|
||||
"icon": "icon.png",
|
||||
"uiRevision": "2",
|
||||
"theme": "light"
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -13,7 +13,7 @@ span.emoji-outer {
|
||||
}
|
||||
|
||||
span.emoji-inner {
|
||||
background: url(../assets/emoji.png);
|
||||
background: url(emoji.png);
|
||||
display: -moz-inline-box;
|
||||
display: inline-block;
|
||||
text-indent: -9999px;
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"logLevel": 10,
|
||||
"debuggingEnabled": false,
|
||||
"logLevel": 99,
|
||||
"debuggingEnabled": true,
|
||||
"timingEnabled": false,
|
||||
"logEvents": false,
|
||||
"escapeHTMLInTemplates": true
|
||||
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name='viewport' content='height=device-height'>
|
||||
<title>Simple Chat</title>
|
||||
<script src="/usr/palm/frameworks/mojo/mojo.js" type="text/javascript" x-mojo-version="1"></script>
|
||||
|
||||
<!-- load my additions -->
|
||||
<script src="app/com.jonandnic.mojo.additions.js" type="text/javascript"></script>
|
||||
|
||||
<!-- application stylesheet should come in after the one loaded by the framework -->
|
||||
<link href="stylesheets/simplechat.css" media="screen" rel="stylesheet" type="text/css">
|
||||
<link href="emoji.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -5,10 +5,6 @@
|
||||
background-size: 32px 32px;
|
||||
}
|
||||
|
||||
.palm-dark .header-text {
|
||||
color:lightgray !important;
|
||||
}
|
||||
|
||||
.explanation-text {
|
||||
margin-top: -5px;
|
||||
padding: 14px;
|
||||
@@ -16,18 +12,10 @@
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.palm-dark .explanation-text {
|
||||
color: lightgray;
|
||||
}
|
||||
|
||||
.chat-log {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.palm-dark .chat-log {
|
||||
color:lightgray !important;
|
||||
}
|
||||
|
||||
.sender {
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -48,22 +36,6 @@
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
|
||||
.palm-dark .chat-time {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.textFieldClass {
|
||||
min-height:56px;
|
||||
background-color:white;
|
||||
border: 1px solid dimgray;
|
||||
}
|
||||
|
||||
.palm-dark .textFieldClass {
|
||||
min-height:56px;
|
||||
background-color:lightgray;
|
||||
border: 1px solid dimgray;
|
||||
}
|
||||
|
||||
.textFieldClass input {
|
||||
padding: 1px;
|
||||
}
|
||||
@@ -76,10 +48,6 @@ textarea {
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
|
||||
.palm-dark .palm-dialog-content .palm-body-text {
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.multiline-hint-text.oblique {
|
||||
color: darkgray;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "com.jonandnic.simplechat",
|
||||
"package_format_version": 2,
|
||||
"loc_name": "SimpleChat",
|
||||
"version": "2.0.0",
|
||||
"icon": "icon.png",
|
||||
"miniicon": "icon.png",
|
||||
"vendor": "Jon Wise",
|
||||
"vendorurl": "www.jonandnic.com",
|
||||
"app": "com.jonandnic.simplechat.app",
|
||||
"services": ["com.jonandnic.simplechat.service"]
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
var libraries = MojoLoader.require({ name: "foundations", version: "1.0" });
|
||||
var Future = libraries["foundations"].Control.Future;
|
||||
var PalmCall = libraries["foundations"].Comms.PalmCall;
|
||||
var AjaxCall = libraries["foundations"].Comms.AjaxCall;
|
||||
|
||||
var AlarmAssistant = function() {}
|
||||
|
||||
AlarmAssistant.prototype.run = function(future) {
|
||||
console.log("***************Hello " + this.controller.args.name);
|
||||
if (this.controller.args.name == "silent") {
|
||||
var outputVal = 0;
|
||||
for (var i = 0; i < 1000; i++) {
|
||||
outputVal = outputVal++;
|
||||
}
|
||||
|
||||
future.result = { reply: "*********** Hello quietly! Output val is:" + outputVal };
|
||||
|
||||
} else {
|
||||
|
||||
console.log("********* Trying to get data");
|
||||
/*var options = { "bodyEncoding": "utf8" };
|
||||
var future1 = AjaxCall.get("http://chat.webosarchive.com/get-chat.php", options);
|
||||
future1.then(function(future2) {
|
||||
console.log("********* Ajax result " + JSON.stringify(future2.result))
|
||||
if (future2.result.status == 200) { // 200 = Success
|
||||
console.log('********* Ajax get success ' + JSON.stringify(future2.result));
|
||||
} else console.log('Ajax get fail');
|
||||
});*/
|
||||
|
||||
var options = { "bodyEncoding": "utf8" };
|
||||
var future1 = AjaxCall.get("http://chat.webosarchive.com/get-chat.php", options);
|
||||
future1.then(function(future) {
|
||||
var result = future.result;
|
||||
//if (result.returnValue == true) {
|
||||
console.log("********* Launch Success = " + JSON.stringify(result));
|
||||
//} else Mojo.Log.info("********* Launch Failure = " + JSON.stringify(result));
|
||||
future.result = { reply: "*********** Hello noisily!" };
|
||||
});
|
||||
|
||||
|
||||
|
||||
/*
|
||||
var future1 = PalmCall.call("palm://com.palm.applicationManager", "open", { "id": "com.jonandnic.simplechat.app", "params": { "action": "alarm" } });
|
||||
future1.then(function(future) {
|
||||
var result = future.result;
|
||||
if (result.returnValue == true) {
|
||||
Mojo.Log.info("********* Launch Success = " + JSON.stringify(result));
|
||||
} else Mojo.Log.info("********* Launch Failure = " + JSON.stringify(result));
|
||||
});
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "com.jonandnic.simplechat.service",
|
||||
"description": "SimpleChat Background Service",
|
||||
"activityTimeout": 30,
|
||||
"services": [{
|
||||
"name": "com.jonandnic.simplechat.service",
|
||||
"description": "helloworld example",
|
||||
"commands": [{
|
||||
"name": "alarm",
|
||||
"assistant": "AlarmAssistant",
|
||||
"public": true
|
||||
}]
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
[{
|
||||
"library": {
|
||||
"name": "foundations",
|
||||
"version": "1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": "AlarmAssistant.js"
|
||||
}
|
||||
]
|
||||
@@ -1,160 +0,0 @@
|
||||
function VersionAssistant(startup) {
|
||||
this.isStartup = startup;
|
||||
|
||||
// on first start, this message is displayed, along with the current version message from below
|
||||
this.startupMessage = Mojo.Controller.appInfo.startupMessage;
|
||||
|
||||
//New Features
|
||||
this.changelog = [
|
||||
{
|
||||
version: "Version 1.8.0",
|
||||
detail: [
|
||||
"Dark theme now available in Preferences!",
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.7.1",
|
||||
detail: [
|
||||
"Fix a bug where hardware mute switch wasn't respected. Show transmit indicator. Add ability to disable link and image parsing to speed things up on tiny devices.",
|
||||
]
|
||||
},{
|
||||
version: "Version 1.7.0",
|
||||
detail: [
|
||||
"Images from listThemePreference are now supported! Inline rendering uses a thumbnail for efficiency; tap the image to load the fullsize, or tap elsewhere on the row to pull up the menu that lets you download the image to your device (it will be saved to /internal/downloads)",
|
||||
]
|
||||
},{
|
||||
version: "Version 1.6.0",
|
||||
detail: [
|
||||
"Added ability to parse Imgur album links and render via a service proxy.",
|
||||
]
|
||||
},{
|
||||
version: "Version 1.5.0",
|
||||
detail: [
|
||||
"Added ability to parse Share Services links and show thumbnails, configurable in Preferences.",
|
||||
]
|
||||
},{
|
||||
version: "Version 1.4.1",
|
||||
detail: [
|
||||
"Add support for some basic markdown",
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.4.0",
|
||||
detail: [
|
||||
"Enter key behavior as a Preference",
|
||||
"Even more silent background sync, won't sync if offline",
|
||||
"Swiping notifications resets missed message count",
|
||||
"Adjust tap target for collapsing controls"
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.3.2",
|
||||
detail: [
|
||||
"More sync timing options.",
|
||||
"Refactored some code to make forking easier."
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.3.1",
|
||||
detail: [
|
||||
"Enter key now sends message when Command menu buttons are hidden."
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.3.0",
|
||||
detail: [
|
||||
"Drastically improved background update and notifications."
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.2.0",
|
||||
detail: [
|
||||
"Converts image links to an image proxy so they can be viewed and scaled properly on tiny devices",
|
||||
"Improved background update, using a notification launch, no longer interupts Exhibition, video playback or One Night Stand"
|
||||
]
|
||||
},
|
||||
{
|
||||
version: "Version 1.1.3",
|
||||
detail: [
|
||||
"Bug fixes and general maintenance"
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.1.2",
|
||||
detail: [
|
||||
"Show/Hide the Command menu buttons by tapping the Compose area title bar",
|
||||
"Enable/Disable listThemePreference Emojis in Preferences",
|
||||
]
|
||||
}, {
|
||||
version: "Version 1.1.1",
|
||||
detail: [
|
||||
"Improved listThemePreference integration, including showing Emojis!<span class='emoji-outer emoji-sizer'><span class='emoji-inner emoji1f388'></span></span>",
|
||||
"Now with a smaller emoji file!",
|
||||
"Improved timeout logic.",
|
||||
"Trying different background sync logic."
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// setup command menu
|
||||
this.cmdMenuModel = {
|
||||
visible: false,
|
||||
items: [
|
||||
{},
|
||||
{
|
||||
label: $L("OK! Let's Go..."),
|
||||
command: 'do-continue'
|
||||
},
|
||||
{}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
VersionAssistant.prototype.setup = function() {
|
||||
this.titleElement = this.controller.get('title');
|
||||
this.dataElement = this.controller.get('data');
|
||||
|
||||
this.titleElement.innerHTML = $L('Version Info');
|
||||
|
||||
var html = '';
|
||||
html += '<div style="margin: 2px 12px 12px 12px">' + this.startupMessage + '</div>';
|
||||
|
||||
for (var i = 0; i < this.changelog.length; i++) {
|
||||
html += Mojo.View.render({ object: { title: this.changelog[i].version }, template: 'version/rowDivider' });
|
||||
html += '<ul>';
|
||||
|
||||
for (var j = 0; j < this.changelog[i].detail.length; j++) {
|
||||
html += '<li>' + this.changelog[i].detail[j] + '</li>';
|
||||
}
|
||||
html += '</ul>';
|
||||
}
|
||||
|
||||
// set data
|
||||
this.dataElement.innerHTML = html;
|
||||
|
||||
// setup menu
|
||||
this.controller.setupWidget(Mojo.Menu.appMenu, { omitDefaultItems: true }, { visible: false });
|
||||
|
||||
//if (this.isStartup) {
|
||||
// set command menu
|
||||
this.controller.setupWidget(Mojo.Menu.commandMenu, { menuClass: 'no-fade' }, this.cmdMenuModel);
|
||||
//}
|
||||
};
|
||||
|
||||
VersionAssistant.prototype.activate = function(event) {
|
||||
this.timer = this.controller.window.setTimeout(this.showContinue.bind(this), 2 * 1000);
|
||||
};
|
||||
VersionAssistant.prototype.deactivate = function(event) {};
|
||||
VersionAssistant.prototype.cleanup = function(event) {};
|
||||
|
||||
VersionAssistant.prototype.showContinue = function() {
|
||||
// show the command menu
|
||||
this.controller.setMenuVisible(Mojo.Menu.commandMenu, true);
|
||||
};
|
||||
|
||||
VersionAssistant.prototype.handleCommand = function(event) {
|
||||
if (event.type == Mojo.Event.command) {
|
||||
switch (event.command) {
|
||||
case 'do-continue':
|
||||
this.controller.stageController.popScene();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||