From 3a78835d796c03e2882dd5902675779d7ea72d29 Mon Sep 17 00:00:00 2001 From: Thanh Nam Nguyen <35841468+jkelol111@users.noreply.github.com> Date: Fri, 21 Aug 2020 01:00:09 +0800 Subject: [PATCH] Update to v 1.0.7 --- CREDITS.md | 2 - LATEST_RELEASE_NOTES.md | 7 +- docs/index.md | 77 ++++++ package-lock.json | 234 +++++++++++------- package.json | 10 +- .../{native-toast.css => kaios-toaster.css} | 38 ++- src/css/global/options.css | 28 ++- src/home.html | 4 +- src/js/backbone/utils.js | 18 +- src/js/libs/kaios-toaster.js | 117 +++++++++ src/js/libs/native-toast.js | 129 ---------- src/manifest.webapp | 2 +- src/player.html | 4 +- src/settings.html | 4 +- 14 files changed, 413 insertions(+), 261 deletions(-) rename src/css/global/{native-toast.css => kaios-toaster.css} (61%) create mode 100644 src/js/libs/kaios-toaster.js delete mode 100644 src/js/libs/native-toast.js diff --git a/CREDITS.md b/CREDITS.md index 86354f3..ecab7f7 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -12,8 +12,6 @@ - `l10n.js` by Mozilla, adapted by kaios-design: https://github.com/kaios-design/gaia-l10n -- `native-toast` by egoist: https://github.com/egoist/native-toast - - `reconnecting-websocket` by pladaria: https://github.com/pladaria/reconnecting-websocket - `TaskTimer` by onury: https://github.com/onury/tasktimer diff --git a/LATEST_RELEASE_NOTES.md b/LATEST_RELEASE_NOTES.md index 9e0f79d..0bf54a2 100644 --- a/LATEST_RELEASE_NOTES.md +++ b/LATEST_RELEASE_NOTES.md @@ -2,9 +2,8 @@ *New features:* -- Changed app origin for stable release: from `kaidi.jkelol111.me` to `jkelol111.github.io`. -- Upgraded KaiAds SDK: downgrading it didn't solve the problem, might as well use the latest. -- Updated manifest (again): Last-ditch effort to see what's wrong with the KaiStore release. +- Dark theme for options menus: previously, options menus weren't themed. Now they are. +- Replaced custom native-toast with kaios-toaster: I created my own native-toast 'fork' called [kaios-toaster](https://github.com/jkelol111/kaios-toaster). It supports displaying multiline toast messages, and looks uniform with KaiOS. *Bugs:* @@ -16,7 +15,7 @@ *Using OmniSD:* -1. Download the file `kaidi-1.0.6-stable-omnisd.zip` to your SD card. +1. Download the file `kaidi-1.0.7-stable-omnisd.zip` to your SD card. 2. Open OmniSD and install. diff --git a/docs/index.md b/docs/index.md index 1ab753a..e0c24d8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,3 +2,80 @@ layout: default --- +# Kaidi +The Ko**di** remote controller for **Kai**OS (hence **Kai**-**di**) + +## Goals and project background +I have created this project in 2018 in a mission to create the first Kodi remote controller app for KaiOS. But why? Well, there are a few insprirations: + +- Most KaiOS devices are WiFi-enabled: the majority of KaiOS devices ship with Wifi and LTE/3G connectivity. This is very convenient for use as a Kodi remote, which brings me to the next reason... + +- Keypads are much better input devices, change my mind: as of now, all KaiOS devices ship with a form of keypad, be it in a T9 or QWERTY layout. This makes is a perfect replacement for a physical remote, as people would not need to look down at the display in order to figure out where to press like on a touchscreen, instead it could be part of muscle memory, much like a real remote control. + +- Lack of useful utilities for KaiOS at the time: KaiOS then was a realatively young platform that lacked a lot of apps we have come to expect from modern smart-phones, as such, I wanted to create one that would be useful and integrate well with the system theming, which plenty of KaiOS then-and-now did not. + +And with all of that in mind, I set out to create the app, with these goals: + +- The UI/UX must match well with the system and relavent KaiOS Design Guidelines: as I mentioned earlier, many apps made for KaiOS do not adhere well with the system theme and design guidelines published by KaiOS Technologies. I wanted to make something that's truly worthy of 'Made for KaiOS'. + +- The UI should be simple and easy to memorize: most navigation occur with one button presses and not a multitude of key combinations just for the sake of packing many controls into the same keypad as possible. + +- Support for as many Kodi JSON-RPC API versions as possible: not everyone may run the latest version of Kodi, especially people with set top boxes that never get updated past their initial release. As such, the functionalities of the app should be compatible with some 'recent' API versions, and not more. + +The app was written in two stages, one Alpha and the other Beta. The 'Beta' version is a complete rewrite of the original Alpha code with largely the same functionality. + +The Alpha version work dated back to 2018, as I had time right after my exams for Year 10. The original code lacked a lot of functionality, was an absolute pain to maintain as I have not applied any true coding styles to it, as I never expected any serious use from it. But as time went by, I got opinions and suggestions from users of the app, and I decided I would attempt a rewrite sometime in the future. + +Fast forward to the closing months of 2019, I once again had time to start a rewrite of the app. This time, I tried using SASS and Gulp in order to make the rewrite of the old `kaidi.css` (the Alpha had all of the app styles in one huge file) easier. Sadly, that particular rewrite did not last long as I quickly had to come back to school and face the harsh reality of having literally NO FREE TIME AT ALL. This was known informally as 'Kaidi2'. + +Later on, while the COVID-19 ravaged around the globe, I suddenly found myself having plenty of free time. And so I began the official second rewrite titled 'Beta'. The whole rewrite made the app much more modular, the code extremely readable, and the UI infinitely consistent. Moreover, a Gulp build process was created to create app builds that are minified, making for smaller package sizes. In the 'Implementation' section below, this version of the app ('Beta') would be detailed. + +'Beta' as of the time of writing is still the latest release of the app. I plan to introduce further features given available time and more test devices. + +## Implementation +### App source code structure +The app source code resides in the `src` folder within the kaidi GitHub repository (https://github.com/jkelol111/kaidi). + +The app is structured like almost every vanilla HTML/CSS/JS KaiOS app would, with a `manifest.webapp` located in the root of the source code folder that contains the details of the app, relevant permissions and more pertaining to the app. + +The HTML files which are the 'pages' of the app are also stored at the root of the source code. These define how the app looks in their individual pages and loads the relevant JS and CSS files for operation. + +Speaking of CSS, JS and various other files, they are stored in their respective folders `css`, `js`, `locales` and `icons`, all located alongside the `manifest.webapp` and HTML files. + +### Page layout +Behind every 'page' in the app, a 'headerbar' of sorts is always present, in the app's theme color. This is for visual recognition that the user is indeed using the Kaidi Remote app. A shade of cyan was chosen as it is relatively light/dark theme agnostic. + +Below the headerbar, a secondary headerbar can be added in some pages to display additional contextual information, such as the name of the page. An example of this would be the settings page, where a secondary headerbar is used to tell the user they're in the right page. These are only used sparingly in the app as KaiOS devices have limited display real estate. + +Once the headerbars have been defined, there is a content section. This can be used for the display of any page content. + +At the bottom of the page, a softkey bar is displayed for defining which button on the keypad corresponds to which action. + +### Code behind each page +Besides the settings page, most pages of the app run on JS that contains a class that extends the KodiRPC or KodiMethods class, the former of which handles various communication with the Kodi JSON-RPC APIs, including listening for specific Kodi events and handling the worker's lifecycle, as well as a providing convenient functions for sending XmlHttpRequests to Kodi and formating them properly, and the latter extends KodiRPC with shared or commonly used functionality, such as displaying the Volume Control HUD in the app. The extended class from KodiRPC or KodiMethods then is used adds the page's specific functionality in, leveraging the functions and variables provided as part of inheriting the above 2 classes. + +All JS embedded in the app are either minified libraries that are untouched from the original publisher, the rest are written following the Standard JS style, which maintains cleanliness of code and consistency. + +The stylesheets are separated into individual files, one of which named `window.css` is imported by all of the pages in app as it provides the elements which all pages will use. For other page specific elements, the HTML can declare addtional CSS files to be loaded, hence reducing memory usage for things that aren't needed, a flaw of the 'Alpha' approach with all of the app's styles in one stylesheet. + +Localization in particular is provided by using the `l10n.js` library from Mozilla, which while designed for Firefox OS, still works fine on KaiOS. Files stored in `locales` of the source define key-value pairs for the library to load depending on the selected language. At the time of writing, there is only English and Vietnamese as supported languages. + +### App building and usage +The app can be downloaded via the KaiStore (pending approval), our community BananaHackers store, or directly from GitHub releases. + +If you're feeling adventurous or want to try all the latest stuff, you could clone the `master` branch from the repository and use `gulp` to build the project. More details are in the project's actual README.md. + +Releases that are pushed to KaiStore or BananaHackers/GitHub can be considered 'stable'. + +### Project license +This project used to be licensed under the MIT license; however, as of the 'Beta' version, the license has been switched to GPLv3. + + + + + + + + + + diff --git a/package-lock.json b/package-lock.json index 4e0c3fd..eb80ffa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "kaidi", - "version": "0.4.8", + "version": "1.0.6", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -79,6 +79,12 @@ "@types/node": "*" } }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -1159,22 +1165,22 @@ } }, "es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", "object-inspect": "^1.7.0", "object-keys": "^1.1.1", "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } }, "es-to-primitive": { @@ -1290,9 +1296,9 @@ "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", - "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", "dev": true, "requires": { "debug": "^2.6.9", @@ -1317,9 +1323,9 @@ } }, "eslint-module-utils": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", - "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", "dev": true, "requires": { "debug": "^2.6.9", @@ -1344,9 +1350,9 @@ } }, "eslint-plugin-es": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz", - "integrity": "sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", "dev": true, "requires": { "eslint-utils": "^2.0.0", @@ -1354,40 +1360,41 @@ }, "dependencies": { "eslint-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", - "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" } }, "regexpp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", - "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", "dev": true } } }, "eslint-plugin-import": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", - "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz", + "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==", "dev": true, "requires": { - "array-includes": "^3.0.3", - "array.prototype.flat": "^1.2.1", + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.1", + "eslint-import-resolver-node": "^0.3.3", + "eslint-module-utils": "^2.6.0", "has": "^1.0.3", "minimatch": "^3.0.4", - "object.values": "^1.1.0", + "object.values": "^1.1.1", "read-pkg-up": "^2.0.0", - "resolve": "^1.12.0" + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" }, "dependencies": { "debug": { @@ -1466,6 +1473,15 @@ "read-pkg": "^2.0.0" } }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -1475,9 +1491,9 @@ } }, "eslint-plugin-node": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.0.0.tgz", - "integrity": "sha512-chUs/NVID+sknFiJzxoN9lM7uKSOEta8GC8365hw1nDfwIPIjjpRSwwPvQanWv8dt/pDe9EV4anmVSwdiSndNg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", "dev": true, "requires": { "eslint-plugin-es": "^3.0.0", @@ -1489,18 +1505,18 @@ }, "dependencies": { "eslint-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.0.0.tgz", - "integrity": "sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" } }, "ignore": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true } } @@ -2600,9 +2616,9 @@ "dev": true }, "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { "pump": "^3.0.0" @@ -2953,32 +2969,50 @@ } }, "gulp-terser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gulp-terser/-/gulp-terser-1.2.0.tgz", - "integrity": "sha512-lf+jE2DALg2w32p0HRiYMlFYRYelKZPNunHp2pZccCYrrdCLOs0ItbZcN63yr2pbz116IyhUG9mD/QbtRO1FKA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/gulp-terser/-/gulp-terser-1.3.2.tgz", + "integrity": "sha512-hLx9Ww9PX304R3E7pMyL+jFftH47QXQCgKE6IZajbz7OoqAPMdr+sTxBpaujgIVkdbnJwJ7AFhfrcyy/cjBgZQ==", "dev": true, "requires": { + "is-promise": "^4.0.0", "plugin-error": "^1.0.1", - "terser": "^4.0.0", - "through2": "^3.0.1", + "terser": ">=4", + "through2": "^4.0.2", "vinyl-sourcemaps-apply": "^0.2.1" }, "dependencies": { + "is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "through2": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", - "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { - "readable-stream": "2 || 3" + "readable-stream": "3" } } } }, "gulp-zip": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gulp-zip/-/gulp-zip-5.0.1.tgz", - "integrity": "sha512-M/IWLh9RvOpuofDZkgDirtiyz9J3yIqnDOJ3muzk2D/XnZ1ruqPlPLRIpXnl/aZU+xXwKPdOIxjRzkUcVEQyZQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/gulp-zip/-/gulp-zip-5.0.2.tgz", + "integrity": "sha512-rZd0Ppuc8Bf7J2/WzcdNaeb+lcEXf1R8mV/PJ9Kdu7PmnInWVeLSmiXIka/2QSe6uhAsGVFAMffWSaMzAPGTBg==", "dev": true, "requires": { "get-stream": "^5.1.0", @@ -2989,11 +3023,12 @@ }, "dependencies": { "through2": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", - "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", "dev": true, "requires": { + "inherits": "^2.0.4", "readable-stream": "2 || 3" } } @@ -3319,9 +3354,9 @@ "dev": true }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", "dev": true }, "is-data-descriptor": { @@ -3450,12 +3485,12 @@ "dev": true }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { - "has": "^1.0.3" + "has-symbols": "^1.0.1" } }, "is-relative": { @@ -3555,6 +3590,15 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, "just-debounce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", @@ -3957,9 +4001,9 @@ } }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "dev": true }, "object-keys": { @@ -4856,9 +4900,9 @@ } }, "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -4993,24 +5037,24 @@ } } }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" } }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" } }, "string_decoder": { @@ -5111,9 +5155,9 @@ } }, "terser": { - "version": "4.6.9", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.9.tgz", - "integrity": "sha512-9UuZOApK4oiTpX4AjnWhTCY3fCqntS3ggPQOku9M3Rvr70VETYsuHjSGuRy0D7X/Z994hfnzMy6TQ/H0WQSmXQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.2.1.tgz", + "integrity": "sha512-/AOtjRtAMNGO0fIF6m8HfcvXTw/2AKpsOzDn36tA5RfhRdeXyb4RvHxJ5Pah7iL6dFkLk+gOnCaNHGwJPl6TrQ==", "dev": true, "requires": { "commander": "^2.20.0", @@ -5243,6 +5287,26 @@ "through2": "^2.0.3" } }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, "tslib": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", diff --git a/package.json b/package.json index 8162131..1805d58 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kaidi", - "version": "1.0.6", + "version": "1.0.7", "description": "A Kodi remote app for KaiOS.", "scripts": { "clean": "gulp clean", @@ -26,8 +26,8 @@ "del": "^5.1.0", "eslint": "^6.8.0", "eslint-config-standard": "^14.1.1", - "eslint-plugin-import": "^2.20.1", - "eslint-plugin-node": "^11.0.0", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.1", "fancy-log": "^1.3.3", @@ -35,7 +35,7 @@ "gulp-clean-css": "^4.3.0", "gulp-htmlmin": "^5.0.1", "gulp-plumber": "^1.2.1", - "gulp-terser": "^1.2.0", - "gulp-zip": "^5.0.1" + "gulp-terser": "^1.3.2", + "gulp-zip": "^5.0.2" } } diff --git a/src/css/global/native-toast.css b/src/css/global/kaios-toaster.css similarity index 61% rename from src/css/global/native-toast.css rename to src/css/global/kaios-toaster.css index 718c041..5f755d5 100644 --- a/src/css/global/native-toast.css +++ b/src/css/global/kaios-toaster.css @@ -1,10 +1,11 @@ -.native-toast { +.kaios-toast { position: fixed; - background-color: #d3d3d3; + background-color: #363636; width: 100%; - line-height: 36px; - color: #363636; + min-height: 36px; + color: #ffffff; text-align: center; + word-wrap: break-word; opacity: 0; z-index: 99999; transition: opacity 0.25s, top 0.25s, bottom 0.25s, -webkit-transform 0.25s; @@ -13,45 +14,40 @@ box-sizing: border-box; max-width: 18rem; } -.native-toast-north { + +.kaios-toast-content { + padding: 8px +} + +.kaios-toast-north { left: 50%; transform: translateX(-50%); top: -54px; } -.native-toast-north.native-toast-shown { +.kaios-toast-north.kaios-toast-shown { opacity: 1; top: 27px; } -.native-toast-south { +.kaios-toast-south { left: 50%; transform: translateX(-50%); bottom: -30px; } -.native-toast-south.native-toast-shown { +.kaios-toast-south.kaios-toast-shown { opacity: 1; bottom: 30px; } -.native-toast-center { - left: 50%; - transform: translate(-50%, -50%); - bottom: -50px; -} -.native-toast-center.native-toast-shown { - opacity: 1; - bottom: 50%; -} - -.native-toast-error { +.kaios-toast-error { background-color: #ff3d3d; color: #fff; } -.native-toast-success { +.kaios-toast-success { background-color: #62a465; color: #fff; } -.native-toast-warning { +.kaios-toast-warning { background-color: #ffb618; color: #fff; } \ No newline at end of file diff --git a/src/css/global/options.css b/src/css/global/options.css index 0a30084..e9ab87e 100644 --- a/src/css/global/options.css +++ b/src/css/global/options.css @@ -12,33 +12,49 @@ width: 100%; max-height: 80%; position: absolute; - overflow: hidden; + overflow: auto; bottom: 0; } -.options-menu .options-menu-title { +.options-menu-title { margin: 0; - color: #323232; font-size: 17px; font-weight: 400; text-align: center; - background-color: #d8d8d8; height: 28px; line-height: 28px; } +.theme-options-menu-title-light { + background-color: #d8d8d8; + color: #323232; +} + +.theme-options-menu-title-dark { + background-color: #272727; + color: #ffffff +} + .options-menu-list { margin: 0; padding: 0; overflow: hidden; } +.theme-options-menu-list-light { + background-color: #ffffff; + color: #000000; +} + +.theme-options-menu-list-dark { + background-color: #363636; + color: #ffffff; +} + .options-menu-list div { height: 50px; line-height: 50px; padding-left: 10px; - background-color: #fff; - font-family: "Open Sans" } .options-menu-list div:focus { diff --git a/src/home.html b/src/home.html index cd6f92e..9e732e2 100644 --- a/src/home.html +++ b/src/home.html @@ -9,7 +9,7 @@ - + @@ -50,7 +50,7 @@

Playback

Settings
- + diff --git a/src/js/backbone/utils.js b/src/js/backbone/utils.js index b67177f..52b19a0 100644 --- a/src/js/backbone/utils.js +++ b/src/js/backbone/utils.js @@ -49,14 +49,14 @@ Creates a new nativeToast with the localized text or the non-available substitut */ function newLocalizedToast (localizationKey, noLocalizationPlaceholder, toastPosition, toastTimeout, toastType) { navigator.mozL10n.formatValue(localizationKey).then((localizedText) => { - nativeToast({ + kaiosToaster({ message: localizedText, position: toastPosition, timeout: toastTimeout, type: toastType }) }).catch(() => { - nativeToast({ + kaiosToaster({ message: noLocalizationPlaceholder, position: toastPosition, timeout: toastTimeout, @@ -178,6 +178,8 @@ function switchTheme () { var softkeyBars = document.querySelectorAll('.softkeys-bar') var separatorElements = document.querySelectorAll('.separator') var settingsElements = document.querySelectorAll('.settings-entry') + var optionMenuElements = document.querySelectorAll('.options-menu') + // var optionMenuTitleElements = document.querySelectorAll('.option-menu-title') switch (currentSelectedTheme) { case 'light': for (var contentElement of contentElements) { @@ -198,6 +200,12 @@ function switchTheme () { settingsElement.children[1].classList.remove('theme-settings-dark') settingsElement.children[1].classList.add('theme-settings-light') } + for (var optionMenuElement of optionMenuElements) { + optionMenuElement.children[0].classList.remove('theme-options-menu-title-dark') + optionMenuElement.children[0].classList.add('theme-options-menu-title-light') + optionMenuElement.children[1].classList.remove('theme-options-menu-list-dark') + optionMenuElement.children[1].classList.add('theme-options-menu-list-light') + } break case 'dark': for (var contentElement of contentElements) { @@ -218,6 +226,12 @@ function switchTheme () { settingsElement.children[1].classList.remove('theme-settings-light') settingsElement.children[1].classList.add('theme-settings-dark') } + for (var optionMenuElement of optionMenuElements) { + optionMenuElement.children[0].classList.remove('theme-options-menu-title-light') + optionMenuElement.children[0].classList.add('theme-options-menu-title-dark') + optionMenuElement.children[1].classList.remove('theme-options-menu-list-light') + optionMenuElement.children[1].classList.add('theme-options-menu-list-dark') + } break default: settings.set('theme', 'light') diff --git a/src/js/libs/kaios-toaster.js b/src/js/libs/kaios-toaster.js new file mode 100644 index 0000000..d1f3dc8 --- /dev/null +++ b/src/js/libs/kaios-toaster.js @@ -0,0 +1,117 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.kaiosToaster = factory()); +}(this, (function () { 'use strict'; + + /*! + * nano-assign v1.0.0 + * (c) 2017-present egoist <0x142857@gmail.com> + * Released under the MIT License. + */ + + var index = function(obj) { + var arguments$1 = arguments; + + for (var i = 1; i < arguments.length; i++) { + // eslint-disable-next-line guard-for-in, prefer-rest-params + for (var p in arguments[i]) { obj[p] = arguments$1[i][p]; } + } + return obj + }; + + var nanoAssign_common = index; + + var prevToast = null; + + var Toast = function Toast(ref) { + var this$1 = this; + if ( ref === void 0 ) ref = {}; + var message = ref.message; if (message === void 0) message = ''; + var position = ref.position; if (position === void 0 || ['north', 'south'].indexOf(position) === -1) position = 'south'; + var timeout = ref.timeout; if ( timeout === void 0 ) timeout = 3000; + var el = ref.el; if ( el === void 0 ) el = document.body; + var rounded = ref.rounded; if ( rounded === void 0 ) rounded = false; + var type = ref.type; if ( type === void 0 ) type = ''; + var debug = ref.debug; if ( debug === void 0 ) debug = false; + var elements = ref.elements; if ( elements === void 0 ) elements = []; + + if (prevToast) { + prevToast.destroy(); + } + + this.message = message; + this.position = position; + this.el = el; + this.timeout = timeout; + this.toast = document.createElement('div'); + this.toast.className = "kaios-toast kaios-toast-"+this.position; + + if (type) { + this.toast.className += " kaios-toast-" + type; + } + + var messageElement = document.createElement('div'); + messageElement.className = 'kaios-toast-content' + messageElement.innerHTML = this.message; + [messageElement ].concat( elements).forEach(function (el) { + this$1.toast.appendChild(el); + }); + + if (rounded) { + this.toast.style.borderRadius = '33px'; + } + + this.el.appendChild(this.toast); + prevToast = this; + this.show(); + + if (!debug && timeout) { + this.hide(); + } + }; + + Toast.prototype.show = function show () { + var this$1 = this; + + setTimeout(function () { + this$1.toast.classList.add('kaios-toast-shown'); + }, 300); + }; + + Toast.prototype.hide = function hide () { + var this$1 = this; + + setTimeout(function () { + this$1.destroy(); + }, this.timeout); + }; + + Toast.prototype.destroy = function destroy () { + var this$1 = this; + + if (!this.toast) { return; } + this.toast.classList.remove('kaios-toast-shown'); + setTimeout(function () { + if (this$1.toast) { + this$1.el.removeChild(this$1.toast); + this$1.toast = null; + } + }, 300); + }; + + function toast(options) { + return new Toast(options); + } + + var loop = function () { + toast[type] = function (options) { return toast(nanoAssign_common({ + type: type + }, options)); }; + }; + + for (var type of ['success', 'warning', 'error']) loop(); + + return toast; + +}))); \ No newline at end of file diff --git a/src/js/libs/native-toast.js b/src/js/libs/native-toast.js deleted file mode 100644 index f9fb843..0000000 --- a/src/js/libs/native-toast.js +++ /dev/null @@ -1,129 +0,0 @@ -(function (global, factory) { -typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : -typeof define === 'function' && define.amd ? define(factory) : -(global.nativeToast = factory()); -}(this, (function () { 'use strict'; - -/*! - * nano-assign v1.0.0 - * (c) 2017-present egoist <0x142857@gmail.com> - * Released under the MIT License. - */ - -var index = function(obj) { - var arguments$1 = arguments; - - for (var i = 1; i < arguments.length; i++) { - // eslint-disable-next-line guard-for-in, prefer-rest-params - for (var p in arguments[i]) { obj[p] = arguments$1[i][p]; } - } - return obj -}; - -var nanoAssign_common = index; - -var prevToast = null; - -var Toast = function Toast(ref) { - var this$1 = this; - if ( ref === void 0 ) ref = {}; - var message = ref.message; if ( message === void 0 ) message = ''; - var position = ref.position; if ( position === void 0 ) position = 'south'; - var timeout = ref.timeout; if ( timeout === void 0 ) timeout = 3000; - var el = ref.el; if ( el === void 0 ) el = document.body; - var rounded = ref.rounded; if ( rounded === void 0 ) rounded = false; - var type = ref.type; if ( type === void 0 ) type = ''; - var debug = ref.debug; if ( debug === void 0 ) debug = false; - var edge = ref.edge; if ( edge === void 0 ) edge = false; - var closeOnClick = ref.closeOnClick; if ( closeOnClick === void 0 ) closeOnClick = false; - var elements = ref.elements; if ( elements === void 0 ) elements = []; - - if (prevToast) { - prevToast.destroy(); - } - - this.message = message; - this.position = position; - this.el = el; - this.timeout = timeout; - this.closeOnClick = closeOnClick; - this.toast = document.createElement('div'); - this.toast.className = "native-toast native-toast-"+this.position; - - if (type) { - this.toast.className += " native-toast-" + type; - } - - var messageElement = document.createElement('div'); - messageElement.className = 'native-toast-message'; - messageElement.innerHTML = this.message; - [messageElement ].concat( elements).forEach(function (el) { - this$1.toast.appendChild(el); - }); - var isMobile = document.body.clientWidth < 768; - - if (edge || isMobile) { - this.toast.className += ' native-toast-edge'; - } else if (rounded) { - this.toast.style.borderRadius = '33px'; - } - - this.el.appendChild(this.toast); - prevToast = this; - this.show(); - - if (!debug && timeout) { - this.hide(); - } - - if (this.closeOnClick) { - this.toast.addEventListener('click', function () { - this$1.destroy(); - }); - } -}; - -Toast.prototype.show = function show () { - var this$1 = this; - - setTimeout(function () { - this$1.toast.classList.add('native-toast-shown'); - }, 300); -}; - -Toast.prototype.hide = function hide () { - var this$1 = this; - - setTimeout(function () { - this$1.destroy(); - }, this.timeout); -}; - -Toast.prototype.destroy = function destroy () { - var this$1 = this; - - if (!this.toast) { return; } - this.toast.classList.remove('native-toast-shown'); - setTimeout(function () { - if (this$1.toast) { - this$1.el.removeChild(this$1.toast); - this$1.toast = null; - } - }, 300); -}; - -function toast(options) { - return new Toast(options); -} - -var loop = function () { - toast[type] = function (options) { return toast(nanoAssign_common({ - type: type - }, options)); }; -}; - -for (var type of ['success', 'info', 'warning', 'error']) loop(); - -return toast; - -}))); \ No newline at end of file diff --git a/src/manifest.webapp b/src/manifest.webapp index ad29db7..3fccefe 100644 --- a/src/manifest.webapp +++ b/src/manifest.webapp @@ -1,5 +1,5 @@ { - "version": "1.0.6", + "version": "1.0.7", "name": "Kaidi Remote", "description": "The Kodi remote app for KaiOS.", "launch_path": "/ad.html", diff --git a/src/player.html b/src/player.html index b552336..e349a39 100644 --- a/src/player.html +++ b/src/player.html @@ -9,7 +9,7 @@ - + @@ -56,7 +56,7 @@

Playback

- + diff --git a/src/settings.html b/src/settings.html index 0b4212b..d8d6cdc 100644 --- a/src/settings.html +++ b/src/settings.html @@ -9,7 +9,7 @@ - + @@ -77,7 +77,7 @@

Donation

Reset
- +