Compare commits

111 Commits
Author SHA1 Message Date
NotAlexNoyle ed6b88fa34 Update canonical Gitea link 2026-11-03 10:48:16 -05:00
NotAlexNoyle 4452d640e7 Update .gitignore 2026-08-05 12:14:43 -04:00
NotAlexNoyle 295ae7d962 Update About dialog for fork attribution
Preserve Jon W copyright and MIT license; add NotAlexNoyle fork
attribution and fork source URL.
2026-05-13 08:18:30 -04:00
NotAlexNoyle 0da0c2426d AlmostSimpleChat fork: rebrand + Twimoji emoji 2026-05-13 08:18:30 -04:00
codepoet80 0d0d231fae image uploading 2026-05-12 21:47:40 -04:00
codepoet80 e4245d1970 add version note (for next time) 2023-09-20 19:26:00 -04:00
codepoet80 ec2547302c bug fix share parsing 2023-09-14 08:25:28 -04:00
codepoet80 6631e5a5aa fix a bug parsing wosa links, should go in next release 2023-06-13 21:17:46 -04:00
codepoet80 6d5b15cc73 bump version 2023-05-31 11:06:12 -04:00
codepoet80 ee1a8f2dc8 add sharing support 2023-05-31 09:58:50 -04:00
codepoet80 6699fd8c06 update additions 2022-09-18 15:47:01 -04:00
codepoet80 f4a07ab049 update attributions 2022-09-17 14:34:13 -04:00
codepoet80 143206362d update additions path 2022-09-17 10:58:51 -04:00
codepoet80 34d7edf578 migrate to common components 2022-09-11 14:06:32 -04:00
codepoet80 43db97cc2b update links 2022-09-11 12:48:34 -04:00
codepoet80 b4110b5ad7 update copyrights 2022-09-10 15:09:35 -04:00
codepoet80 c5f16ff2f7 re-set log level 2022-09-03 07:49:56 -04:00
codepoet80 678b7a3db8 add comment 2022-09-03 07:37:55 -04:00
codepoet80 21106502dc update comment 2022-08-20 15:23:26 -04:00
codepoet80 3f88c17702 add dark mode, migrate TLD 2022-08-20 15:03:32 -04:00
codepoet80 8621e204af parsing pref 2022-03-28 21:37:47 -04:00
codepoet80 09359eab76 try optional link parsing and loading spinner 2022-03-28 20:47:47 -04:00
codepoet80 ad813fa9db tidy up 2022-02-18 14:42:36 -05:00
Jon W bd3a85d163 Update README.md 2022-01-19 12:04:14 -05:00
Jon W d9fcf68f6c Update README.md 2022-01-19 12:03:33 -05:00
Jon W b0e7d8201b Update README.md 2022-01-19 11:44:35 -05:00
codepoet80 49c53c2725 sync from new pc 2021-12-18 18:57:08 -05:00
CodePoet80 8795a83a59 fix bug 2021-12-14 12:51:03 -05:00
CodePoet80 8d8d089b39 fix clientid bug 2021-12-14 12:05:15 -05:00
CodePoet80 11da674e7d bump version 2021-12-13 17:28:56 -05:00
CodePoet80 b3d1b8a9ba support downloading attachments 2021-12-13 17:11:00 -05:00
CodePoet80 da0e6a82e1 stub in menu item 2021-12-13 16:55:12 -05:00
CodePoet80 c5c1d37c17 support image attachments 2021-12-13 16:42:40 -05:00
CodePoet80 852db09107 updater 2021-12-11 14:59:32 -05:00
CodePoet80 bb6b6ed5c9 change version info 2021-12-11 13:31:38 -05:00
CodePoet80 1bff5e2bf4 send version number in update check 2021-12-11 13:00:26 -05:00
CodePoet80 5a09ebaf10 bump version 2021-11-23 20:03:01 -05:00
CodePoet80 0aad1d3f66 bug fix imgur links 2021-11-23 20:02:43 -05:00
CodePoet80 9348c8efa6 upgrade updater 2021-11-23 19:22:08 -05:00
CodePoet80 4b66dc21b1 bump version 2021-11-23 10:21:44 -05:00
CodePoet80 0002846c4a add support for imgur albums 2021-11-23 10:20:28 -05:00
CodePoet80 f51cb700bc tweak info text 2021-06-05 14:27:32 -04:00
CodePoet80 52069fdfff add wosa parsing 2021-06-05 13:49:48 -04:00
CodePoet80 8e396ada3c add markdown support, bump version 2021-04-26 18:34:09 -04:00
CodePoet80 6ff0c5af86 bump version number 2021-04-21 18:50:29 -04:00
CodePoet80 689a4e8744 add preference for enter submits 2021-04-21 18:46:56 -04:00
CodePoet80 052bd755a1 pre-check background notifications for quieter experience 2021-04-21 16:59:26 -04:00
CodePoet80 bc5484ec0a remember last message when dashboard swiped clsoed 2021-04-21 15:26:14 -04:00
CodePoet80 b8972169a3 handle unknown emojis, better tap target 2021-04-21 15:08:23 -04:00
CodePoet80 f44e6e4464 make update check config specific 2021-04-16 13:00:20 -04:00
CodePoet80 d3f48b5823 send client-id with get 2021-04-16 11:00:09 -04:00
CodePoet80 a6add5d811 add client-id to get request 2021-04-16 10:40:51 -04:00
CodePoet80 200f327f23 better approach to sound playing 2021-04-15 21:14:07 -04:00
CodePoet80 ccb8b74a50 tweak dashboard message for flexibility 2021-04-15 21:02:21 -04:00
CodePoet80 e57abfcd0c oops 2021-04-15 20:53:24 -04:00
CodePoet80 3183c069a7 bump version info 2021-04-15 20:51:56 -04:00
CodePoet80 994f0edea6 more tweaks to make forking easier 2021-04-15 20:20:33 -04:00
CodePoet80 b7c4ccff34 another tweak to simplify forking 2021-04-15 20:03:39 -04:00
CodePoet80 12df9ec788 small tweak to make forking easier 2021-04-15 19:54:51 -04:00
CodePoet80 f5d412987f hide notification stage on relaunch 2021-04-15 09:51:07 -04:00
CodePoet80 3b1a01f231 bump version 2021-04-15 09:27:23 -04:00
CodePoet80 9de7602d63 send message with enter if command menu hidden 2021-04-15 09:27:10 -04:00
CodePoet80 230334e997 tweak icons 2021-04-15 08:27:48 -04:00
CodePoet80 1ab5a4154c bump version 2021-04-14 17:35:19 -04:00
CodePoet80 37b4a356cd cleanup and code comments 2021-04-14 17:34:08 -04:00
CodePoet80 86275b9f75 better background notificiations 2021-04-14 17:22:26 -04:00
CodePoet80 430d174742 bump version 2021-04-12 14:12:57 -04:00
CodePoet80 5e522c3fb5 bump version 2021-04-12 14:12:40 -04:00
CodePoet80 2ad76ec331 more background check times 2021-04-12 14:10:49 -04:00
CodePoet80 776b7b696a handle image links with proxy 2021-04-12 13:43:31 -04:00
CodePoet80 4785694ad9 restore new notification approach 2021-04-10 14:45:35 -04:00
CodePoet80 52a3bf09ee restore 1.1.3 2021-04-10 14:45:10 -04:00
CodePoet80 70e43f02f4 work on new notification approach 2021-04-10 14:37:41 -04:00
CodePoet80 d556147b09 fix merge to main of 1.x 2021-04-10 14:14:38 -04:00
CodePoet80 2768c9f1d9 merge 1.x to mai 2021-04-10 14:13:30 -04:00
CodePoet80 67e1e93513 change appid back 2021-03-06 17:24:22 -05:00
CodePoet80 b19f045158 prep for appid change-over 2021-03-06 17:22:18 -05:00
CodePoet80 b87ef1640d bump version 2021-03-06 13:47:20 -05:00
CodePoet80 d93a2783b8 textbox improvements, handle virtual keyboard 2021-03-06 13:47:05 -05:00
CodePoet80 0e8be0cb1c bug fixes, prep for edit feature 2021-03-06 12:27:12 -05:00
CodePoet80 dc71f15c3d handle links that already have http 2021-02-23 11:36:22 -05:00
CodePoet80 38f332af62 switch to systemmodel PlayAlertSound 2021-02-22 16:44:22 -05:00
CodePoet80 45fbd3a477 move PlayAlertSound to system model 2021-02-22 14:45:28 -05:00
CodePoet80 c7854528f1 move alert sound to SystemModel 2021-02-22 14:42:33 -05:00
CodePoet80 73f429ef92 disable debugging 2021-02-22 12:44:41 -05:00
CodePoet80 ca5cdc577b add context menu, bump version 2021-02-21 21:02:31 -05:00
CodePoet80 b0bcf26a7b bump version 2021-02-18 15:09:51 -05:00
CodePoet80 59fba932a5 improve background lifecycle 2021-02-18 15:08:37 -05:00
CodePoet80 10e8507519 stop keeping screen on 2021-02-17 10:34:33 -05:00
CodePoet80 6d759d6a6e fix preferences bugs, bump version 2021-02-15 18:42:42 -05:00
CodePoet80 c4c7842381 fix title 2021-02-15 16:35:10 -05:00
CodePoet80 8e65846653 touchpad fixes 2021-02-15 16:15:01 -05:00
CodePoet80 3f478326d2 bug fix for touchpad 2021-02-15 15:48:05 -05:00
CodePoet80 ac3c68aaad fix keyboard scale on touchpad 2021-02-15 15:30:59 -05:00
CodePoet80 dd408b6150 remove some extra log messages 2021-02-15 15:20:06 -05:00
CodePoet80 282796e7d9 UI tweaks, bump version number 2021-02-15 15:15:46 -05:00
CodePoet80 57693afc13 cleanup, more scroll fixing 2021-02-15 14:41:58 -05:00
CodePoet80 53aeccf477 use preferences for alarm delay 2021-02-14 20:12:11 -05:00
CodePoet80 81801493ca background notifications (just barely) working! 2021-02-14 16:33:31 -05:00
CodePoet80 e23b85da99 move to managed stage launch 2021-02-14 11:49:17 -05:00
CodePoet80 44099722bf more scroll improvements 2021-02-14 07:51:40 -05:00
CodePoet80 94e79b4408 indicate trailing slash 2021-02-13 15:50:10 -05:00
CodePoet80 4a25b201b1 tweak some strings 2021-02-13 15:38:17 -05:00
CodePoet80 068f576615 update icon 2021-02-13 15:34:20 -05:00
CodePoet80 97e16178b2 overhaul scroll behavior, allow landscape on touchpad 2021-02-13 15:23:14 -05:00
CodePoet80 f0d166069d hide command menu fade 2021-02-04 19:15:20 -05:00
CodePoet80 795338b050 fix wrapping bug on tiny devices 2021-01-30 17:40:08 -05:00
CodePoet80 5013bc367f fix message bug 2021-01-27 17:54:14 -05:00
CodePoet80 1e41f6db90 bug fix default sound 2021-01-25 21:01:24 -05:00
CodePoet80 ec710f04fb customizable sound, other refactors 2021-01-25 19:11:27 -05:00
CodePoet80 a4ceb7ffe3 Initial commit 2021-01-25 10:23:32 -05:00
76 changed files with 7623 additions and 2650 deletions

No files matched your search

+3 -1
View File
@@ -1,2 +1,4 @@
.DS_Store
secrets.js
.DS_Store
framework_config.json
_bin/
+2 -2
View File
@@ -1,6 +1,6 @@
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/system-model.js $DIR/../app/models/system-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
+2 -2
View File
@@ -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/system-model.js $DIR/../app/models/system-model.js
cp $DIR/../../webos-common/Mojo/com.wosa.mojo.additions.js $DIR/../app/com.wosa.mojo.additions.js
palm-run $DIR/../
palm-run $DIR/../
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 webOS Archive
Copyright (c) 2022 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
+35 -7
View File
@@ -1,12 +1,40 @@
# Share Space app for webOS
# Simple Chat client app for webOS
![Share Space Icon](icon.png)
![App Icon](icon.png)
Share Space is a sharing service app for legacy Palm/HP webOS devices, which depends on the back-end service listed below.
You can download it for your webOS Device from the [webOS Archive App Museum II](appcatalog.webosarchive.org).
SimpleChat client for legacy Palm/HP webOS devices, depends on back-end services:
Tested on Pre, Pre2, Pre3, Veer and Touchpad.
+ [simplechat-service](https://github.com/codepoet80/simplechat-service)
Uses [Sharing Service](https://github.com/webosarchive/sharing-service) which is hosted by [webOSArchive](http://www.webosarchive.org) for the webOS community without guarantee of privacy or performance. Illegal or illicit use strictly prohibited.
+ [simplechat-discordbot](https://github.com/codepoet80/simplechat-discordbot) (Optional)
You can also self-host the service, see the [instructions here](https://github.com/webosarchive/sharing-service/blob/main/README.md).
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/).
Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

+55 -71
View File
@@ -3,101 +3,85 @@ In the app assistant, we setup some app-wide global objects and handle different
*/
var appModel = null;
var updaterModel = null;
var serviceModel = null;
var systemModel = null;
var MainStageName = "main";
var InDockMode = false;
var welcomed = false;
Mojo.Additions = Additions;
function AppAssistant() {
appModel = new AppModel();
updaterModel = new UpdaterModel();
serviceModel = new ShareServiceModel();
systemModel = new SystemModel();
Mojo.Additions = Additions;
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("Share Space is Launching! Launch params: " + JSON.stringify(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["AutoDownloadTime"]) {
appModel.AppSettingsCurrent["AutoDownloadTime"] = appModel.AppSettingsDefaults["AutoDownloadTime"];
if (!appModel.AppSettingsCurrent["BackgroundUpdate"]) {
appModel.AppSettingsCurrent["BackgroundUpdate"] = "00:30:00";
appModel.SaveSettings();
}
appModel.EstablishAlarms();
//Reset alarms
systemModel.ClearSystemAlarm("SimpleChat");
if (appModel.AppSettingsCurrent["BackgroundUpdate"] && appModel.AppSettingsCurrent["BackgroundUpdate"] != "" && appModel.AppSettingsCurrent["BackgroundUpdate"] != -1)
systemModel.SetSystemAlarmRelative("SimpleChat", appModel.AppSettingsCurrent["BackgroundUpdate"]);
if (!params || !params["action"]) {
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
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
{
Mojo.Log.info("Found existing main stage, app was already running");
Mojo.Log.info("This is a non-alarm re-launch");
var stageController = this.controller.getStageController("main");
stageController.activate(); //bring existing stage into focus
if (params)
this.handleParameterLaunch(params, stageController);
} else //If not, determine if we should make one
{
Mojo.Log.info("Did not find existing main stage, app is not running");
Mojo.Log.info("This is a non-alarm launch of version " + Mojo.Controller.appInfo.version);
var stageArguments = { name: MainStageName, lightweight: true };
this.controller.createStageWithCallback(stageArguments, function(stageController) {
stageController.pushScene(MainStageName);
if (params)
this.handleParameterLaunch(params, stageController);
}.bind(this));
}
} else {
this.handleParameterLaunch(params);
}
};
AppAssistant.prototype.handleParameterLaunch = function(params) {
Mojo.Log.info("Launch params: " + JSON.stringify(params));
//Touch2Share Launch (goes to main)
if (params["sendDataToShare"]) {
Mojo.Log.info("Launch with Touch2Share request!");
systemModel.SendDataForTouch2Share(appModel.CurrentShareURL);
}
//Alarm Launch (goes to dashboard)
else if (params.action && params.action == "BackgroundDownload"){
Mojo.Log.info("Alarm launch for background sync...");
//TODO: Check if in Dock Mode (and remember)
systemModel.GetDisplayState(function(response) {
Mojo.Log.info("Called back from GetDisplayState with response: " + JSON.stringify(response));
InDockMode = false;
if (response && response.state == "on" && response.active == false) {
InDockMode = true;
systemModel.SetDisplayState("unlock");
systemModel.SetDisplayState("on");
//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");
}
appModel.ShowDownloaderStage();
}.bind(this));
}
//JustType or other (goes to main)
else {
Mojo.Log.info("Launch with item request to be handled by Main scene...");
appModel.LaunchQuery = params;
var mainStage = this.controller.getStageProxy(MainStageName);
if (mainStage) {
var stageController = this.controller.getStageController(MainStageName);
stageController.swapScene({ transition: Mojo.Transition.crossFade, name: MainStageName });
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 {
} 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;
}
}
}
};
+140
View File
@@ -0,0 +1,140 @@
/*
This alarm scene is used for Touchpads, which will only pretend to change settings if running in the background
Launching this scene forces the Touchpad to wake up to deal with presenting it, and when it does we have a good
chance of successfully changing the settings. We can then close this window. All the smarts for this are in stage assistant.
*/
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...");
this.serviceEndpointBase = appModel.ServiceEndpointBase;
if (appModel.AppSettingsCurrent["UseCustomEndpoint"] && appModel.AppSettingsCurrent["EndpointURL"]) {
this.serviceEndpointBase = appModel.AppSettingsCurrent["EndpointURL"];
}
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) {
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");
} 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!");
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!");
}
} else {
Mojo.Log.info("No new chats on server during Dashboard message 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");
appController.closeStage("dashboard");
}
}
} else {
Mojo.Log.error("No usable response from server during Dashboard message check: " + response);
appController.closeStage("dashboard");
}
}.bind(this));
}
DashboardAssistant.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);
appModel.AppSettingsCurrent["LastKnownMessage"] = newMessages[j].uid;
Mojo.Log.info("Dashboard counting: " + newMessages[j].uid);
}
if (newMessages[j].uid == LastKnownMessage) {
startCounting = true;
}
}
return actuallyNewMessages.length;
}
DashboardAssistant.prototype.handleTap = function(event) {
Mojo.Log.info("Dashboard tapped!");
var appController = Mojo.Controller.getAppController();
var mainStage = appController.getStageProxy("main");
if (!mainStage) {
systemModel.LaunchApp(Mojo.Controller.appInfo.id);
appController.closeAllStages();
} else {
mainStage.activate();
appController.closeStage("dashboard")
}
}
DashboardAssistant.prototype.handleDrag = function(event) {
var infoElement = this.controller.get("dashboardinfo");
infoElement.style.opacity = "0.5"; //TODO: this only seems to effect the icon
}
DashboardAssistant.prototype.handleDragEnd = function(event) {
Mojo.Log.info("Dashboard drag end!");
var appController = Mojo.Controller.getAppController();
appController.closeAllStages();
}
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 renderedInfo = Mojo.View.render({ object: info, template: "dashboard/item-info" });
infoElement.innerHTML = renderedInfo;
this.controller.getSceneScroller().mojo.revealTop(true);
}
DashboardAssistant.prototype.deactivate = function(event) {
Mojo.Event.stopListening(this.controller.get("dashboardinfo"), Mojo.Event.tap, this.handleTap);
}
// Cleanup anything we did in setup function
DashboardAssistant.prototype.cleanup = function() {
Mojo.Log.info("Dashboard notification stage closing at " + new Date());
appModel.SaveSettings();
}
-253
View File
@@ -1,253 +0,0 @@
function DetailAssistant() {
/* this is the creator function for your scene assistant object. It will be passed all the
additional parameters (after the scene name) that were passed to pushScene. The reference
to the scene controller (this.controller) has not be established yet, so any initialization
that needs the scene controller should be done in the setup function below. */
}
DetailAssistant.prototype.setup = function() {
/* setup widgets here */
//Menu
this.appMenuAttributes = { omitDefaultItems: true };
this.appMenuModel = {
label: "Settings",
items: [{
label: $L('Select All'),
command: Mojo.Menu.selectAllCmd,
shortcut: 'a',
disabled: false
}, {
label: $L('Copy'),
command: Mojo.Menu.copyCmd,
shortcut: 'c',
disabled: false
}]
};
this.controller.setupWidget(Mojo.Menu.appMenu, this.appMenuAttributes, this.appMenuModel);
//Text content field
this.controller.setupWidget("divTextContent",
this.attributes = {
multiline: true,
enterSubmits: false,
focus: false
},
this.model = {
value: "",
disabled: false
}
);
//OK Button
this.controller.setupWidget("btnOK",
this.attributes = {
},
this.model = {
label : "OK",
disabled: false
}
);
//Command Menu
this.cmdMenuAttributes = {
spacerHeight: 0,
menuClass: 'no-fade'
},
this.cmdMenuModel = {
visible: true,
items: [{
items: [
{ label: 'Back', icon: 'back', command: 'do-goBack' }
]
},
{
items: [
]
},
{
items: [
{ label: 'Share', command: 'do-share' },
{ label: 'Save', icon: 'save', command: 'do-save' }
]
}
]
};
this.controller.setupWidget(Mojo.Menu.commandMenu, this.cmdMenuAttributes, this.cmdMenuModel);
/* add event handlers to listen to events from widgets */
};
DetailAssistant.prototype.activate = function(event) {
//Bind selected podcast to scene elements
Mojo.Log.info(JSON.stringify(appModel.LastShareSelected));
this.controller.get("divShareTitle").innerHTML = "Shared: " + appModel.ConvertTimeStamp(appModel.LastShareSelected.timestamp, true);
//Calculate links
if (appModel.LastShareSelected && appModel.LastShareSelected.contenttype && appModel.LastShareSelected.contenttype.indexOf("image") != -1) { //image links
var link = serviceModel.MakeShareURL(appModel.AppSettingsCurrent["Username"], appModel.LastShareSelected.guid, "image");
appModel.CurrentShareURL = link;
this.controller.get("divShareLinks").innerHTML += "• <a href='" + link + "'>View in Browser</a>";
this.controller.get("divShareLinks").innerHTML += " &nbsp;(<a href='javascript:this.doCopy(\"" + link + "\")'>Copy Link</a>)<br>";
link = this.makeDownloadURL(appModel.LastShareSelected.thumbnail, "i");
this.downloadLink = link;
} else { //text links
var link = serviceModel.MakeShareURL(appModel.AppSettingsCurrent["Username"], appModel.LastShareSelected.guid, "t");
appModel.CurrentShareURL = link;
this.downloadLink = link;
this.controller.get("divShareLinks").innerHTML = "• <a href='" + link + "'>View in Browser</a>";
this.controller.get("divShareLinks").innerHTML += " &nbsp;(<a href='javascript:this.doCopy(\"" + link + "\")'>Copy Link</a>)<br>";
}
if (appModel.AppSettingsCurrent["DebugMode"]) { //If debugging, show links
this.controller.get("divShareInfo").style.display = "block";
}
//Show actual content
if (appModel.LastShareSelected.contenttype == "application/json") {
this.controller.get("divTextContent").innerHTML = "<pre>" + JSON.stringify(appModel.LastShareSelected.content, null, 1) + "</pre>"
} else if (appModel.LastShareSelected.contenttype == "text/plain") {
this.controller.get("divTextContent").innerHTML = "<pre>" + appModel.LastShareSelected.content + "</pre>"
} else {
var useImg = appModel.LastShareSelected.content;
useImg = useImg.split("?");
useImg = useImg[0] + "?img=" + useImg[1] + "&size=" + this.setPhotoSize();
Mojo.Log.info("Rendering img: " + useImg);
this.controller.get("divImageContent").innerHTML = "<img src='" + useImg + "' style='max-width:90%;'>";
}
Mojo.Controller.getAppController().showBanner({ messageText: 'Touch2Share Ready!', icon: 'assets/notify.png' }, { source: 'notification' });
};
doCopy = function(link) {
Mojo.Log.info("Copy tapped for link " + link);
var stageController = Mojo.Controller.getAppController().getActiveStageController()
stageController.setClipboard(link);
Mojo.Controller.getAppController().showBanner({ messageText: 'Link copied!', icon: 'assets/notify.png' }, { source: 'notification' });
}
DetailAssistant.prototype.makeDownloadURL = function(thumbUrl, type) {
var newURL = thumbUrl;
newURL = newURL.replace("tthumb", type);
newURL = newURL.replace("ithumb", type);
return newURL;
}
DetailAssistant.prototype.setPhotoSize = function() {
switch(systemModel.DetectDevice()) {
case "TouchPad":
return 800;
break;
case "Pre3":
return 400;
break;
case "Pre":
return 300;
break;
case "Tiny":
return 280;
break;
default:
return 400;
}
}
//Handle menu and button bar commands
DetailAssistant.prototype.handleCommand = function(event) {
Mojo.Log.info("handling command button press for command: " + event.command);
if (event.type == Mojo.Event.command) {
var stageController = Mojo.Controller.getAppController().getActiveStageController();
switch (event.command) {
case 'do-goBack':
stageController.popScene();
break;
case 'do-share':
var itemsToShow = [
{ label: 'Open in Browser', command: 'do-browserOpen' },
{ label: 'Email Link', command: 'do-emailLink' },
{ label: 'Message Link', command: 'do-messageLink' },
{ label: 'Copy Link', command: 'do-copyLink' }
]
if (appModel.LastShareSelected.contenttype.indexOf("image") == -1) {
itemsToShow.push({ label: 'Copy Content', command: 'do-copyContent' });
}
this.controller.popupSubmenu({
onChoose: this.handlePopupChoose.bind(this, event.item),
//placeNear: Mojo.Menu.commandMenu,
items: itemsToShow
});
break;
case 'do-save':
var usePath = "sharespace/" + appModel.AppSettingsCurrent["Username"];
if (appModel.AppSettingsCurrent["UseCustomDownloadPath"] && appModel.AppSettingsCurrent["CustomDownloadPath"] != "")
usePath = appModel.AppSettingsCurrent["CustomDownloadPath"];
Mojo.Controller.getAppController().showBanner({ messageText: 'Downloading content...', icon: 'assets/notify.png' }, { source: 'notification' });
systemModel.DownloadFile(this.downloadLink, appModel.LastShareSelected.contenttype, usePath, appModel.LastShareSelected.guid, true);
break;
}
}
};
DetailAssistant.prototype.handlePopupChoose = function(task, command) {
Mojo.Log.info("Perform: ", command);
var stageController = Mojo.Controller.getAppController().getActiveStageController();
switch (command) {
case "do-browserOpen":
this.controller.serviceRequest("palm://com.palm.applicationManager", {
method: "launch",
parameters: {
id: 'com.palm.app.browser',
params: {
"target": appModel.CurrentShareURL
}
}
});
Mojo.Log.warn("target: " + appModel.CurrentShareURL);
break;
case "do-emailLink":
this.controller.serviceRequest("palm://com.palm.applicationManager", {
method: 'open',
parameters: {
id: "com.palm.app.email",
params: {
summary: "Check out this link",
text: appModel.CurrentShareURL
}
}
});
Mojo.Log.warn("target: " + appModel.CurrentShareURL);
break;
case "do-messageLink":
this.controller.serviceRequest('palm://com.palm.applicationManager', {
method: 'open',
parameters: {
id: 'com.palm.app.messaging',
params: {
messageText: "Check out this link: " + appModel.CurrentShareURL
}
}
});
Mojo.Log.warn("target: " + appModel.CurrentShareURL);
break;
case "do-copyLink":
stageController.setClipboard(appModel.CurrentShareURL);
Mojo.Controller.getAppController().showBanner({ messageText: 'Link copied!', icon: 'assets/notify.png' }, { source: 'notification' });
Mojo.Log.warn("target: " + appModel.CurrentShareURL);
break;
case "do-copyContent":
stageController.setClipboard(appModel.LastShareSelected.content);
Mojo.Controller.getAppController().showBanner({ messageText: 'Content copied!', icon: 'assets/notify.png' }, { source: 'notification' });
break;
}
}
DetailAssistant.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 */
};
DetailAssistant.prototype.cleanup = function(event) {
/* this function should do any cleanup needed before the scene is destroyed as
a result of being popped off the scene stack */
};
-210
View File
@@ -1,210 +0,0 @@
/*
This alarm scene is used for Touchpads, which will only pretend to change settings if running in the background
Launching this scene forces the Touchpad to wake up to deal with presenting it, and when it does we have a good
chance of successfully changing the settings. We can then close this window. All the smarts for this are in stage assistant.
*/
var downloadMgrInt = null;
function DownloadAssistant(argFromPusher) {
this.passedArguments = argFromPusher;
this.downloadList = [];
}
DownloadAssistant.prototype.setup = function() {
Mojo.Log.info("Dashboard notification stage setup at " + new Date());
this.displayDashboard(Mojo.Controller.appInfo.title, "Checking for new shares...");
//Event handlers
Mojo.Event.listen(this.controller.get("dashboardinfo"), Mojo.Event.tap, this.handleTap.bind(this));
}
DownloadAssistant.prototype.activate = function(event) {
Mojo.Log.info("Dashboard activating!");
//Set options for service model
serviceModel.ForceHTTP = appModel.AppSettingsCurrent["ForceHTTP"];
serviceModel.UseCustomEndpoint = appModel.AppSettingsCurrent["UseCustomEndpoint"];
serviceModel.CustomEndpointURL = appModel.AppSettingsCurrent["EndpointURL"];
serviceModel.CustomShortURL = appModel.AppSettingsCurrent["ShortURL"];
serviceModel.CustomCreateKey = appModel.AppSettingsCurrent["CustomCreateKey"];
serviceModel.UseCustomClientId = appModel.AppSettingsCurrent["UseCustomClientId"];
serviceModel.CustomClientId = appModel.AppSettingsCurrent["CustomClientId"];
this.fetchShares();
}
DownloadAssistant.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 renderedInfo = Mojo.View.render({ object: info, template: "download/item-info" });
infoElement.innerHTML = renderedInfo;
this.controller.getSceneScroller().mojo.revealTop(true);
}
DownloadAssistant.prototype.fetchShares = function() {
serviceModel.DoShareListRequest(appModel.AppSettingsCurrent["Username"], appModel.AppSettingsCurrent["Credential"], function(responseObj){
if (responseObj != null) {
if (responseObj.shares) {
//If we got a good looking response, find out what to download
Mojo.Log.info("Download dashboard ready to process share list: " + JSON.stringify(responseObj));
this.checkIfDownloadNeeded(appModel.AppSettingsCurrent["Username"], responseObj.shares, responseObj.accesslevel);
} else {
Mojo.Log.warn("Share list was empty in Download dashboard. Either there was no matching result, or there were server or connectivity problems.");
appModel.CloseNotificationStage();
}
} else {
Mojo.Log.error("No usable response from server while Download dashboard loading shares: " + response);
appModel.CloseNotificationStage();
}
}.bind(this), this.errorHandler.bind(this));
}
DownloadAssistant.prototype.checkIfDownloadNeeded = function(username, results, accessLevel) {
Mojo.Log.info("Determining which shares need to be downloaded...");
this.downloadList = [];
this.getFileListForUser(username, function(fileList) {
for (var i = 0; i < results.length; i++) {
if (results[i].guid) {
//Figure out what mimetype to use
if (results[i].contenttype == "image/jpeg")
ext = ".jpg";
else if (results[i].contenttype == "text/plain")
ext = ".txt";
else if (results[i].contenttype == "text/json")
ext = ".json";
else {
var ext = results[i].contenttype.split("/");
ext = ext[ext.length - 1];
ext = "." + ext;
}
var fileToCheck = results[i].guid + ext;
var found = false;
if (fileList.items) {
for (var f = 0;f < fileList.items.length;f ++){
if (fileList.items[f].name == fileToCheck) {
Mojo.Log.info("Already downloaded: " + fileToCheck);
found = true;
}
}
}
if (!found) {
var newURL = results[i].thumbnail;
newURL = newURL.replace("tthumb", "t");
newURL = newURL.replace("ithumb", "i");
Mojo.Log.info("Need to download: " + newURL);
this.downloadList.push(newURL);
var usePath = "sharespace/" + username;
if (appModel.AppSettingsCurrent["UseCustomDownloadPath"] && appModel.AppSettingsCurrent["CustomDownloadPath"] != "")
usePath = appModel.AppSettingsCurrent["CustomDownloadPath"];
systemModel.DownloadFile(newURL, results[i].contenttype, usePath, results[i].guid);
}
}
}
Mojo.Log.info("Files in download list: " + this.downloadList.length);
if (this.downloadList.length > 0) {
this.displayDashboard(Mojo.Controller.appInfo.title, "Downloading shares...", this.downloadList.length);
} else {
this.displayDashboard(Mojo.Controller.appInfo.title, "No new shares to download.");
}
downloadMgrInt = this.controller.window.setInterval(function() {
this.checkDownloadManagerStatus();
}.bind(this), 1500);
}.bind(this));
}
DownloadAssistant.prototype.getFileListForUser = function(username, callback) {
if (callback)
callback.bind(this);
Mojo.Log.info("Asking FileMgr service for list of files");
this.controller.serviceRequest('palm://ca.canucksoftware.filemgr', {
method: 'listFiles',
parameters: {
path: "/media/internal/sharespace/" + username + "/",
},
onSuccess: callback,
onFailure: callback
});
}
DownloadAssistant.prototype.checkDownloadManagerStatus = function() {
if (this.downloadList.length > 0) {
Mojo.Log.info("checking if download manager is done...");
this.controller.serviceRequest('palm://com.palm.downloadmanager/', {
method: 'listPending',
parameters: {},
onSuccess : function (response){
//Mojo.Log.info("List Pending success, results="+JSON.stringify(response));
if (response) {
if (response.count && response.count > 0) {
Mojo.Log.info("Remaining downloads: " + response.count);
this.displayDashboard(Mojo.Controller.appInfo.title, "Downloading shares...", response.count);
} else {
Mojo.Log.info("Download Manager completed all downloads!");
this.controller.window.clearInterval(downloadMgrInt);
if (InDockMode)
systemModel.SetDisplayState("dock");
appModel.CloseDashboardStageByName("download");
}
} else {
Mojo.Log.error("List response failure");
this.controller.window.clearInterval(downloadMgrInt);
appModel.CloseDashboardStageByName("download");
}
}.bind(this),
onFailure : function (e){
Mojo.Log.error("List Pending failure, results="+JSON.stringify(e));
this.controller.window.clearInterval(downloadMgrInt);
appModel.CloseDashboardStageByName("download");
}.bind(this)
});
} else {
if (InDockMode)
systemModel.SetDisplayState("dock");
appModel.CloseDashboardStageByName("download");
}
}
DownloadAssistant.prototype.handleTap = function(event) {
Mojo.Log.info("Dashboard tapped!");
var appController = Mojo.Controller.getAppController();
var mainStage = appController.getStageProxy("main");
if (!mainStage) {
systemModel.LaunchApp(Mojo.Controller.appInfo.id);
appController.closeAllStages();
} else {
mainStage.activate();
appController.closeStage("dashboard")
}
}
DownloadAssistant.prototype.handleDrag = function(event) {
var infoElement = this.controller.get("dashboardinfo");
infoElement.style.opacity = "0.5"; //TODO: this only seems to effect the icon
}
DownloadAssistant.prototype.handleDragEnd = function(event) {
Mojo.Log.info("Dashboard drag end!");
this.controller.window.clearInterval(downloadMgrInt);
appModel.CloseDashboardStageByName("download");
}
DownloadAssistant.prototype.errorHandler = function (errorText, callback) {
Mojo.Log.error("Error in Dashboard scene: " + errorText);
}
DownloadAssistant.prototype.deactivate = function(event) {
Mojo.Event.stopListening(this.controller.get("dashboardinfo"), Mojo.Event.tap, this.handleTap);
}
// Cleanup anything we did in setup function
DownloadAssistant.prototype.cleanup = function() {
Mojo.Log.info("Dashboard notification stage closing at " + new Date());
//Event handlers
Mojo.Event.stopListening(this.controller.get("dashboardinfo"), Mojo.Event.tap, this.handleTap);
appModel.SaveSettings();
}
+83
View File
@@ -0,0 +1,83 @@
/* Copyright 2010 Palm, Inc. All rights reserved. */
/*global Mojo, $L, Class, window, document, PalmSystem, AppAssistant, palmGetResource, Foundations, _, */
var EmoticonPickerDialogAssistant = function(sceneAssistant, onselect) {
this.sceneAssistant = sceneAssistant;
this.controller = sceneAssistant.controller;
this.onselect = onselect;
};
EmoticonPickerDialogAssistant.prototype.show = function() {
this.controller.showDialog({
template: 'main/emoticonpicker-dialog',
assistant: this
});
};
EmoticonPickerDialogAssistant.prototype.setup = function(widget) {
this.widget = widget;
var emoTable = this.controller.get('emo-table');
var emoticonList = [
"B-)",
">:(",
":'(",
":[",
":-!",
"X(",
":@",
"o_O",
":O",
">:-)",
"O:)",
"<3",
":-*",
":D",
":/",
":(",
":|",
":P",
";)",
":)"
];
var row = emoTable.insertRow();
var insertCell = this.insertCell;
emoticonList.forEach(function(emoticon) {
if (row.cells.length === 5) {
row = emoTable.insertRow(0);
}
insertCell(row, emoticon);
});
emoTable.addEventListener(Mojo.Event.tap, this.handleEmoticonSelect.bind(this));
this.controller.get('cancel_button').addEventListener(Mojo.Event.tap, this.handleClose.bind(this));
};
EmoticonPickerDialogAssistant.prototype.insertCell = function(row, emoticon) {
var cell = row.insertCell(0);
cell.innerHTML = Mojo.Format.runTextIndexer(emoticon.escapeHTML());
cell.setAttribute("emo", emoticon);
cell.style.height = "40px";
};
EmoticonPickerDialogAssistant.prototype.handleEmoticonSelect = function(event) {
event.stopPropagation(); // stop the tap because it causes the underlying text item to lose focus
event.preventDefault();
var td = event.target;
if (td && td.tagName !== "TD") {
td = event.target.up('td');
}
if (td) {
this.onselect(td.getAttribute("emo"));
}
this.widget.mojo.close();
};
EmoticonPickerDialogAssistant.prototype.handleClose = function(event) {
event.stopPropagation(); // stop the tap because it causes the underlying text item to lose focus
event.preventDefault();
this.widget.mojo.close();
};
-143
View File
@@ -1,143 +0,0 @@
function LoginAssistant(sceneAssistant, doneCallBack) {
this.doneCallBack = doneCallBack;
/* this is the creator function for your scene assistant object. It will be passed all the
additional parameters (after the scene name) that were passed to pushScene. The reference
to the scene controller (this.controller) has not be established yet, so any initialization
that needs the scene controller should be done in the setup function below. */
Mojo.Log.info("new Login assistant exists");
this.sceneAssistant = sceneAssistant; //dialog's do not have their own controller, so need access to the launching scene's controller
}
LoginAssistant.prototype.setup = function(widget) {
/* this function is for setup tasks that have to happen when the scene is first created */
this.widget = widget;
Mojo.Log.info("login assistant setup");
Mojo.Log.info("Current Move is: " + appModel.AppSettingsCurrent["Username"]);
/* setup widgets here */
this.sceneAssistant.controller.setupWidget("txtUsername",
this.attributes = {
textFieldName: "Username",
hintText: "User Name",
property: 'value',
multiline: false,
changeOnKeyPress: true,
autoReplace: false,
textCase: Mojo.Widget.steModeLowerCase,
requiresEnterKey: false,
focus: false
},
this.model = {
value: appModel.AppSettingsCurrent["Username"],
disabled: false
}
);
this.sceneAssistant.controller.setupWidget("txtCredential",
this.attributes = {
textFieldName: "Credential",
hintText: "Admin Password",
property: 'value',
multiline: false,
changeOnKeyPress: true,
autoReplace: false,
textCase: Mojo.Widget.steModeLowerCase,
requiresEnterKey: false,
focus: false
},
this.model = {
value: appModel.AppSettingsCurrent["Credential"],
disabled: false
}
);
this.sceneAssistant.controller.setupWidget("linkSpinner",
this.attributes = {
spinnerSize: "small"
},
this.model = {
spinning: true
}
);
this.sceneAssistant.controller.setupWidget("goButton", { type: Mojo.Widget.activityButton }, { label: "OK", disabled: false });
this.sceneAssistant.controller.setupWidget("cancelButton", { type: Mojo.Widget.button }, { label: "Cancel", disabled: false });
/* add event handlers to listen to events from widgets */
Mojo.Event.listen(this.sceneAssistant.controller.get("txtUsername"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.sceneAssistant.controller.get("txtCredential"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.sceneAssistant.controller.get("goButton"), Mojo.Event.tap, this.handleGoPress.bind(this));
Mojo.Event.listen(this.sceneAssistant.controller.get("cancelButton"), Mojo.Event.tap, this.handleCancelPress.bind(this));
};
LoginAssistant.prototype.activate = function(event) {
Mojo.Log.info("Login assistant activated");
/* put in event handlers here that should only be in effect when this scene is active. For
example, key handlers that are observing the document */
};
LoginAssistant.prototype.handleValueChange = function(event) {
appModel.AppSettingsCurrent[event.srcElement.title] = event.value;
}
LoginAssistant.prototype.handleCancelPress = function(event) {
this.doneCallBack(false);
this.widget.mojo.close();
}
LoginAssistant.prototype.handleGoPress = function(event) {
if (this.sceneAssistant.controller.get("txtUsername").mojo.getValue() == "") {
this.sceneAssistant.controller.get("txtUsername").mojo.focus();
this.sceneAssistant.controller.get("goButton").mojo.deactivate();
return;
}
if (this.sceneAssistant.controller.get("txtCredential").mojo.getValue() == "") {
this.sceneAssistant.controller.get("txtCredential").mojo.focus();
this.sceneAssistant.controller.get("goButton").mojo.deactivate();
return;
}
//Update UI for this state
this.tryServiceLogin();
}
LoginAssistant.prototype.tryServiceLogin = function() {
serviceModel.DoShareListRequest(appModel.AppSettingsCurrent["Username"], appModel.AppSettingsCurrent["Credential"], function(response) {
if (response.error) {
this.doneCallBack(response);
} else {
if (response && response.shares && response.shares != "") {
Mojo.Log.info("Login success!");
appModel.SaveSettings();
this.doneCallBack(true);
} else {
this.doneCallBack({"error": "Login failure. Check connectivity and your credentials. If you haven't logged in for a long time, create a new account."});
}
}
this.widget.mojo.close(); //Dismiss this dialog
}.bind(this), this.errorHandler.bind(this));
}
LoginAssistant.prototype.deactivate = function(event) {
Mojo.Log.info("Login assistant deactivated");
/* 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.sceneAssistant.controller.get("txtUsername"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.sceneAssistant.controller.get("txtCredential"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.sceneAssistant.controller.get("goButton"), Mojo.Event.tap, this.handleGoPress);
Mojo.Event.stopListening(this.sceneAssistant.controller.get("cancelButton"), Mojo.Event.tap, this.handleCancelPress);
};
LoginAssistant.prototype.cleanup = function(event) {
Mojo.Log.info("Login assistant cleaned up");
/* this function should do any cleanup needed before the scene is destroyed as
a result of being popped off the scene stack */
};
LoginAssistant.prototype.errorHandler = function (errorText, callback) {
Mojo.Log.error(errorText);
if (callback) {
callback.bind(this);
callback({"error": errorText});
} else {
Mojo.Controller.getAppController().showBanner({ messageText: errorText, icon: "assets/notify.png" }, "", "");
}
}
File diff suppressed because it is too large. Load diff
-132
View File
@@ -1,132 +0,0 @@
function NewshareAssistant(sceneAssistant, doneCallBack) {
this.doneCallBack = doneCallBack;
/* this is the creator function for your scene assistant object. It will be passed all the
additional parameters (after the scene name) that were passed to pushScene. The reference
to the scene controller (this.controller) has not be established yet, so any initialization
that needs the scene controller should be done in the setup function below. */
Mojo.Log.info("new NewShare assistant exists");
this.sceneAssistant = sceneAssistant; //dialog's do not have their own controller, so need access to the launching scene's controller
}
NewshareAssistant.prototype.setup = function(widget) {
/* this function is for setup tasks that have to happen when the scene is first created */
this.widget = widget;
Mojo.Log.info("Current Share Target is: " + appModel.AppSettingsCurrent["Username"]);
/* setup widgets here */
//Text box
var textAttrib = {
textFieldName: "ShareContent",
hintText: "Text to share",
property: 'value',
multiline: true,
changeOnKeyPress: true,
autoReplace: true,
textCase: Mojo.Widget.steModeSentenceCase,
requiresEnterKey: false,
focus: true
};
if (appModel.LastShareSelected.contenttype == "application/json") {
textAttrib.hintText = "JSON to share"
textAttrib.autoReplace = false;
textAttrib.textCase = Mojo.Widget.steModeLowerCase;
}
Mojo.Log.info("Using Last Share: " + JSON.stringify(appModel.LastShareSelected));
this.controller.setupWidget("txtShareContent",
this.attributes = textAttrib,
this.model = {
value: appModel.LastShareSelected.content,
disabled: false
}
);
this.controller.setupWidget("goButton", { type: Mojo.Widget.activityButton }, { label: "OK", disabled: false });
this.controller.setupWidget("cancelButton", { type: Mojo.Widget.button }, { label: "Cancel", disabled: false });
};
NewshareAssistant.prototype.activate = function(event) {
Mojo.Log.info("NewShare assistant activated for share: " + appModel.LastShareSelected.guid);
if (appModel.LastShareSelected.guid == "new") {
this.controller.get("divEditTitle").innerHTML = "New Share Content";
} else {
this.controller.get("divEditTitle").innerHTML = "Edit Share Content";
}
/* add event handlers to listen to events from widgets */
Mojo.Event.listen(this.controller.get("goButton"), Mojo.Event.tap, this.handleOKPress.bind(this));
Mojo.Event.listen(this.controller.get("cancelButton"), Mojo.Event.tap, this.handleCancelPress.bind(this));
//Resize event
this.controller.window.onresize = this.calculateControlsPosition.bind(this);
this.calculateControlsPosition();
};
NewshareAssistant.prototype.calculateControlsPosition = function() {
var maxHeight = 380;
if ((this.controller.window.innerHeight - 210) < maxHeight)
maxHeight = this.controller.window.innerHeight - 210;
this.controller.get("txtShareContent").style.height = maxHeight + "px";
}
NewshareAssistant.prototype.handleCancelPress = function(event) {
var stageController = Mojo.Controller.getAppController().getActiveStageController();
stageController.pushScene({ transition: Mojo.Transition.crossFade, name: "main" });
}
NewshareAssistant.prototype.handleOKPress = function(event) {
var shareContent = this.controller.get("txtShareContent").mojo.getValue();
if (shareContent && shareContent != "") {
if (appModel.LastShareSelected.contenttype == "application/json") {
try {
var testObj = JSON.parse(shareContent);
} catch (ex) {
Mojo.Controller.getAppController().showBanner({ messageText: 'JSON content not be parsed', icon: 'assets/notify.png' }, { source: 'notification' });
this.controller.get('goButton').mojo.deactivate();
this.controller.window.setTimeout(this.controller.get('txtShareContent').mojo.focus(), 500);
return false;
}
}
appModel.LastShareSelected.content = shareContent;
this.tryAddShare();
} else {
this.controller.get('goButton').mojo.deactivate();
this.controller.get("txtShareContent").mojo.focus();
}
}
NewshareAssistant.prototype.tryAddShare = function() {
serviceModel.DoShareAddRequestText(appModel.LastShareSelected.content, appModel.AppSettingsCurrent["Username"], appModel.AppSettingsCurrent["Credential"], appModel.LastShareSelected.contenttype, function(responseObj) {
if (responseObj && responseObj.guid && responseObj.guid != "") {
Mojo.Log.info("Add share success!");
if (appModel.AppSettingsCurrent["CopyLinkOnShare"]) {
var stageController = Mojo.Controller.getAppController().getActiveStageController()
stageController.setClipboard(serviceModel.MakeShareURL(appModel.AppSettingsCurrent["Username"], responseObj.guid, "text"));
Mojo.Controller.getAppController().showBanner({ messageText: 'Content shared, link copied!', icon: 'assets/notify.png' }, { source: 'notification' });
} else {
Mojo.Controller.getAppController().showBanner({ messageText: 'Content shared!', icon: 'assets/notify.png' }, { source: 'notification' });
}
} else {
this.errorHandler("Share failure: " + JSON.stringify(responseObj))
}
this.handleCancelPress();
}.bind(this), this.errorHandler.bind(this));
}
NewshareAssistant.prototype.errorHandler = function (errorText, callback) {
Mojo.Log.error(errorText);
Mojo.Controller.getAppController().showBanner({ messageText: errorText, icon: "assets/notify.png" }, "", "");
errorText = errorText.charAt(0).toUpperCase() + errorText.slice(1);
this.controller.get('goButton').mojo.deactivate();
Mojo.Additions.ShowDialogBox("Share Sevice Error", errorText);
}
NewshareAssistant.prototype.deactivate = function(event) {
Mojo.Log.info("NewShare assistant deactivated");
Mojo.Event.stopListening(this.controller.get("goButton"), Mojo.Event.tap, this.handleOKPress);
Mojo.Event.stopListening(this.controller.get("cancelButton"), Mojo.Event.tap, this.handleCancelPress);
};
NewshareAssistant.prototype.cleanup = function(event) {
Mojo.Log.info("NewShare assistant cleaned up");
/* this function should do any cleanup needed before the scene is destroyed as
a result of being popped off the scene stack */
};
-173
View File
@@ -1,173 +0,0 @@
function NewuserAssistant() {
/* this is the creator function for your scene assistant object. It will be passed all the
additional parameters (after the scene name) that were passed to pushScene. The reference
to the scene controller (this.controller) has not be established yet, so any initialization
that needs the scene controller should be done in the setup function below. */
}
NewuserAssistant.prototype.setup = function() {
/* setup widgets here */
this.controller.setupWidget("scrollTnC",
this.attributes = {
mode: 'vertical'
},
this.model = {}
);
//Agree Button
this.controller.setupWidget("btnAgree", { type: Mojo.Widget.defaultButton }, { label: "Agree", buttonClass: "affirmative", disabled: true });
//Cancel Button
this.controller.setupWidget("btnCancel", { type: Mojo.Widget.defaultButton }, { label: "Cancel", buttonClass: "negative", disabled: false });
//OK Button
this.controller.setupWidget("btnOK", { type: Mojo.Widget.activityButton }, { label: "Create Space", buttonClass: "affirmative", disabled: false });
//Username Field
this.controller.setupWidget("txtUsername",
this.attributes = {
hintText: $L("Choose a username"),
multiline: false,
enterSubmits: false,
focus: true,
textCase: Mojo.Widget.steModeLowerCase,
autoReplace: false
},
this.model = {
disabled: false
}
);
//Username Field
this.controller.setupWidget("txtPassword",
this.attributes = {
hintText: $L("Enter a Password"),
multiline: false,
enterSubmits: false,
focus: false,
textCase: Mojo.Widget.steModeLowerCase,
autoReplace: false
},
this.model = {
disabled: false
}
);
//Menu
this.appMenuAttributes = { omitDefaultItems: true };
this.appMenuModel = {};
this.controller.setupWidget(Mojo.Menu.appMenu, this.appMenuAttributes, this.appMenuModel);
};
NewuserAssistant.prototype.activate = function(event) {
/* add event handlers to listen to events from widgets */
Mojo.Event.listen(this.controller.get("btnAgree"), Mojo.Event.tap, this.agreeClick.bind(this));
Mojo.Event.listen(this.controller.get("btnCancel"), Mojo.Event.tap, this.cancelClick.bind(this));
Mojo.Event.listen(this.controller.get("btnOK"), Mojo.Event.tap, this.okClick.bind(this));
//bind tryagain listener
this.controller.get("imgTryagain").addEventListener("click", this.generateSharePhrase.bind(this));
//Get terms and conditions from service and put into UI
serviceModel.GetTnC(function(response) {
this.controller.get("divTnC").innerHTML = response;
Mojo.Additions.DisableWidget("btnAgree", false);
}.bind(this));
this.sharephrase = "";
//Resize event
this.controller.window.onresize = this.calculateControlsPosition.bind(this);
this.calculateControlsPosition();
};
NewuserAssistant.prototype.calculateControlsPosition = function() {
var maxHeight = 380;
if ((this.controller.window.innerHeight - 180) < maxHeight)
maxHeight = this.controller.window.innerHeight - 180;
this.controller.get("scrollTnC").style.height = maxHeight + "px";
}
NewuserAssistant.prototype.agreeClick = function(event) {
Mojo.Additions.DisableWidget("btnAgree", true);
this.controller.get("divCredentials").style.display = "block";
this.controller.get("btnOK").style.display = "block";
this.generateSharePhrase();
this.controller.getSceneScroller().mojo.revealElement(this.controller.get("txtPassword"));
}
NewuserAssistant.prototype.generateSharePhrase = function() {
//Get new credentials from service and put into UI
serviceModel.GetRandomWords(function(response) {
if (response) {
this.controller.get("divSharephrase").innerHTML = response;
this.sharephrase = response;
} else {
Mojo.Additions.ShowDialogBox("Service Error", "Did not receive random words from service.");
}
}.bind(this));
}
NewuserAssistant.prototype.okClick = function(event) {
//validate input
var disallowed = ["con", "prn", "aux", "nul", "com", "do", "done", "elif", "else", "esac", "fi", "for", "function", "if", "in", "select", "then", "until", "while", "time"];
this.username = this.controller.get('txtUsername').mojo.getValue().toLowerCase();
if (this.username == "" || disallowed.indexOf(this.username) != -1 || this.username.match(/[^a-z]/g) || this.username.indexOf(" ") != -1) {
Mojo.Additions.ShowDialogBox("Invalid username", "Your username must be one word, alphabetic characters only, and cannot contain any reserved words for Unix or Windows operating systems.");
this.controller.get('btnOK').mojo.deactivate();
} else {
if (this.sharephrase && this.sharephrase != "") {
this.password = this.controller.get('txtPassword').mojo.getValue().toLowerCase();
if (this.password == "" || disallowed.indexOf(this.password) != -1 || this.password.match(/[^A-Za-z0-9 ]/g) || this.password.indexOf(" ") != -1) {
Mojo.Additions.ShowDialogBox("Invalid password", "Your password must be one word, alpha-numeric characters only, and cannot contain any reserved words for Unix or Windows operating systems.");
this.controller.get('btnOK').mojo.deactivate();
} else {
serviceModel.DoNewUserRequest(this.username, this.sharephrase, this.password, function(responseObj) {
if (responseObj != null) {
appModel.AppSettingsCurrent["Username"] = this.username;
appModel.AppSettingsCurrent["Credential"] = this.password;
appModel.AppSettingsCurrent["SharePhrase"] = this.sharephrase;
appModel.SaveSettings();
Mojo.Log.info("Successfully created account ", appModel.AppSettingsCurrent["Username"], appModel.AppSettingsCurrent["Credential"], appModel.AppSettingsCurrent["SharePhrase"]);
var stageController = Mojo.Controller.getAppController().getActiveStageController();
stageController.swapScene({ transition: Mojo.Transition.zoomFade, name: "welcome" });
} else {
Mojo.Log.error("No usable response from server while uploading share");
Mojo.Controller.getAppController().showBanner({ messageText: "Bad response uploading image", icon: "assets/notify.png" }, "", "");
}
this.controller.get('btnOK').mojo.deactivate();
}.bind(this), this.errorHandler.bind(this));
}
} else {
Mojo.Additions.ShowDialogBox("Missing Share Phrase", "The share phrase is provided by the server, but appears to be missing. This likely means the server is unreachable, down, or improperly configured.");
this.controller.get('btnOK').mojo.deactivate();
}
}
}
NewuserAssistant.prototype.cancelClick = function(event) {
var stageController = Mojo.Controller.getAppController().getActiveStageController();
stageController.swapScene({ transition: Mojo.Transition.zoomFade, name: "main" });
}
NewuserAssistant.prototype.errorHandler = function (errorText, callback) {
Mojo.Log.error(errorText);
Mojo.Controller.getAppController().showBanner({ messageText: errorText, icon: "assets/notify.png" }, "", "");
errorText = errorText.charAt(0).toUpperCase() + errorText.slice(1);
Mojo.Additions.ShowDialogBox("Share Sevice Error", errorText);
this.controller.get('btnOK').mojo.deactivate();
}
NewuserAssistant.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("btnAgree"), Mojo.Event.tap, this.agreeClick);
Mojo.Event.stopListening(this.controller.get("btnCancel"), Mojo.Event.tap, this.cancelClick);
Mojo.Event.stopListening(this.controller.get("btnOK"), Mojo.Event.tap, this.cancelClick);
this.controller.window.removeEventListener("resize", this.calculateControlsPosition);
this.controller.window.onresize = null;
};
NewuserAssistant.prototype.cleanup = function(event) {
/* this function should do any cleanup needed before the scene is destroyed as
a result of being popped off the scene stack */
};
+212 -160
View File
@@ -8,87 +8,139 @@ function PreferencesAssistant() {
PreferencesAssistant.prototype.setup = function() {
/* setup widgets here */
//Refresh timeout picker
this.controller.setupWidget("listRefresh",
//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 = {
label: $L("Refresh"),
label: $L("Foreground Update"),
choices: [
{ label: "Manual", value: "" },
{ 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 },
{ label: "3 minutes", value: 180000 },
{ label: "5 minutes", value: 300000 }
{ label: "5 minutes", value: 180000 },
]
},
this.model = {
value: appModel.AppSettingsCurrent["RefreshTimeout"],
value: appModel.AppSettingsCurrent["ForegroundUpdate"],
disabled: false
}
);
//Toggles
var disableDL = true;
if (appModel.FileMgrPresent)
disableDL = false;
this.controller.setupWidget("toggleAutoDownload",
var backgroundValue;
if (!appModel.AppSettingsCurrent["BackgroundUpdate"] || appModel.AppSettingsCurrent["BackgroundUpdate"] == 0 || appModel.AppSettingsCurrent["BackgroundUpdate"] == "")
backgroundValue = "-1";
else
backgroundValue = appModel.AppSettingsCurrent["BackgroundUpdate"]
this.controller.setupWidget("listBackgroundUpdate",
this.attributes = {
trueValue: true,
falseValue: false
},
this.model = {
value: appModel.AppSettingsCurrent["UseAutoDownload"],
disabled: disableDL
}
);
//List boxes
this.controller.setupWidget("listAutoDownloadTime",
this.attributes = {
label: $L("Download Interval"),
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: "03:00:00" },
{ label: "6 Hours", value: "06:00:00" },
{ label: "12 Hours", value: "12:00:00" },
{ label: "24 Hours", value: "23:59:59" }
{ label: "3 Hours", value: "02:00:00" },
{ label: "5 Hours", value: "05:00:00" },
]
},
this.model = {
value: appModel.AppSettingsCurrent["AutoDownloadTime"],
disabled: disableDL
}
);
if (appModel.FileMgrPresent)
this.controller.get("divDownloadExplain").innerHTML = "Frequent automatic downloads can have significant impact on battery life.";
//More toggles
this.controller.setupWidget("toggleCopyLinkOnShare",
this.attributes = {
trueValue: true,
falseValue: false
},
this.model = {
value: appModel.AppSettingsCurrent["CopyLinkOnShare"],
value: backgroundValue,
disabled: false
}
);
this.controller.setupWidget("toggleForceHTTP",
//Enter Action listEnterSubmits
this.controller.setupWidget("listEnterSubmits",
this.attributes = {
trueValue: true,
falseValue: false
label: $L("Enter Submits"),
choices: [
{ label: "Never", value: "never" },
{ label: "Collapsed", value: "collapsed" },
{ label: "Always", value: "always" }
]
},
this.model = {
value: appModel.AppSettingsCurrent["ForceHTTP"],
value: appModel.AppSettingsCurrent["EnterSubmits"],
disabled: false
}
);
this.controller.setupWidget("toggleCustomClientId",
//Emoji toggle
this.controller.setupWidget("toggleEmojis",
this.attributes = {
trueValue: true,
falseValue: false
},
this.model = {
value: appModel.AppSettingsCurrent["UseCustomClientId"],
value: appModel.AppSettingsCurrent["ShowEmojis"],
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: [
{ label: "Choose...", value: "choose" },
{ label: "Off", value: "off" }
]
};
if (appModel.AppSettingsCurrent["AlertSound"] != "off") {
var useVal = appModel.AppSettingsCurrent["AlertSound"];
var labelVal = useVal;
if (Mojo.Environment.DeviceInfo.platformVersionMajor < 3) {
labelVal = useVal.substring(0, 8) + "...";
}
this.soundChoices.choices.unshift({ label: labelVal, value: useVal });
}
this.controller.setupWidget("listAlertSound",
this.attributes = this.soundChoices,
this.model = {
value: appModel.AppSettingsCurrent["AlertSound"],
disabled: false
}
);
//API Toggles
this.controller.setupWidget("toggleClientAPI",
this.attributes = {
trueValue: true,
falseValue: false
},
this.model = {
value: appModel.AppSettingsCurrent["UseClientAPIKey"],
disabled: false
}
);
@@ -102,23 +154,25 @@ PreferencesAssistant.prototype.setup = function() {
disabled: false
}
);
//Text fields
this.controller.setupWidget("txtCustomClientId",
//API Text fields
this.controller.setupWidget("txtClientAPI",
this.attributes = {
hintText: $L("Your Service Client Id"),
hintText: $L("Your Client Id"),
multiline: false,
enterSubmits: false,
autoReplace: false,
focus: false,
autoFocus: false,
textCase: Mojo.Widget.steModeLowerCase
},
this.model = {
value: appModel.AppSettingsCurrent["CustomClientId"],
disabled: !appModel.AppSettingsCurrent["UseCustomEndpoint"]
value: appModel.AppSettingsCurrent["ClientAPIKey"],
disabled: !appModel.AppSettingsCurrent["UseClientAPIKey"]
}
);
this.controller.setupWidget("txtEndpointURL",
this.attributes = {
hintText: $L("http://your-server.com/"),
hintText: $L("http://your-chat-server.com/"),
multiline: false,
enterSubmits: false,
autoReplace: false,
@@ -129,43 +183,6 @@ PreferencesAssistant.prototype.setup = function() {
disabled: !appModel.AppSettingsCurrent["UseCustomEndpoint"]
}
);
this.controller.setupWidget("txtShortURL",
this.attributes = {
hintText: $L("http://short.link/"),
multiline: false,
enterSubmits: false,
autoReplace: false,
textCase: Mojo.Widget.steModeLowerCase
},
this.model = {
value: appModel.AppSettingsCurrent["ShortURL"],
disabled: !appModel.AppSettingsCurrent["UseCustomEndpoint"]
}
);
this.controller.setupWidget("txtCustomCreateKey",
this.attributes = {
hintText: $L("Your Service Create Key"),
multiline: false,
enterSubmits: false,
autoReplace: false,
textCase: Mojo.Widget.steModeLowerCase
},
this.model = {
value: appModel.AppSettingsCurrent["CustomCreateKey"],
disabled: !appModel.AppSettingsCurrent["UseCustomEndpoint"]
}
);
//Drawer
this.controller.setupWidget("drawerSelfHost",
this.attributes = {
modelProperty: 'open',
unstyled: false
},
this.model = {
open: appModel.AppSettingsCurrent["UseCustomEndpoint"]
}
);
//OK Button
this.controller.setupWidget("btnOK", { type: Mojo.Widget.activityButton }, { label: "Done", disabled: false });
//Menu
@@ -178,26 +195,27 @@ 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));
Mojo.Event.listen(this.controller.get("toggleClientAPI"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("toggleCustomEndPoint"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("btnOK"), Mojo.Event.tap, this.okClick.bind(this));
};
PreferencesAssistant.prototype.activate = function(event) {
/* put in event handlers here that should only be in effect when this scene is active. For
example, key handlers that are observing the document */
/* add event handlers to listen to events from widgets */
Mojo.Event.listen(this.controller.get("listRefresh"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("toggleAutoDownload"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("listAutoDownloadTime"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("toggleCopyLinkOnShare"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("toggleForceHTTP"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("toggleCustomClientId"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("txtCustomClientId"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("toggleCustomEndPoint"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("txtEndpointURL"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("txtShortURL"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("txtCustomCreateKey"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.controller.get("btnOK"), Mojo.Event.tap, this.okClick.bind(this));
//this.showBetaFeatures();
};
PreferencesAssistant.prototype.showBetaFeatures = function() {
@@ -208,51 +226,46 @@ PreferencesAssistant.prototype.handleValueChange = function(event) {
Mojo.Log.info(event.srcElement.id + " value changed to " + event.value);
switch (event.srcElement.id) {
case "toggleCustomClientId":
{
var thisWidgetSetup = this.controller.getWidgetSetup("txtCustomClientId");
thisWidgetSetup.model.disabled = !event.value;
this.controller.modelChanged(thisWidgetSetup.model);
if (event.value)
this.controller.get('txtCustomClientId').mojo.focus();
break;
}
case "toggleAutoDownload":
{
var thisWidgetSetup = this.controller.getWidgetSetup("listAutoDownloadTime");
thisWidgetSetup.model.disabled = !event.value;
this.controller.modelChanged(thisWidgetSetup.model);
break;
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.Controller.getAppController().showBanner({ messageText: "Re-launch app to apply this setting" }, "", "");
break;
case "listAlertSound":
if (event.value == "choose") {
this.setAlarmSound();
} else {
appModel.AppSettingsCurrent["AlertSound"] = event.value;
}
break;
case "toggleClientAPI":
var thisWidgetSetup = this.controller.getWidgetSetup("txtClientAPI");
thisWidgetSetup.model.disabled = !event.value;
this.controller.modelChanged(thisWidgetSetup.model);
if (event.value)
this.controller.get('txtClientAPI').mojo.focus();
break;
case "toggleCustomEndPoint":
{
//Toggle enabled on related text boxes
var thisWidgetSetup = this.controller.getWidgetSetup("drawerSelfHost");
thisWidgetSetup.model.open = event.value;
this.controller.modelChanged(thisWidgetSetup.model);
var thisWidgetSetup = this.controller.getWidgetSetup("txtEndpointURL");
thisWidgetSetup.model.disabled = !event.value;
this.controller.modelChanged(thisWidgetSetup.model);
var thisWidgetSetup = this.controller.getWidgetSetup("txtShortURL");
thisWidgetSetup.model.disabled = !event.value;
this.controller.modelChanged(thisWidgetSetup.model);
var thisWidgetSetup = this.controller.getWidgetSetup("txtCustomCreateKey");
thisWidgetSetup.model.disabled = !event.value;
this.controller.modelChanged(thisWidgetSetup.model);
if (event.value)
this.controller.get('txtEndpointURL').mojo.focus();
break;
}
var thisWidgetSetup = this.controller.getWidgetSetup("txtEndpointURL");
thisWidgetSetup.model.disabled = !event.value;
this.controller.modelChanged(thisWidgetSetup.model);
if (event.value)
this.controller.get('txtEndpointURL').mojo.focus();
break;
case "txtEndpointURL":
var lastChar = event.value[event.value.length - 1]
if (lastChar != "/") {
event.value = event.value + "/";
Mojo.Log.warn("Custom end point URL was missing trailing slash, it has been added. Value is now: " + event.value);
}
if(!appModel.AppSettingsCurrent["ShortURL"] || appModel.AppSettingsCurrent["ShortURL"] == "") {
this.controller.get('txtShortURL').mojo.setValue(event.value);
appModel.AppSettingsCurrent["ShortURL"] = event.value;
}
break;
}
@@ -260,14 +273,56 @@ PreferencesAssistant.prototype.handleValueChange = function(event) {
Mojo.Log.info(event.srcElement.title + " now: " + event.value);
appModel.AppSettingsCurrent[event.srcElement.title] = event.value;
appModel.SaveSettings();
//Show/hide beta features
this.showBetaFeatures();
};
// opens ringtone picker.
PreferencesAssistant.prototype.setAlarmSound = function() {
var self = this;
var params = {
defaultKind: 'ringtone',
onSelect: function(file) {
var fileToUse = file.fullPath.replace("/media/internal/ringtones/", "").replace(".mp3", "");
appModel.AppSettingsCurrent["AlertSound"] = fileToUse;
appModel.SaveSettings();
var useVal = fileToUse;
var labelVal = useVal;
try {
if (Mojo.Environment.DeviceInfo.platformVersionMajor < 3) {
labelVal = useVal.substring(0, 8) + "...";
}
} catch (ex) {
Mojo.Log.error("Could not set ringtone value");
}
self.soundChoices.choices[0].label = labelVal;
self.soundChoices.choices[0].value = useVal;
var thisWidgetSetup = self.controller.getWidgetSetup("listAlertSound");
var thisWidgetModel = thisWidgetSetup.model;
thisWidgetModel.value = fileToUse;
self.controller.setWidgetModel("listAlertSound", thisWidgetModel);
self.controller.modelChanged(thisWidgetModel);
Mojo.Log.info("alarm sound changed to: " + fileToUse)
}
}
var appController = Mojo.Controller.getAppController();
var stageController = appController.getStageProxy("main");
Mojo.FilePicker.pickFile(params, stageController);
}
//Handle menu and button bar commands
PreferencesAssistant.prototype.handleCommand = function(event) {
if (event.type == Mojo.Event.command) {
switch (event.command) {
case 'do-goBack':
Mojo.Controller.stageController.popScene();
this.okClick();
break;
case 'do-resetSettings':
appModel.ResetSettings(appModel.AppSettingsDefaults);
@@ -277,30 +332,27 @@ PreferencesAssistant.prototype.handleCommand = function(event) {
};
PreferencesAssistant.prototype.okClick = function(event) {
var stageController = Mojo.Controller.getAppController().getActiveStageController();
var appController = Mojo.Controller.getAppController();
var stageController = appController.getStageProxy("main");
stageController.popScene();
}
PreferencesAssistant.prototype.deactivate = function(event) {
if (this.controller.get('txtEndpointURL').mojo.getValue() == "") {
appModel.AppSettingsCurrent["UseCustomEndpoint"] = false;
}
appModel.SaveSettings();
appModel.EstablishAlarms();
/* 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("listRefresh"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.controller.get("toggleAutoDownload"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.controller.get("listAutoDownloadTime"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.controller.get("toggleForceHTTP"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.controller.get("toggleCustomClientId"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.controller.get("txtCustomClientId"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.controller.get("listThemePreference"), 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("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("txtShortURL"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.controller.get("txtCustomCreateKey"), Mojo.Event.propertyChange, this.handleValueChange);
Mojo.Event.stopListening(this.controller.get("btnOK"), Mojo.Event.tap, this.okClick);
Mojo.Event.stopListening(this.controller.get("btnOK"), Mojo.Event.tap, this.okClick.bind(this));
};
PreferencesAssistant.prototype.cleanup = function(event) {
+8 -5
View File
@@ -1,11 +1,14 @@
Mojo.Additions = Additions;
function StageAssistant() {
/* this is the creator function for your stage assistant object */
}
StageAssistant.prototype.activate = function() {
Mojo.Log.error("Stage activated");
stageController = Mojo.Controller.stageController;
if (stageController.getScenes().length < 1)
stageController.pushScene('main');
}
StageAssistant.prototype.setup = function() {
/* this function is for setup tasks that have to happen when the stage is first created */
this.controller.pushScene({ name: "main" });
this.controller.setWindowOrientation("free");
Mojo.Log.info("Stage assistant created!");
};
+79
View File
@@ -0,0 +1,79 @@
function UserAssistant(sceneAssistant, doneCallBack) {
this.doneCallBack = doneCallBack;
/* this is the creator function for your scene assistant object. It will be passed all the
additional parameters (after the scene name) that were passed to pushScene. The reference
to the scene controller (this.controller) has not be established yet, so any initialization
that needs the scene controller should be done in the setup function below. */
Mojo.Log.info("new User assistant exists");
this.sceneAssistant = sceneAssistant; //dialog's do not have their own controller, so need access to the launching scene's controller
}
UserAssistant.prototype.setup = function(widget) {
/* this function is for setup tasks that have to happen when the scene is first created */
this.widget = widget;
Mojo.Log.info("User assistant setup");
Mojo.Log.info("Current username is: " + appModel.AppSettingsCurrent["SenderName"]);
/* setup widgets here */
this.sceneAssistant.controller.setupWidget("txtUserName",
this.attributes = {
textFieldName: "userName",
hintText: " Enter nickname",
property: 'value',
multi: false,
enterSubmits: true,
changeOnKeyPress: false,
textReplacement: false,
requiresEnterKey: false,
focus: true
},
this.model = {
value: appModel.AppSettingsCurrent["SenderName"],
disabled: false
}
);
this.sceneAssistant.controller.setupWidget("goButton", { type: Mojo.Widget.defaultButton }, { label: "OK", disabled: false });
//this.sceneAssistant.controller.setupWidget("cancelButton", { type: Mojo.Widget.button }, { label: "Cancel", disabled: false });
/* add event handlers to listen to events from widgets */
Mojo.Event.listen(this.sceneAssistant.controller.get("txtUserName"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.listen(this.sceneAssistant.controller.get("goButton"), Mojo.Event.tap, this.handleGoPress.bind(this));
//Mojo.Event.listen(this.sceneAssistant.controller.get("cancelButton"), Mojo.Event.tap, this.handleCancelPress.bind(this));
};
UserAssistant.prototype.handleValueChange = function(event) {
this.handleGoPress();
};
UserAssistant.prototype.handleGoPress = function(event) {
var newName = this.sceneAssistant.controller.get('txtUserName').mojo.getValue();
if (newName && newName != "" && newName != " " && newName.toLowerCase() != "webos user") {
//Remember the name they entered
appModel.AppSettingsCurrent["SenderName"] = newName;
appModel.SaveSettings();
this.doneCallBack(newName);
this.widget.mojo.close();
} else {
Mojo.Controller.getAppController().showBanner({ messageText: "Provide a unique username!" }, "", "");
}
}
UserAssistant.prototype.activate = function(event) {
this.sceneAssistant.controller.get('txtUserName').mojo.focus();
/* put in event handlers here that should only be in effect when this scene is active. For
example, key handlers that are observing the document */
};
UserAssistant.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.sceneAssistant.controller.get("txtUserName"), Mojo.Event.propertyChange, this.handleValueChange.bind(this));
Mojo.Event.stopListening(this.sceneAssistant.controller.get("goButton"), Mojo.Event.tap, this.handleGoPress.bind(this));
//Mojo.Event.stopListening(this.sceneAssistant.controller.get("cancelButton"), Mojo.Event.tap, this.handleCancelPress.bind(this));
};
UserAssistant.prototype.cleanup = function(event) {
Mojo.Log.info("user assistant cleaned up");
/* this function should do any cleanup needed before the scene is destroyed as
a result of being popped off the scene stack */
};
+87 -14
View File
@@ -7,33 +7,106 @@ function VersionAssistant(startup) {
//New Features
this.changelog = [
{
version: "Version 1.0.2 Changes",
version: "Version 1.9.0",
detail: [
"Fixes a bug that prevents background downloads when Always Use HTTP is on",
"Share images in the chat, right from your webOS device!",
]
},
{
version: "Version 1.0.1 Changes",
version: "Version 1.8.6",
detail: [
"Add download button to detail scene",
"Fix a layout issue",
"Fix a bug parsing certain kinds of links.",
]
},
{
version: "Version 1.0.0 Features",
version: "Version 1.8.5",
detail: [
"Wirelessly add photos to Exhibition from anywhere with automatic downloads -- just turn it on in Preferences (requires FileMgr)",
"Touch2Share content between your devices, either loading it in a web page, or right in the app (turn on 'Handle URLs' in the menu)",
"Share photos you take on your device via email, text message, or other web apps by copying the link the app makes for you -- grab it from the content detail scene, or turn on 'Copy Link on Share' in Preferences",
"Start a new share from JustType -- turn it on in your JustType settings",
"Host your own server for more control and privacy!"
"Add support for sharing from JustType and other apps.",
]
},
{
version: "Coming Soon",
version: "Version 1.8.0",
detail: [
"Shared Clipboard mode will minimize to a Dashboard to make it quick and easy to share text and links between your devices",
"Share with other users, without needing to log out and back in",
"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."
]
}
];
-68
View File
@@ -1,68 +0,0 @@
function WelcomeAssistant(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;
this.startupMessage = "Your account has been created!";
// setup command menu
this.cmdMenuModel = {
visible: false,
items: [
{},
{
label: $L("Got it!"),
command: 'do-continue'
},
{}
]
};
};
WelcomeAssistant.prototype.setup = function() {
//this.titleElement = this.controller.get('title');
this.dataElement = this.controller.get('welcome-data');
//this.titleElement.innerHTML = $L('Version Info');
var useURL = serviceModel.buildURL(null, "");
useURL = useURL.replace(".php", "");
var html = '<p>';
html += '<b>Name:</b> <em>' + appModel.AppSettingsCurrent["Username"] + "</em><br>";
html += '<b>Share Phrase:</b> <em>' + appModel.AppSettingsCurrent["SharePhrase"] + "</em><br>";
html += '<b>Admin Password:</b> <em>' + appModel.AppSettingsCurrent["Credential"] + "</em><br>";
html += '<b>URL:</b> <em>' + useURL + "</em><br></p>";
// 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);
//}
};
WelcomeAssistant.prototype.activate = function(event) {
this.timer = this.controller.window.setTimeout(this.showContinue.bind(this), 4 * 1000);
};
WelcomeAssistant.prototype.deactivate = function(event) {};
WelcomeAssistant.prototype.cleanup = function(event) {};
WelcomeAssistant.prototype.showContinue = function() {
// show the command menu
this.controller.setMenuVisible(Mojo.Menu.commandMenu, true);
};
WelcomeAssistant.prototype.handleCommand = function(event) {
if (event.type == Mojo.Event.command) {
switch (event.command) {
case 'do-continue':
var stageController = Mojo.Controller.getAppController().getActiveStageController();
stageController.swapScene({ transition: Mojo.Transition.zoomFade, name: "main" });
break;
}
}
};
+1 -1
View File
@@ -12,7 +12,7 @@ Mojo Additions
this.Additions = function() {}
Mojo.Log.info("#### Mojo Additions added");
console.log("** Mojo Additions loaded **");
Additions.ShowDialogBox = function(title, message) {
var stageController = Mojo.Controller.getAppController().getActiveStageController();
+85 -58
View File
@@ -2,6 +2,7 @@
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
*/
@@ -11,41 +12,58 @@ var AppModel = function() {
this.DefaultScene = "main";
//Define your app-wide, non-persisted settings here
this.UpdateCheckDone = false;
this.LaunchQuery = "";
this.LastShareSelected = null;
this.CurrentShareURL = null;
this.FileMgrPresent = true;
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 = {
Username: "",
Credential: "",
SharePhrase: "",
RefreshTimeout: 60000,
UseAutoDownload: false,
AutoDownloadTime: "01:00:00",
CopyLinkOnShare: true,
ForceHTTP: false,
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: "",
ShortURL: "",
UseCustomClientId: false,
CustomClientId: "",
CustomCreateKey: "",
UseCustomDownloadPath: false,
CustomDownloadPath: null,
LastVersionRun: "0.0.1",
DebugMode: false,
SenderName: "webOS User",
FirstRun: true,
MyMessages: null,
LastKnownMessage: null,
LastVersionRun: 0
};
}
AppModel.prototype.ShowDownloaderStage = function() {
Mojo.Log.info("App Model checking if we should to show Dashboard stage...");
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));
}
@@ -53,28 +71,57 @@ AppModel.prototype.ShowDownloaderStage = function() {
AppModel.prototype.checkForMessages = function(connMgrResponse) {
Mojo.Log.info("App Model got response from connection manager: " + JSON.stringify(connMgrResponse));
if (connMgrResponse && connMgrResponse.isInternetConnectionAvailable) {
this.actuallyShowDownloaderStage();
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.actuallyShowDownloaderStage = function() {
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("download");
var dashboardStage = this.controller.getStageProxy("dashboard");
var pushDashScene = function(stageController) {
stageController.pushScene('download', "download/download-scene");
stageController.pushScene('dashboard', "dashboard/dashboard-scene");
}.bind(this);
if (!dashboardStage) {
Mojo.Log.info("Download dashboard not open, creating it...");
Mojo.Log.info("Dashboard stage not open, creating it...");
this.controller.createStageWithCallback({
name: 'download',
name: 'dashboard',
lightweight: true,
height: 100,
soundclass: "assets/silent.mp3"
}, pushDashScene, 'dashboard');
} else {
Mojo.Log.info("Download dashboard already open, activating it...");
var dashboardStageController = this.controller.getStageController("download");
Mojo.Log.info("Dashboard stage already open, activating it...");
var dashboardStageController = this.controller.getStageController("dashboard");
if (dashboardStageController) {
dashboardStageController.activate();
dashboardStageController.delegateToSceneAssistant("activate");
@@ -82,41 +129,19 @@ AppModel.prototype.actuallyShowDownloaderStage = function() {
}
}
AppModel.prototype.CloseDashboardStageByName = function(stageName) {
AppModel.prototype.CloseNotificationStage = function() {
this.controller = Mojo.Controller.getAppController();
var dashboardStage = this.controller.getStageProxy(stageName);
var dashboardStage = this.controller.getStageProxy("dashboard");
if (!dashboardStage) {
Mojo.Log.info(stageName + " dashboard not open, nothing to do");
Mojo.Log.info("Dashboard stage not open, nothing to do");
} else {
Mojo.Log.info(stageName + " dashboard open, closing it...");
this.controller.closeStage(stageName);
Mojo.Log.info("Dashboard stage open, closing it...");
this.controller.closeStage("dashboard");
}
}
AppModel.prototype.EstablishAlarms = function() {
//Reset alarms
systemModel.ClearSystemAlarm("BackgroundDownload");
if (appModel.AppSettingsCurrent["UseAutoDownload"] && appModel.AppSettingsCurrent["Username"] != "" && appModel.AppSettingsCurrent["Credential"]) {
Mojo.Log.warn("Re-establishing background download alarm with time: " + appModel.AppSettingsCurrent["AutoDownloadTime"]);
systemModel.SetSystemAlarmRelative("BackgroundDownload", appModel.AppSettingsCurrent["AutoDownloadTime"]);
} else {
Mojo.Log.warn("Not setting background download alarm since conditions weren't met.");
}
}
AppModel.prototype.ConvertTimeStamp = function(timeStamp, isUTC) {
if (isUTC) {
var offset = new Date().getTimezoneOffset();
timeStamp = Date.parse(timeStamp);
timeStamp = timeStamp - ((offset * 60) * 1000);
timeStamp = new Date(timeStamp);
}
timeStamp = timeStamp.toLocaleString();
timeStamp = timeStamp.split("GMT");
timeStamp = timeStamp[0];
return timeStamp;
}
//#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.
@@ -194,4 +219,6 @@ AppModel.prototype.ResetSettings = function() {
//Restart main scene
stageController.pushScene(this.DefaultScene);
Mojo.Log.info("re-opened default scene");
}
}
//#endregion
+175
View File
@@ -0,0 +1,175 @@
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);
}
-449
View File
@@ -1,449 +0,0 @@
/*
ShareBoard Model - Mojo
Version 1.0
Created: 2021
License: MIT
Description: A model to interact with a share service
*/
var ShareServiceModel = function() {
this.urlBase = Mojo.Controller.appInfo.serviceURL;
this.shortUrlBase = Mojo.Controller.appInfo.shortURL;
};
//Properties
ShareServiceModel.prototype.ForceHTTP = false;
ShareServiceModel.prototype.UseCustomShare = false;
ShareServiceModel.prototype.UseCustomEndpoint = false;
ShareServiceModel.prototype.CustomEndpointURL = "";
ShareServiceModel.prototype.CustomShortURL = "";
ShareServiceModel.prototype.CustomCreateKey = "";
ShareServiceModel.prototype.UseCustomClientId = false;
ShareServiceModel.prototype.CustomClientId = "";
//ShareServiceModel.prototype.ServiceCompatWarning = 0;
ShareServiceModel.prototype.buildURL = function(username, actionType) {
var urlBase = this.urlBase;
if (this.UseCustomEndpoint == true && this.CustomEndpointURL != "") {
urlBase = this.CustomEndpointURL;
}
//Make sure we don't end up with double slashes in the built URL if there's a custom endpoint
var urlTest = urlBase.split("://");
if (urlTest[urlTest.length - 1].indexOf("/") != -1) {
urlBase = urlBase.substring(0, urlBase.length - 1);
}
var path = urlBase + "/" + actionType + ".php";
if (username)
path += "?username=" + username;
if (this.ForceHTTP)
path = path.replace ("https:", "http:");
return path;
}
ShareServiceModel.prototype.MakeShareURL = function(username, guid, type) {
var urlBase = this.shortUrlBase;
if (this.CustomShortURL == true && this.CustomShortURL != "") {
urlBase = this.CustomShortURL;
}
if (type.indexOf("image") != -1)
urlBase = urlBase + "download.php?";
else
urlBase = urlBase + "t.php?";
var data = username + "|" + guid;
data = btoa(data);
urlBase = urlBase + data;
if (urlBase.indexOf("==") == urlBase.length - 2)
urlBase = urlBase.slice(0, urlBase.length - 2)
return urlBase;
}
//HTTP request for list files
ShareServiceModel.prototype.DoShareListRequest = function(username, credential, callback, errorhandler) {
if (callback)
callback = callback.bind(this);
if (!errorhandler) {
errorhandler = function(errorText) {
Mojo.Log.warn(errorText);
Mojo.Controller.getAppController().showBanner({ messageText: errorText }, "", "");
}
} else {
errorhandler = errorhandler.bind(this);
}
var useURL = this.buildURL(username, "get-shares");
Mojo.Log.info("Calling sharing service at " + useURL + " with key " + this.getCurrentClientKey());
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", useURL);
xmlhttp.setRequestHeader("client-id", this.getCurrentClientKey());
xmlhttp.setRequestHeader("credential", credential);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status >= 400) {
errorhandler(xmlhttp.status + " Error getting share list: " + responseObj.error, callback);
return false;
} else {
if (xmlhttp.responseText && xmlhttp.responseText != "") {
try {
var responseObj = JSON.parse(xmlhttp.responseText);
if (responseObj.error) {
errorhandler("Share service error: " + responseObj.error, callback);
return false;
} else {
//Mojo.Log.info("Share List success! " + xmlhttp.responseText);
if (callback) {
callback(responseObj);
} else {
Mojo.Controller.getAppController().showBanner({ messageText: "Shares retreived!" }, "", "");
}
return true;
}
} catch (ex) {
errorhandler("Error parsing share list response: " + ex + ", response: " + xmlhttp.responseText, callback);
return false;
}
} else {
errorhandler("Share list response was empty", callback);
return false;
}
}
}
}.bind(this);
}
//HTTP request for add file
ShareServiceModel.prototype.DoShareAddRequestText = function(content, username, credential, contenttype, callback, errorhandler) {
if (callback)
callback = callback.bind(this);
if (!errorhandler) {
errorhandler = function(errorText) {
Mojo.Log.warn(errorText);
Mojo.Controller.getAppController().showBanner({ messageText: errorText }, "", "");
}
}
var useURL = this.buildURL(username, "share-text");
Mojo.Log.info("Adding text share: " + content + " of type " + contenttype + " from URL " + useURL);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", useURL);
xmlhttp.setRequestHeader("client-id", this.getCurrentClientKey());
xmlhttp.setRequestHeader("credential", credential);
xmlhttp.setRequestHeader("content-type", contenttype);
xmlhttp.send(content);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status >= 400) {
errorhandler(xmlhttp.status + " Error adding share text: " + responseObj.error);
return false;
} else {
Mojo.Log.info("Share service sent response while sharing text: " + xmlhttp.responseText);
if (xmlhttp.responseText && xmlhttp.responseText != "") {
try {
var responseObj = JSON.parse(xmlhttp.responseText);
if (responseObj.error) {
errorhandler("Error sharing text: " + responseObj.error);
return false;
} else {
Mojo.Log.info("Share text success! " + xmlhttp.responseText);
if (callback) {
callback(responseObj);
} else {
Mojo.Controller.getAppController().showBanner({ messageText: "Content shared!" }, "", "");
}
return true;
}
} catch (ex) {
errorhandler("Error parsing add share response: " + ex);
return false;
}
} else {
errorhandler("Add share response was empty");
return false;
}
}
}
}.bind(this);
}
//Upload a file
ShareServiceModel.prototype.DoShareAddRequestImage = function (fullFilePath, username, credential, contenttype, callback, errorhandler) {
if (callback)
callback = callback.bind(this);
if (!errorhandler) {
errorhandler = function(errorText) {
Mojo.Log.warn(errorText);
Mojo.Controller.getAppController().showBanner({ messageText: errorText }, "", "");
}
}
var useURL = this.buildURL(username, "share-image");
Mojo.Log.info("Adding image share: " + fullFilePath + " of type " + contenttype + " from URL " + useURL);
this.uploadRequest = new Mojo.Service.Request('palm://com.palm.downloadmanager/', {
method: 'upload',
parameters: {
fileName: fullFilePath,
url: useURL,
fileLabel: "image",
contentType: contenttype,
postParameters: [
{"key":"username", "data": username},
{"key":"credential" , "data": credential},
],
customHttpHeaders : [
'client-id: ' + this.getCurrentClientKey(),
],
subscribe: true
},
onSuccess: function(response) {
Mojo.Log.info("Upload progress", JSON.stringify(response));
if ((response.completed && response.completed == true) || (response.completionCode && response.completionCode != 0)) {
if (response.error) {
errorhandler(response.error);
return false;
} else if (response.completionCode && response.completionCode != 0) {
var errMsg = "error code " + response.completionCode;
switch(Math.abs(response.completionCode)) {
case 1:
errMsg = "General Error";
break;
case 2:
errMsg = "Connection Timeout";
break;
case 3:
errMsg = "Corrupt File";
break;
case 4:
errMsg = "File System Error";
break;
case 5:
errMsg = "HTTP Error";
break;
case 6:
errMsg = "Connection Offline";
break;
}
errorhandler(errMsg);
return false;
} else {
if (response.responseString) {
Mojo.Log.info("Upload response: " + response.responseString);
var responseObj = JSON.parse(response.responseString);
if (responseObj.error) {
errorhandler(responseObj.error);
return false;
} else {
if (callback) {
callback(responseObj);
} else {
Mojo.Controller.getAppController().showBanner({ messageText: "Image uploaded!" }, "", "");
}
return true;
}
} else {
errorhandler("Error uploading image: server response was empty");
return false;
}
}
}
},
onFailure: function(response) {
errorhandler("Error uploading image share: " + response);
return false;
}
});
}
//HTTP request for list files
ShareServiceModel.prototype.DoShareDeleteRequest = function(itemid, username, credential, callback, errorhandler) {
if (callback)
callback = callback.bind(this);
if (!errorhandler) {
errorhandler = function(errorText) {
Mojo.Log.warn(errorText);
Mojo.Controller.getAppController().showBanner({ messageText: errorText }, "", "");
}
}
var useURL = this.buildURL(username, "delete-share-item");
Mojo.Log.info("Calling sharing service at " + useURL + " for item " + itemid + " with key " + this.getCurrentClientKey());
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", useURL);
xmlhttp.setRequestHeader("client-id", this.getCurrentClientKey());
xmlhttp.setRequestHeader("credential", credential);
xmlhttp.setRequestHeader("itemid", itemid);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status >= 400) {
errorhandler(xmlhttp.status + " Error deleting share: " + responseObj.error);
return false;
} else {
Mojo.Log.info("Share service sent response while deleting share: " + xmlhttp.responseText);
if (xmlhttp.responseText && xmlhttp.responseText != "") {
try {
var responseObj = JSON.parse(xmlhttp.responseText);
if (responseObj.error) {
errorhandler("Error deleting share: " + responseObj.error);
return false;
} else {
Mojo.Log.info("Share Delete success! " + xmlhttp.responseText);
if (callback) {
callback(responseObj);
} else {
Mojo.Controller.getAppController().showBanner({ messageText: "Content deleted!" }, "", "");
}
return true;
}
} catch (ex) {
errorhandler("Error parsing delete share response: " + ex);
return false;
}
} else {
errorhandler("Delete share response was empty");
return false;
}
}
}
}.bind(this);
}
//HTTP request for new user
ShareServiceModel.prototype.DoNewUserRequest = function(username, sharephrase, password, callback, errorhandler) {
if (callback)
callback = callback.bind(this);
if (!errorhandler) {
errorhandler = function(errorText) {
Mojo.Log.warn(errorText);
Mojo.Controller.getAppController().showBanner({ messageText: errorText }, "", "");
}
}
var useURL = this.buildURL(null, "new-user");
Mojo.Log.info("Creating user: " + username + " with share-phrase " + sharephrase + " and password " + password + " from URL " + useURL);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", useURL);
xmlhttp.setRequestHeader("client-id", this.getCurrentClientKey());
var request = {
"username":username,
"sharephrase":sharephrase,
"password":password,
"createkey":this.getCurrentCreateKey()
}
xmlhttp.send(JSON.stringify(request));
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status >= 400) {
errorhandler(xmlhttp.status + " Error creating user: " + responseObj.error);
return false;
} else {
Mojo.Log.info("Share service sent response while creating user: " + xmlhttp.responseText);
if (xmlhttp.responseText && xmlhttp.responseText != "") {
try {
var responseObj = JSON.parse(xmlhttp.responseText);
if (responseObj.error) {
errorhandler("Error creating user: " + responseObj.error);
return false;
} else {
Mojo.Log.info("New user success! " + xmlhttp.responseText);
if (callback) {
callback(responseObj);
} else {
Mojo.Controller.getAppController().showBanner({ messageText: "User created!" }, "", "");
}
return true;
}
} catch (ex) {
errorhandler("Error parsing create user response: " + ex);
return false;
}
} else {
errorhandler("Create user response was empty");
return false;
}
}
}
}.bind(this);
}
//HTTP request to get Terms and Conditions
ShareServiceModel.prototype.GetTnC = function(callback) {
if (callback)
callback = callback.bind(this);
var useURL = this.buildURL(null, "tandc");
Mojo.Log.info("Getting Terms and Conditions with query: " + useURL);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", useURL);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (callback)
callback(xmlhttp.responseText);
}
}.bind(this);
}
//HTTP request to get random share phrase
ShareServiceModel.prototype.GetRandomWords = function(callback) {
if (callback)
callback = callback.bind(this);
var theQuery = this.buildURL(null, "random-words");
Mojo.Log.info("Getting Random words query: " + theQuery);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", theQuery);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (callback)
callback(xmlhttp.responseText);
}
}.bind(this);
}
//HTTP request to get random share phrase
ShareServiceModel.prototype.QueryShareData = function(query, callback) {
if (callback)
callback = callback.bind(this);
var theQuery = query;
theQuery = theQuery.replace("download.php", "q.php");
theQuery = theQuery.replace("image.php", "q.php");
theQuery = theQuery.replace("t.php", "q.php");
Mojo.Log.warn("Querying share item with URL: " + theQuery);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", theQuery);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
try {
var itemData = JSON.parse(xmlhttp.responseText);
if (callback)
callback(itemData);
} catch (ex) {
Mojo.Log.error("Got bad item query response payload: " + ex, xmlhttp.responseText);
}
}
}.bind(this);
}
ShareServiceModel.prototype.getCurrentClientKey = function() {
var retVal = atob(appKeys['shareBoardClientKey']);
if (this.UseCustomEndpoint) {
retVal = this.CustomClientId;
Mojo.Log.info("Using custom shareboard client key: " + retVal);
}
//Mojo.Log.info("Using shareboard client key: " + retVal);
return retVal;
}
ShareServiceModel.prototype.getCurrentCreateKey = function() {
var retVal = atob(appKeys['shareBoardCreateKey']);
if (this.UseCustomEndpoint) {
retVal = this.CustomCreateKey;
Mojo.Log.info("Using custom shareboard create key: " + retVal);
}
//Mojo.Log.info("Using shareboard create key: " + retVal);
return retVal;
}
@@ -3,7 +3,7 @@
<div class="dashboard-newitem" style="display:#{showCount}">
<span>#{count}</span>
</div>
<div id="dashboard-icon" class="palm-dashboard-icon dashboard-icon-download">
<div id="dashboard-icon" class="palm-dashboard-icon dashboard-icon-chat">
</div>
</div>
<div class="palm-dashboard-text-container">
-26
View File
@@ -1,26 +0,0 @@
<div class="palm-hasheader" style="margin-bottom:60px">
<div id="divShareTitle" class="palm-header center" onclick="Mojo.Controller.stageController.swapScene({ transition: Mojo.Transition.crossFade, name: 'main' });">
Share Details
</div>
</div>
<!-- only visible in debug mode -->
<div class="palm-group" id="divShareInfo" style="display:none">
<div class="palm-group-title">
<span x-mojo-loc=''>Debug Links</span>
</div>
<div id="divShareLinks" name="divShareLinks">
</div>
</div>
<div class="palm-group" id="divTextDetail">
<div class="palm-group-title">
<span x-mojo-loc=''>Content</span>
</div>
<div id="divTextContent" name="divTextContent" style="background-color:white; border: 1px solid dimgray; margin: 0px;">
<div id="divImageContent" style="width:100%; margin:auto; align-content: center; text-align: center;margin-top: 6px !important;">
<img src="icon-256.png" style="width:128px;height:128px" /><br/>
</div>
</div>
</div>
-31
View File
@@ -1,31 +0,0 @@
<div class="palm-dialog-content">
<div id="login-title" class="palm-dialog-title">
Log In to a Share Space
</div>
<div class="palm-dialog-seperator"></div>
<div class="textfield-group" x-mojo-focus-highlight="true">
<div class="title">
<div id="txtUsername" name="txtUsername" x-mojo-element="TextField" title="Username"></div>
</div>
</div>
<div class="textfield-group" x-mojo-focus-highlight="true">
<div class="title">
<div id="txtCredential" name="txtCredential" x-mojo-element="TextField" title="Credential"></div>
</div>
</div>
<div class="palm-group" id="linkError" style="display:none" name="linkError">
<div class="palm-group-title"><span style="color:white">Error</span></div>
<div class="errorresponse">
There was no usable response from the Service before its timeout.
</div>
</div>
<div class="palm-dialog-buttons">
<div x-mojo-element="Button" id="goButton"></div>
<div x-mojo-element="Button" id="cancelButton"></div>
</div>
</div>
+8
View File
@@ -0,0 +1,8 @@
<div>
<table width="100%" id="emo-table">
</table>
<div id="cancel_button" class="palm-button" x-mojo-tap-highlight="momentary">
<span x-mojo-loc="">Cancel</span>
</div>
</div>
+3 -7
View File
@@ -1,10 +1,6 @@
<div class="palm-row" x-mojo-tap-highlight='momentary'>
<div class="palm-row" style="min-height: 68px;">
<div class="palm-row-wrapper">
<div class="task-row">
<div style="height:48px; float:left;"><img class="thumbnail" src="#{thumbnail}" style="width:48px; height: 48px; margin-right: 8px;"></div>
<div title="#{guid}"><span style="font-size:18px;">#{timestamp}</span>
<p style="margin:0px; padding: 0px;padding-bottom: 3px;">#{contenttype}</p>
</div>
</div>
<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>
</div>
</div>
+1 -1
View File
@@ -1,3 +1,3 @@
<div class="palm-list">
#{-listElements}
<div> #{-listElements}</div>
</div>
+17 -9
View File
@@ -1,17 +1,25 @@
<div class="palm-page-header">
<div class="header-icon sharespace"></div>
<div class="palm-page-header multi-line">
<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=''>Share Space</span>
<span x-mojo-loc='' style="text-transform:none;" id="spnTitle">webOS SimpleChat</span>
</div>
</div>
<div id="showShareList" name="showShareList" style="display:none">
<div id="showChatList" name="showChatList" style="display:block;">
<div class="palm-group">
<div class="palm-group-title"><span x-mojo-loc='' id="spnUsername">Task List</span></div>
<div id="shareList" x-mojo-element="List" style="padding: 1px;margin:-12px;"></div>
<div class="palm-group-title"><span x-mojo-loc=''>Chat Log</span></div>
<div x-mojo-element="Scroller" id="chatScroller" class="scrollerClass" name="chatScroller" style="height: 100px;padding: 0px;margin:-8px;">
<div id="chatList" x-mojo-element="List"></div>
</div>
</div>
</div>
<div id="divSpinnerContainer" style="margin-top: 100px; width: 130px;margin-left: auto;margin-right: auto; align-items: center;">
<div x-mojo-element="Spinner" class="spinnerClass" id="workingSpinner" name="workingSpinner"></div>
</div>
<div class="palm-group" style="min-height:64px">
<div class="palm-group-title" id="divComposeTitle"><span x-mojo-loc='' id="spanCompose">Compose</span> &nbsp;<img src="assets/twisty-down.png" id="imgTwisty"></div>
<div x-mojo-element="TextField" id="txtMessage" class="textFieldClass" name="txtMessage"></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>
</div>
&nbsp;
-24
View File
@@ -1,24 +0,0 @@
<div class="palm-page-header">
<div class="header-icon sharespace"></div>
<div class="header-text">
<span x-mojo-loc=''>Share Space</span>
</div>
</div>
<div class="palm-group">
<div class="palm-group-title" id="divEditTitle">New Content</div>
<div class="palm-list">
<div class="palm-row single">
<div class="palm-row-wrapper textfield-group" x-mojo-focus-highlight="true">
<div class="title">
<div class="search-bar">
<div class="textfield-search" id="txtShareContent" x-mojo-element="TextField" style="height: 300px;" title="ShareContent"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div x-mojo-element="Button" id="goButton" class="buttonClass" name="goButton"></div>
<div x-mojo-element="Button" id="cancelButton" class="buttonClass" name="cancelButton"></div>
-87
View File
@@ -1,87 +0,0 @@
<div class="palm-page-header">
<div class="header-icon sharespace"></div>
<div class="header-text">
<span x-mojo-loc=''>Share Space - New User</span>
</div>
</div>
<div class="palm-group">
<div class="palm-group-title">
<span x-mojo-loc=''>Terms and Conditions (Scroll)</span>
</div>
<div x-mojo-element="Scroller" class="scrollerClass" id="scrollTnC" name="scrollTnC" style="height:200px;margin:-15px 10px 10px -15px;padding:0px;">
<div id="divTnC">
<ul>
<li>Loading Terms and Conditions...</li>
</ul>
</div>
<div x-mojo-element="Button" id="btnAgree" name="btnAgree" style="margin-left: 20%; margin-right:14%"></div>
</div>
</div>
<div class="palm-group" id="divCredentials" style="display:none">
<div class="palm-group-title">
<span x-mojo-loc=''>Credentials</span>
</div>
<div class="palm-list">
<div class="palm-row first">
<div class="palm-row-wrapper">
<div class="title" style="float:left; margin-left: 8px; margin-top: 14px;padding:0px;"><span class="label ">Username</span></div>
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper" style="height: 12px">
<div class="textfield-group" x-mojo-focus-highlight="true">
<div class="title">
<div id="txtUsername" name="txtUsername" x-mojo-element="TextField" title="Username"></div>
</div>
</div>
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper" style="height: 12px">
<div class="title" class="truncating-text" style="float:left; margin-left: 8px; margin-top: 14px;padding:0px"><span class="label ">Share phrase</span></div>
<img id="imgTryagain" src="assets/tryagain.png" style="height:24px; width:24px; margin-top: 12px; margin-left: 12px;">
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper">
<div id="divSharephrase" style="margin: 12px 14px;font-style: italic;">&nbsp;</div>
<div class="explainer" style="margin-left:10px; padding-bottom: 12px;">Anyone who knows this phrase can share with you.</div>
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper" style="height: 12px">
<div class="title" class="truncating-text" style="float:left; margin-left: 8px; margin-top: 14px;padding:0px"><span class="label ">Admin Password</span></div>
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper">
<div class="textfield-group" x-mojo-focus-highlight="true">
<div class="title">
<div id="txtPassword" name="txtPassword" x-mojo-element="TextField" title="Password"></div>
</div>
</div>
</div>
</div>
<div class="palm-row last">
<div class="palm-row-wrapper">
<div id="divPasswordInstructions" style="padding:6px 10px 12px 10px;line-height: 16px">
<span class="explainer">Keep this one safe, you'll use it to delete shares or configure your space.</span>
</div>
</div>
</div>
</div>
</div>
<div x-mojo-element="Button" id="btnOK" name="btnOK" style="display: none;"></div>
<div x-mojo-element="Button" id="btnCancel" name="btnCancel"></div>
+38 -40
View File
@@ -8,45 +8,60 @@
<div class="palm-group-title">
<span x-mojo-loc=''>Basic</span>
</div>
<div class="palm-list" id="listBasic">
<div class="palm-list" id="divTest">
<div class="palm-row first">
<div class="palm-row-wrapper">
<div id="listRefresh" x-mojo-element="ListSelector" title="RefreshTimeout" class="right"></div>
<div x-mojo-element="ListSelector" title="ThemePreference" id="listThemePreference"></div>
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper">
<div x-mojo-element="ToggleButton" id="toggleAutoDownload" title="UseAutoDownload"></div>
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Auto Download</span></div>
<div id="listForegroundUpdate" x-mojo-element="ListSelector" title="ForegroundUpdate" class="right"></div>
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper">
<div id="listAutoDownloadTime" x-mojo-element="ListSelector" title="AutoDownloadTime" class="right"></div>
<div id="listBackgroundUpdate" x-mojo-element="ListSelector" title="BackgroundUpdate" class="right"></div>
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper">
<div class="explanation-text" id="divDownloadExplain">Download features require FileMgr, which you can install from PreWare.</div>
<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="toggleCopyLinkOnShare" title="CopyLinkOnShare"></div>
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Copy Link on Share</span></div>
<div x-mojo-element="ToggleButton" id="toggleEmojis" title="ShowEmojis"></div>
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Discord Emojis</span></div>
</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">
<div x-mojo-element="ToggleButton" id="toggleForceHTTP" title="ForceHTTP"></div>
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Always use HTTP</span></div>
<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>
<div x-mojo-element="ListSelector" id="listAlertSound" class="listselectorClass" style="float:right" name="listAlertSound"></div>
</div>
</div>
</div>
</div>
@@ -59,49 +74,32 @@
<div class="palm-row first">
<div class="palm-row-wrapper">
<div x-mojo-element="ToggleButton" id="toggleCustomClientId" title="UseCustomClientId"></div>
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Custom Client API Key</span></div>
<div x-mojo-element="ToggleButton" id="toggleClientAPI" title="UseClientAPIKey"></div>
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Custom Client Id</span></div>
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper" style="margin:14px 22px 4px 12px">
<div id="txtCustomClientId" name="txtCustomClientId" x-mojo-element="TextField" title="CustomClientId"></div>
<div id="txtClientAPI" name="txtClientAPI" x-mojo-element="TextField" title="ClientAPIKey"></div>
</div>
</div>
<div class="palm-row first">
<div class="palm-row-wrapper">
<div x-mojo-element="ToggleButton" id="toggleCustomEndPoint" title="UseCustomEndpoint"></div>
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Custom Endpoint URL</span></div>
</div>
</div>
<div class="palm-row last">
<div class="palm-row-wrapper">
<div x-mojo-element="ToggleButton" id="toggleCustomEndPoint" title="UseCustomEndpoint"></div>
<div class="title" style="margin-left: -4px; float:left;"><span class="label">Custom Endpoint</span></div>
<div class="palm-row-wrapper" style="margin:14px 22px 4px 12px">
<div id="txtEndpointURL" name="txtEndpointURL" x-mojo-element="TextField" title="EndpointURL"></div>
</div>
</div>
<div x-mojo-element="Drawer" id="drawerSelfHost" class="drawerClass" name="drawerSelfHost">
<div class="palm-row">
<div class="palm-row-wrapper" style="margin:14px 22px 4px 12px">
<div id="txtEndpointURL" name="txtEndpointURL" x-mojo-element="TextField" title="EndpointURL"></div>
</div>
</div>
<div class="palm-row">
<div class="palm-row-wrapper" style="margin:14px 22px 4px 12px">
<div id="txtShortURL" name="txtShortURL" x-mojo-element="TextField" title="ShortURL"></div>
</div>
</div>
<div class="palm-row last">
<div class="palm-row-wrapper" style="margin:14px 22px 4px 12px">
<div id="txtCustomCreateKey" name="txtCustomCreateKey" x-mojo-element="TextField" title="CustomCreateKey"></div>
</div>
</div>
</div>
<div class="explanation-text">For more information on self-hosting, please visit <a href="https://github.com/webosarchive/webos-sharespace">https://github.com/webosarchivewebos-sharespace</a></div>
</div>
</div>
<div class="explanation-text">For more information on self-hosting, please visit <a href="https://github.com/codepoet80/simplechat-service">https://github.com/codepoet80/simplechat-service</a></div>
<div x-mojo-element="Button" id="btnOK" name="btnOK"></div>
+21
View File
@@ -0,0 +1,21 @@
<div class="palm-dialog-content">
<div id="hue-title" class="palm-dialog-title multi-line">
Getting Acquainted
</div>
<div class="palm-dialog-seperator" style="height: 8px;"></div>
<div class="palm-body-text">
SimpleChat is a lightweight message board for webOS. It keeps a log of recent messages, and allows you to post public messages.<br> How do you want to identify yourself?
</div>
<div class="textfield-group" x-mojo-focus-highlight="true" id="divUserInfo" style="display:block; margin-left: 15px; margin-right: 15px;">
<div class="title">
<div id="txtUserName" name="txtUserName" x-mojo-element="TextField" title="senderName"></div>
</div>
</div>
<div class="palm-dialog-seperator" style="height: 18px;"></div>
<div class="palm-dialog-buttons">
<div x-mojo-element="Button" id="goButton"></div>
</div>
</div>
+1 -1
View File
@@ -7,7 +7,7 @@
</div>
<div class="palm-header-spacer"></div>
<div id="data" style="margin-right: 12px"></div>
<div id="data"></div>
<div class="my-scene-fade-bottom" x-mojo-scroll-fade="bottom"></div>
</div>
-26
View File
@@ -1,26 +0,0 @@
<div class="palm-page-header">
<div class="header-icon sharespace"></div>
<div class="header-text">
<span x-mojo-loc=''>Share Space - Welcome</span>
</div>
</div>
<div class="welcome">
<div class="my-scene-fade-top" x-mojo-scroll-fade="top"></div>
<h3>Getting Started</h3>
<div class="welcome-text">
<p>Your Share Space has been created! Keep your credentials somewhere safe:</p>
</div>
<div id="welcome-data" class="welcome-text"></div>
<div class="welcome-text">
<p>Anyone who has your <b>Name</b> and <b>Share Phrase</b> can share content with you from their webOS device, or from the web.</p>
<p>Any time content is shared to your Share Space, a public URL will be generated that you can give to others.
This URL will contain your Share Space <b>Name</b>, but <i>not</i> your <b>Share Phrase</b>.</p>
<p>Only users with your <b>Admin Password</b> can delete content, or manage your Share Space.</p>
</div>
<div class="my-scene-fade-bottom" x-mojo-scroll-fade="bottom"></div>
</div>
+14 -15
View File
@@ -1,26 +1,25 @@
{
"id": "com.palm.webos.sharespace",
"version": "1.0.3",
"vendor": "webOS Archive",
"id": "com.palm.app.notalexnoyle.almostsimplechat",
"version": "1.9.1",
"vendor": "NotAlexNoyle",
"type": "web",
"main": "index.html",
"title": "Share Space",
"icon": "icon.png",
"miniicon": "assets/notify.png",
"noWindow": true,
"splashicon": "icon-256.png",
"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",
"serviceURL": "https://share.webosarchive.org/",
"shortURL": "https://wosa.link/",
"tapToShareSupported": true,
"universalSearch": {
"universalSearch" : {
"action": {
"displayName": "New Share",
"url": "com.palm.webos.sharespace",
"url": "com.palm.app.notalexnoyle.almostsimplechat",
"launchParam": {
"newshare": "#{searchTerms}"
}
}
},
"startupMessage": "<img src='icon.png' style='float:right; margin-left: 6px'>Welcome to ShareSpace -- a powerful app for getting content on and off your webOS device! You can interact with this app from anywhere at <a href='http://share.webosarchive.org'>share.webosarchive.org</a>!<br>Here are some things you can do..."
}
}
}
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

+5225
View File
File diff suppressed because it is too large. Load diff
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

+98
View File
@@ -0,0 +1,98 @@
/* TODO: put your application-specific CSS here */
.palm-page-header .header-icon.preferences {
background: url(../icon.png) no-repeat;
background-size: 32px 32px;
}
.palm-dark .header-text {
color:lightgray !important;
}
.explanation-text {
margin-top: -5px;
padding: 14px;
font-size: 14px;
color: #000;
}
.palm-dark .explanation-text {
color: lightgray;
}
.chat-log {
margin-top: 8px;
}
.palm-dark .chat-log {
color:lightgray !important;
}
.sender {
font-weight: bold;
}
.sender.discord {
color: #6473b9;
}
.sender.discord::before {
content: url('../assets/discord.png');
}
.chat-time {
margin-top: 6px;
font-size: 12px;
font-style: italic;
color: dimgray;
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;
}
.dashboard-icon-chat {
background: url(../icon-48.png);
}
textarea {
margin-top: 0px !important;
}
.palm-dark .palm-dialog-content .palm-body-text {
color: black !important;
}
.multiline-hint-text.oblique {
color: darkgray;
}
.likes:not(:empty) {
background: url('../assets/heart.png');
background-size: 12px 12px;
background-repeat: no-repeat;
background-position: 8px;
background-position-x: 0;
padding-left: 14px;
}
#emo-table td {
text-align: center;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
{
"logLevel": 0,
"logLevel": 10,
"debuggingEnabled": false,
"timingEnabled": false,
"logEvents": false,
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

+8 -3
View File
@@ -3,18 +3,23 @@
<head>
<meta name='viewport' content='height=device-height'>
<title>Share Space</title>
<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="stylesheets/sharespace.css" media="screen" rel="stylesheet" type="text/css">
<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>
-4
View File
@@ -1,4 +0,0 @@
var appKeys = {
'shareBoardClientKey': 'base64 encode the client key from the server',
'shareBoardCreateKey': 'base64 encode the create key from the server (if needed)'
};
+3
View File
@@ -0,0 +1,3 @@
var secrets = {
'clientid': 'SecretSharedWithServer'
};
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+9 -27
View File
@@ -5,43 +5,25 @@
"scenes": "main",
"source": "app/assistants/main-assistant.js"
},
{
"source": "app/assistants/login-assistant.js",
"comment": "since this will be a dialog, not a scene, we do not include the 'scenes' member (or we get errors)"
},
{
"scene": "newuser",
"source": "app/assistants/newuser-assistant.js"
},
{
"scene": "welcome",
"source": "app/assistants/welcome-assistant.js"
},
{
"scene": "detail",
"source": "app/assistants/detail-assistant.js"
},
{
"scene": "newshare",
"source": "app/assistants/newshare-assistant.js"
},
{
"scenes": "preferences",
"source": "app/assistants/preferences-assistant.js"
},
{
"source": "app/assistants/user-assistant.js",
"comment": "since this will be a dialog, not a scene, we do not include the 'scenes' member (or we get errors)"
},
{
"scenes": "version",
"source": "app/assistants/version-assistant.js"
},
{
"scenes": "download",
"source": "app/assistants/download-assistant.js",
"comment": "this is a dashboard"
{
"source": "app/assistants/emoticonpicker-dialog-assistant.js"
},
{ "source": "app/models/shareservice-model.js" },
{ "scenes": "dashboard", "source": "app/assistants/dashboard-assistant.js" },
{ "source": "app/models/service-model.js" },
{ "source": "app/models/system-model.js" },
{ "source": "app/models/updater-model.js" },
{ "source": "app/models/app-model.js" },
{ "source": "app/models/system-model.js" },
{ "source": "secrets.js" }
]
-89
View File
@@ -1,89 +0,0 @@
/* TODO: put your application-specific CSS here */
.palm-page-header .header-icon.sharespace {
background: url(../icon.png) no-repeat;
background-size: 32px 32px;
}
.task-title.new {
color: dimgray;
font-style: italic;
}
.task-row {
padding: 8px 0px 8px 8px;
}
.checkmark {
float: right;
visibility: visible;
opacity: 0.1;
margin-top: 3px;
width: 30px;
}
.checkmark.true {
opacity: 1;
visibility: visible;
}
.explanation-text {
margin-top: -5px;
padding: 14px;
font-size: 14px;
color: #000;
}
.palm-group-title.detail {
color: #000;
margin-left: -4px;
}
.palm-row-wrapper.detail {
padding: 3px;
}
.explainer {
font-style: italic;font-size: smaller; color:dimgray;
}
#welcome-data {
margin-left: 8px;
padding-left: 3px;
margin-right: 8px;
padding-right: 3px;
border-top: 1px solid lightgray;
border-right: 1px solid lightgray;
border-bottom: 1px solid lightgray;
border-left: 1px solid lightgray;
background-color: #efefef;
}
.welcome-text {
margin: 8px 12px 12px 12px
}
.welcome-text p {
padding: 0px; margin: 4px 0px;
}
.welcome-text b {
color: #1f75bf; font-variant: small-caps;
}
.welcome-text em {
font-weight: bold;
}
h3 {
margin: 8px 12px 12px 12px
}
.dashboard-icon-download {
background: url(../assets/dash-icon.png);
}
.palm-dashboard-text {
font-size: 14px;
margin-top: -2px;
}
+160
View File
@@ -0,0 +1,160 @@
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;
}
}
};