diff --git a/.editconfig b/.editconfig new file mode 100644 index 000000000..8f9bbe26e --- /dev/null +++ b/.editconfig @@ -0,0 +1,20 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] + +# Change these settings to your own preference +indent_style = space +indent_size = 2 + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 823351c24..ec8506984 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,16 @@ * [CONFIG] There is no more dev/prod distinction, WPHC turn debug OFF when building the prod app automatically. * [ABOUT] The About feature has been removed. You can use Pages to achieve the same purpose. + +### 2.0.0-beta13 (2016-10-22) + +To upgrade checkout `git checkout v2.0.0-beta13` and run `npm i` + +* [FEATURE] Display app icon in the menu header +* [FEATURE] Progressive Web App support (Manifest & service workers) +* Remove share button on browser + + ### 2.0.0-beta12 (2016-09-18) diff --git a/CONFIGURATION.md b/CONFIGURATION.md index 1be0e319b..914e1b236 100644 --- a/CONFIGURATION.md +++ b/CONFIGURATION.md @@ -81,6 +81,16 @@ For instance if you want to modify the way the menu is displayed, you will need After that you will need to register your new template in `lib/templates/index.js` (read the comments for help) +## Service Workers (Experimental) + +WPHC supports progressive web apps. When [enabled](#serviceWorker) make sure you modify `config/manifest.json` with your own app informations (title, description etc.) and overwrite all the icons in `config/icons`. + +PWA requires a HTTPS connection, make sure to have an SSL certificate. + +Chrome dev tools allow you to test the "add to homescreen" feature on the browser. + +![image](https://cloud.githubusercontent.com/assets/1388706/19619167/740031b0-9860-11e6-9ca0-ebb5bb9bb152.png) + ## Frequently asked questions ### How to change the font @@ -151,6 +161,7 @@ Here is a simple view of what you can configure: * title * ionicConfig +* serviceWorker * api * baseUrl * timeout @@ -158,6 +169,7 @@ Here is a simple view of what you can configure: * menu * exposeAsideWhen * list + * logo * settings * cache * views @@ -204,13 +216,15 @@ allow overwriting ionic configuration +### serviceWorker [Object] -The media query used to determine when to always display the left menu. +* ***enabled*** ```Boolean``` Experiemental. default `false` -``` -"exposeAsideWhen": "(min-width:900px)" -``` +### menu [Object] + +* ***exposeAsideWhen*** ```String``` The media query used to determine when to always display the left menu, default `(min-width:900px)` +* ***displayIcon*** ```Boolean``` whether or not to display the icon on the menu header. default `true`, to modify the icon overwrite `config/icons/icon_48.png` ### Settings configuration. diff --git a/INSTALLATION.md b/INSTALLATION.md index fbbb5033d..251f525fa 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -42,11 +42,6 @@ During the installation you might have the following error on OSX: ## Config files -``` -# Copy local config -npm run installWPHC -``` - Your personal config files live now in the `config` folder. You can modify all of them except `config.default.cson` which contains the default config that can be overwritten using `config/config.cson` ## Installing the Web service diff --git a/PUSHNOTIFICATIONS.md b/PUSHNOTIFICATIONS.md index 27845c651..ec34182e9 100644 --- a/PUSHNOTIFICATIONS.md +++ b/PUSHNOTIFICATIONS.md @@ -105,3 +105,9 @@ The register http request fails with this message: `{error: "401", reason: "Unau Why am I getting the errors `{Unable to connect to tls://gateway.sandbox.push.apple.com:2195}` or `{Unable to connect to tsl://gateway.push.apple.com:2195}`? [Solution](http://stackoverflow.com/questions/1444355/iphone-push-notification-unable-to-connect-to-the-ssl-server) + +### Param tells me that I am not registered + +If the "enabled" checkbox on the push notif parameters (in app) is never on. It could mean that the following checkboxes are not checked. Please check at least `category` to resolve the problem. + +![image](https://cloud.githubusercontent.com/assets/1388706/19411490/f5f52170-9302-11e6-9f31-28f9a97da691.png) diff --git a/README.md b/README.md index 54a599688..6052fff16 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ - [X] Syntax highlighter - [X] Offline (Bookmarks) - [X] Comments (Submitting is not supported yet) +- [X] Progressive Web App (manifest & Service Workers) ## Built with WPHC @@ -78,7 +79,7 @@ $ git tag $ git checkout # Install -$ npm install && npm run installWPHC +$ npm install # Run on the browser $ npm start @@ -123,6 +124,9 @@ Read the manual: [SPLASHICONS.md](SPLASHICONS.md) ## Project public API ``` +# Installation +npm run installWPHC (auto ran post npm install) + # Dev server npm start diff --git a/config/config.default.cson b/config/config.default.cson index c7b0d2a8f..fd23c756e 100755 --- a/config/config.default.cson +++ b/config/config.default.cson @@ -15,6 +15,9 @@ "timeout": 30000 "maxAttempt": 3 +"serviceWorker": + "enabled" : false + # IONIC "ionicConfig": "views": @@ -49,6 +52,7 @@ "state": "public.posts" "params": {} "exposeAsideWhen": "(min-width:900px)" + "displayIcon": true # uses config/icons/icon_48.png # SETTINGS PAGE "settings": diff --git a/dist/icons/icon_128.png b/dist/icons/icon_128.png new file mode 100644 index 000000000..adfffcbb6 Binary files /dev/null and b/dist/icons/icon_128.png differ diff --git a/dist/icons/icon_144.png b/dist/icons/icon_144.png new file mode 100644 index 000000000..e35db6a7d Binary files /dev/null and b/dist/icons/icon_144.png differ diff --git a/dist/icons/icon_168.png b/dist/icons/icon_168.png new file mode 100644 index 000000000..f9159a0c6 Binary files /dev/null and b/dist/icons/icon_168.png differ diff --git a/dist/icons/icon_192.png b/dist/icons/icon_192.png new file mode 100644 index 000000000..651730049 Binary files /dev/null and b/dist/icons/icon_192.png differ diff --git a/dist/icons/icon_48.png b/dist/icons/icon_48.png new file mode 100644 index 000000000..376d2a81f Binary files /dev/null and b/dist/icons/icon_48.png differ diff --git a/dist/icons/icon_72.png b/dist/icons/icon_72.png new file mode 100644 index 000000000..5a11cc48a Binary files /dev/null and b/dist/icons/icon_72.png differ diff --git a/dist/icons/icon_96.png b/dist/icons/icon_96.png new file mode 100644 index 000000000..b561e9502 Binary files /dev/null and b/dist/icons/icon_96.png differ diff --git a/dist/index.js b/dist/index.js index 1d5d3ccc7..a52c09872 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,4 +1,11 @@ import templates from './templates/index.js'; +import './icons/icon_48.png'; +import './icons/icon_72.png'; +import './icons/icon_96.png'; +import './icons/icon_144.png'; +import './icons/icon_168.png'; +import './icons/icon_192.png'; +import '!file?name=[name].[ext]!./manifest.json'; let mod = angular.module('wordpress-hybrid-client.overwriteModule', [ templates diff --git a/dist/manifest.json b/dist/manifest.json new file mode 100644 index 000000000..2a1f4099f --- /dev/null +++ b/dist/manifest.json @@ -0,0 +1,43 @@ +{ + "name": "Your App Name (45 characters max)", + "short_name": "Your App", + "description": "Your App description", + "default_locale": "en", + "start_url": "index.html", + "display": "standalone", + "lang": "en-US", + "icons": [ + { + "src": "img/icon_48.png", + "sizes": "48x48", + "type": "image/png" + }, + { + "src": "img/icon_72.png", + "sizes": "72x72", + "type": "image/png" + }, + { + "src": "img/icon_96.png", + "sizes": "96x96", + "type": "image/png" + }, + { + "src": "img/icon_144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "img/icon_168.png", + "sizes": "168x168", + "type": "image/png" + }, + { + "src": "img/icon_192.png", + "sizes": "192x192", + "type": "image/png" + } + ], + "background_color": "#4e8ef7", + "theme_color": "#4e8ef7" +} \ No newline at end of file diff --git a/lib/directives/postToolbar/index.js b/lib/directives/postToolbar/index.js index dc1f35b7f..5a29ff239 100644 --- a/lib/directives/postToolbar/index.js +++ b/lib/directives/postToolbar/index.js @@ -19,8 +19,9 @@ export default function() { var vm = this; vm.isBookmarked = $WPHCBookmark.isBookmarked(vm.post); vm.hasBookmark = angular.isDefined($attrs.showBookmark); - vm.hasShare = angular.isDefined($attrs.showShare); - vm.terms = vm.post._embedded['https://api.w.org/term']; + vm.hasShare = angular.isDefined($attrs.showShare) && ionic.Platform.isWebView(); + vm.terms = vm.post._embedded['https://api.w.org/term'] + || vm.post._embedded['wp:term']; vm.showTaxonomies = showTaxonomies; vm.share = share; vm.bookmark = bookmark; diff --git a/lib/index.coffee b/lib/index.coffee index d2c34e4a7..c88493676 100644 --- a/lib/index.coffee +++ b/lib/index.coffee @@ -10,6 +10,7 @@ require './font/font.coffee' require 'expose?_!lodash' require 'wp-api-angularjs' require './config.js' +require '!file?name=[name].[ext]!./service-worker.js'; overwriteModule = require '../config/index.js' customPostsModule = require './customPosts/index.js' pagesModule = require './pages/index.js' @@ -126,6 +127,7 @@ app.controller 'WPHCMainController' , ($log, $WPHCConfig) -> vm.appVersion = wordpressHybridClient.version || null vm.appConfig = $WPHCConfig vm.appTitle = vm.appConfig.title || null + vm.displayIcon = vm.appConfig.menu.displayIcon vm ### diff --git a/lib/index.html b/lib/index.html index a78aa930b..2468d66c6 100644 --- a/lib/index.html +++ b/lib/index.html @@ -7,10 +7,20 @@ {%=o.htmlWebpackPlugin.options.pkg.title %} + + {% if (o.htmlWebpackPlugin.options.serviceWorkerEnabled) { %} + + {% } %} diff --git a/lib/scss/_bar.scss b/lib/scss/_bar.scss old mode 100644 new mode 100755 index 399519128..957065c44 --- a/lib/scss/_bar.scss +++ b/lib/scss/_bar.scss @@ -1,3 +1,13 @@ +$logoSize : $bar-height - (2 * $bar-padding-portrait); .bar { +} +.menu-bar.has-icon{ + .icon{ + width: $logoSize; + height: $logoSize; + } + .title{ + margin-left: $logoSize + 10; + } } \ No newline at end of file diff --git a/lib/scss/_post.scss b/lib/scss/_post.scss old mode 100644 new mode 100755 index b06d23ec4..50aa00ef5 --- a/lib/scss/_post.scss +++ b/lib/scss/_post.scss @@ -162,4 +162,5 @@ wphc-post { } } @include post-item("../img/post-img-border.png"); + } diff --git a/lib/service-worker.js b/lib/service-worker.js new file mode 100644 index 000000000..0928a8fa5 --- /dev/null +++ b/lib/service-worker.js @@ -0,0 +1,80 @@ +// tick this to make the cache invalidate and update +const CACHE_VERSION = 1; +const CURRENT_CACHES = { + 'read-through': 'read-through-cache-v' + CACHE_VERSION +}; + +self.addEventListener('activate', (event) => { + // Delete all caches that aren't named in CURRENT_CACHES. + // While there is only one cache in this example, the same logic will handle the case where + // there are multiple versioned caches. + const expectedCacheNames = Object.keys(CURRENT_CACHES).map((key) => { + return CURRENT_CACHES[key]; + }); + + event.waitUntil( + caches.keys().then((cacheNames) => { + return Promise.all( + cacheNames.map((cacheName) => { + if (expectedCacheNames.indexOf(cacheName) === -1) { + // If this cache name isn't present in the array of "expected" cache names, then delete it. + console.log('Deleting out of date cache:', cacheName); + return caches.delete(cacheName); + } + }) + ); + }) + ); +}); + +// This sample illustrates an aggressive approach to caching, in which every valid response is +// cached and every request is first checked against the cache. +// This may not be an appropriate approach if your web application makes requests for +// arbitrary URLs as part of its normal operation (e.g. a RSS client or a news aggregator), +// as the cache could end up containing large responses that might not end up ever being accessed. +// Other approaches, like selectively caching based on response headers or only caching +// responses served from a specific domain, might be more appropriate for those use cases. +self.addEventListener('fetch', (event) => { + + event.respondWith( + caches.open(CURRENT_CACHES['read-through']).then((cache) => { + return cache.match(event.request).then((response) => { + if (response) { + // If there is an entry in the cache for event.request, then response will be defined + // and we can just return it. + + return response; + } + + // Otherwise, if there is no entry in the cache for event.request, response will be + // undefined, and we need to fetch() the resource. + console.log(' No response for %s found in cache. ' + + 'About to fetch from network...', event.request.url); + + // We call .clone() on the request since we might use it in the call to cache.put() later on. + // Both fetch() and cache.put() "consume" the request, so we need to make a copy. + // (see https://fetch.spec.whatwg.org/#dom-request-clone) + return fetch(event.request.clone()).then((response) => { + + // Optional: add in extra conditions here, e.g. response.type == 'basic' to only cache + // responses from the same domain. See https://fetch.spec.whatwg.org/#concept-response-type + if (response.status < 400 && response.type === 'basic') { + // We need to call .clone() on the response object to save a copy of it to the cache. + // (https://fetch.spec.whatwg.org/#dom-request-clone) + cache.put(event.request, response.clone()); + } + + // Return the original response object, which will be used to fulfill the resource request. + return response; + }); + }).catch((error) => { + // This catch() will handle exceptions that arise from the match() or fetch() operations. + // Note that a HTTP error response (e.g. 404) will NOT trigger an exception. + // It will return a normal response object that has the appropriate error code set. + console.error(' Read-through caching failed:', error); + + throw error; + }); + }) + ); +}); \ No newline at end of file diff --git a/lib/templates/module/menu.html b/lib/templates/module/menu.html index b6a7802dd..23520a3ed 100644 --- a/lib/templates/module/menu.html +++ b/lib/templates/module/menu.html @@ -1,6 +1,7 @@ - -

{{main.appTitle}}

+ + +

{{main.appTitle}}

- - + + \ No newline at end of file diff --git a/lib/translations/de.cson b/lib/translations/de.cson index 11b7a4400..86e967040 100644 --- a/lib/translations/de.cson +++ b/lib/translations/de.cson @@ -12,7 +12,7 @@ "tags": "Tags" "pages": "Pages" "posts": "Posts" - "authors": "Authors" + "authors": "Autoren" "search": "Suche" "bookmarks": "Lesezeichen" "socialNetworks": "Soziale Netzwerke" @@ -48,9 +48,9 @@ "sharing": "shared": "Geteilt!" "authors": - "title": "Authors" + "title": "Autoren" "author": - "title": "Author: {{name}}" + "title": "Autor: {{name}}" "pages": "title": "Pages" "posts": diff --git a/package.json b/package.json index 9c30727f8..852f16edf 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "wordpress-hybrid-client", - "version": "2.0.0-beta12", + "version": "2.0.0-beta13", "title": "wordpress-hybrid-client", "description": "AngularJS client using Ionic Framework and based on the json-rest-api plugin: https://wordpress.org/plugins/json-rest-api/ with CORS enabled.", "main": "index.js", "scripts": { "build": "bash ./release.sh", "restore": "ionic state restore", + "postinstall": "npm run installWPHC", "installWPHC": "cd scripts && node ./install.js", "increaseVersion": "cd scripts && node ./increaseVersion.js", "start": "webpack-dev-server --port 8080 --json --progress", diff --git a/scripts/install.js b/scripts/install.js index c58c312bf..4cab4c37b 100644 --- a/scripts/install.js +++ b/scripts/install.js @@ -8,6 +8,8 @@ copy('../dist/config.xml', '../config.xml'); copy('../dist/config.scss', '../config/config.scss'); copy('../dist/index.js', '../config/index.js', true); copy('../dist/templates', '../config/templates'); +copy('../dist/icons', '../config/icons'); +copy('../dist/manifest.json', '../config/manifest.json'); copy('../release.sh.dist', '../release.sh'); function copy(source, target, overwrite) { diff --git a/webpack.config.js b/webpack.config.js index 4e61d7857..63a57f654 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -79,6 +79,7 @@ module.exports = { new HtmlWebpackPlugin({ filename: 'index.html', pkg: pkg, + serviceWorkerEnabled: projectConfig.serviceWorker.enabled, appVersion: getAppVersion(), template: path.join(libPath, 'index.html') }), diff --git a/webpack.config.prod.js b/webpack.config.prod.js index 97c014f45..fe8bac32d 100644 --- a/webpack.config.prod.js +++ b/webpack.config.prod.js @@ -17,6 +17,7 @@ module.exports = extend(webpackConfig, { new HtmlWebpackPlugin({ filename: 'index.html', pkg: pkg, + serviceWorkerEnabled: projectConfig.serviceWorker.enabled, appVersion: getAppVersion(), template: path.join(libPath, 'index.html') }),