mirror of
https://gitee.com/mafgwo/stackedit
synced 2024-11-15 19:22:27 +08:00
Added A2HS prompt
This commit is contained in:
parent
f7542965b6
commit
0e8aa0a58a
|
@ -5,7 +5,6 @@ var config = require('../config')
|
|||
var VueLoaderPlugin = require('vue-loader/lib/plugin')
|
||||
var vueLoaderConfig = require('./vue-loader.conf')
|
||||
var StylelintPlugin = require('stylelint-webpack-plugin')
|
||||
var FaviconsWebpackPlugin = require('favicons-webpack-plugin')
|
||||
|
||||
function resolve (dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
|
@ -48,16 +47,33 @@ module.exports = {
|
|||
loader: 'vue-loader',
|
||||
options: vueLoaderConfig
|
||||
},
|
||||
// We can't pass graphlibrary to babel
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'string-replace-loader',
|
||||
include: [
|
||||
resolve('node_modules/graphlibrary')
|
||||
],
|
||||
options: {
|
||||
search: '^\\s*(?:let|const) ',
|
||||
replace: 'var ',
|
||||
flags: 'gm'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: [resolve('src'), resolve('test'), resolve('node_modules/mermaid/src')],
|
||||
include: [
|
||||
resolve('src'),
|
||||
resolve('test'),
|
||||
resolve('node_modules/mermaid')
|
||||
],
|
||||
exclude: [
|
||||
resolve('node_modules/mermaid/src/diagrams/class/parser'),
|
||||
resolve('node_modules/mermaid/src/diagrams/flowchart/parser'),
|
||||
resolve('node_modules/mermaid/src/diagrams/gantt/parser'),
|
||||
resolve('node_modules/mermaid/src/diagrams/git/parser'),
|
||||
resolve('node_modules/mermaid/src/diagrams/sequence/parser'),
|
||||
resolve('node_modules/mermaid/src/diagrams/sequence/parser')
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -86,10 +102,6 @@ module.exports = {
|
|||
new StylelintPlugin({
|
||||
files: ['**/*.vue', '**/*.scss']
|
||||
}),
|
||||
new FaviconsWebpackPlugin({
|
||||
logo: resolve('src/assets/favicon.png'),
|
||||
title: 'StackEdit',
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
VERSION: JSON.stringify(require('../package.json').version)
|
||||
})
|
||||
|
|
|
@ -9,6 +9,12 @@ var HtmlWebpackPlugin = require('html-webpack-plugin')
|
|||
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
|
||||
var OfflinePlugin = require('offline-plugin');
|
||||
var WebpackPwaManifest = require('webpack-pwa-manifest')
|
||||
var FaviconsWebpackPlugin = require('favicons-webpack-plugin')
|
||||
|
||||
function resolve (dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
|
||||
var env = config.build.env
|
||||
|
||||
|
@ -94,6 +100,22 @@ var webpackConfig = merge(baseWebpackConfig, {
|
|||
ignore: ['.*']
|
||||
}
|
||||
]),
|
||||
new FaviconsWebpackPlugin({
|
||||
logo: resolve('src/assets/favicon.png'),
|
||||
title: 'StackEdit',
|
||||
}),
|
||||
new WebpackPwaManifest({
|
||||
name: 'StackEdit',
|
||||
description: 'Full-featured, open-source Markdown editor',
|
||||
display: 'standalone',
|
||||
start_url: 'app',
|
||||
background_color: '#ffffff',
|
||||
crossorigin: 'use-credentials',
|
||||
icons: [{
|
||||
src: resolve('src/assets/favicon.png'),
|
||||
sizes: [96, 128, 192, 256, 384, 512]
|
||||
}]
|
||||
}),
|
||||
new OfflinePlugin({
|
||||
ServiceWorker: {
|
||||
events: true
|
||||
|
@ -101,7 +123,7 @@ var webpackConfig = merge(baseWebpackConfig, {
|
|||
AppCache: true,
|
||||
excludes: ['**/.*', '**/*.map', '**/index.html', '**/static/oauth2/callback.html', '**/icons-*/*.png', '**/static/fonts/KaTeX_*'],
|
||||
externals: ['/', '/app', '/oauth2/callback']
|
||||
})
|
||||
}),
|
||||
]
|
||||
})
|
||||
|
||||
|
|
82
package-lock.json
generated
82
package-lock.json
generated
|
@ -16854,6 +16854,69 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"string-replace-loader": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-replace-loader/-/string-replace-loader-2.1.1.tgz",
|
||||
"integrity": "sha512-0Nvw1LDclF45AFNuYPcD2Jvkv0mwb/dQSnJZMvhqGrT+zzmrpG3OJFD600qfQfNUd5aqfp7fCm2mQMfF7zLbyQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^1.1.0",
|
||||
"schema-utils": "^0.4.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz",
|
||||
"integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"ajv-keywords": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
|
||||
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
|
||||
"integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"big.js": "^3.1.3",
|
||||
"emojis-list": "^2.0.0",
|
||||
"json5": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "0.4.7",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
|
||||
"integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.1.0",
|
||||
"ajv-keywords": "^3.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
|
@ -19774,6 +19837,25 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"webpack-pwa-manifest": {
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack-pwa-manifest/-/webpack-pwa-manifest-3.7.1.tgz",
|
||||
"integrity": "sha512-G37fVCa1ndij3jyz6WaOaxHLHdp2URyOHwp2GLmxt39sXL8ZdOFM1qvHagEJBkNh+3hu25eIgy6TD5J/8sgQcQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"css-color-names": "0.0.4",
|
||||
"jimp": "^0.2.28",
|
||||
"mime": "^1.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"webpack-sources": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
"sass-loader": "^7.0.1",
|
||||
"semver": "^5.5.0",
|
||||
"shelljs": "^0.8.1",
|
||||
"string-replace-loader": "^2.1.1",
|
||||
"stylelint": "^9.2.0",
|
||||
"stylelint-config-standard": "^16.0.0",
|
||||
"stylelint-processor-html": "^1.0.0",
|
||||
|
@ -124,6 +125,7 @@
|
|||
"webpack-dev-middleware": "^1.10.0",
|
||||
"webpack-hot-middleware": "^2.18.0",
|
||||
"webpack-merge": "^4.1.2",
|
||||
"webpack-pwa-manifest": "^3.7.1",
|
||||
"worker-loader": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -2,12 +2,18 @@
|
|||
<div class="notification">
|
||||
<div class="notification__item flex flex--row flex--align-center" v-for="(item, idx) in items" :key="idx">
|
||||
<div class="notification__icon flex flex--column flex--center">
|
||||
<icon-information v-if="item.type === 'info'"></icon-information>
|
||||
<icon-alert v-else-if="item.type === 'error'"></icon-alert>
|
||||
<icon-alert v-if="item.type === 'error'"></icon-alert>
|
||||
<icon-information v-else></icon-information>
|
||||
</div>
|
||||
<div class="notification__content">
|
||||
{{item.content}}
|
||||
</div>
|
||||
<button class="notification__button button" v-if="item.type === 'confirm'" @click="item.reject">
|
||||
No
|
||||
</button>
|
||||
<button class="notification__button button" v-if="item.type === 'confirm'" @click="item.resolve">
|
||||
Yes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -49,4 +55,17 @@ export default {
|
|||
margin-right: 12px;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.notification__button {
|
||||
color: $navbar-color;
|
||||
padding: 8px;
|
||||
flex: none;
|
||||
|
||||
&:active,
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: $navbar-hover-color;
|
||||
background-color: $navbar-hover-background;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
16
src/index.js
16
src/index.js
|
@ -33,6 +33,22 @@ if (localStorage.updated) {
|
|||
setTimeout(() => localStorage.removeItem('updated'), 2000);
|
||||
}
|
||||
|
||||
if (!localStorage.installPrompted) {
|
||||
window.addEventListener('beforeinstallprompt', async (promptEvent) => {
|
||||
// Prevent Chrome 67 and earlier from automatically showing the prompt
|
||||
promptEvent.preventDefault();
|
||||
|
||||
try {
|
||||
await store.dispatch('notification/confirm', 'Add StackEdit to your home screen?');
|
||||
promptEvent.prompt();
|
||||
await promptEvent.userChoice;
|
||||
} catch (err) {
|
||||
// Cancel
|
||||
}
|
||||
localStorage.installPrompted = true;
|
||||
});
|
||||
}
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
/* eslint-disable no-new */
|
||||
|
|
|
@ -7,6 +7,7 @@ const clientId = GOOGLE_CLIENT_ID;
|
|||
const apiKey = 'AIzaSyC_M4RA9pY6XmM9pmFxlT59UPMO7aHr9kk';
|
||||
const appsDomain = null;
|
||||
const tokenExpirationMargin = 5 * 60 * 1000; // 5 min (Google tokens expire after 1h)
|
||||
let googlePlusNotification = true;
|
||||
|
||||
const driveAppDataScopes = ['https://www.googleapis.com/auth/drive.appdata'];
|
||||
const getDriveScopes = token => [token.driveFullAccess
|
||||
|
@ -160,7 +161,12 @@ export default {
|
|||
|
||||
// Call the user info endpoint
|
||||
const user = await getUser('me', token);
|
||||
token.name = user.displayName;
|
||||
if (user.displayName) {
|
||||
token.name = user.displayName;
|
||||
} else if (googlePlusNotification) {
|
||||
store.dispatch('notification/info', 'Please activate Google Plus to change your account name and photo.');
|
||||
googlePlusNotification = false;
|
||||
}
|
||||
userSvc.addInfo({
|
||||
id: `${subPrefix}:${user.id}`,
|
||||
name: user.displayName,
|
||||
|
@ -449,10 +455,10 @@ export default {
|
|||
},
|
||||
});
|
||||
revisions.forEach((revision) => {
|
||||
store.commit('userInfo/addItem', {
|
||||
userSvc.addInfo({
|
||||
id: `${subPrefix}:${revision.lastModifyingUser.permissionId}`,
|
||||
name: revision.lastModifyingUser.displayName,
|
||||
imageUrl: revision.lastModifyingUser.photoLink,
|
||||
imageUrl: revision.lastModifyingUser.photoLink || '',
|
||||
});
|
||||
allRevisions.push(revision);
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import providerRegistry from '../services/providers/common/providerRegistry';
|
||||
import utils from '../services/utils';
|
||||
|
||||
const defaultTimeout = 5000;
|
||||
const defaultTimeout = 5000; // 5 sec
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
|
@ -14,20 +15,49 @@ export default {
|
|||
},
|
||||
actions: {
|
||||
showItem({ state, commit }, item) {
|
||||
if (state.items.every(other => other.type !== item.type || other.content !== item.content)) {
|
||||
const existingItem = utils.someResult(
|
||||
state.items,
|
||||
other => other.type === item.type && other.content === item.content && item,
|
||||
);
|
||||
if (existingItem) {
|
||||
return existingItem.promise;
|
||||
}
|
||||
|
||||
item.promise = new Promise((resolve, reject) => {
|
||||
commit('setItems', [...state.items, item]);
|
||||
const removeItem = () => commit(
|
||||
'setItems',
|
||||
state.items.filter(otherItem => otherItem !== item),
|
||||
);
|
||||
setTimeout(
|
||||
() => commit('setItems', state.items.filter(otherItem => otherItem !== item)),
|
||||
() => removeItem(),
|
||||
item.timeout || defaultTimeout,
|
||||
);
|
||||
}
|
||||
item.resolve = (res) => {
|
||||
removeItem();
|
||||
resolve(res);
|
||||
};
|
||||
item.reject = (err) => {
|
||||
removeItem();
|
||||
reject(err);
|
||||
};
|
||||
});
|
||||
|
||||
return item.promise;
|
||||
},
|
||||
info({ dispatch }, info) {
|
||||
dispatch('showItem', {
|
||||
return dispatch('showItem', {
|
||||
type: 'info',
|
||||
content: info,
|
||||
});
|
||||
},
|
||||
confirm({ dispatch }, question) {
|
||||
return dispatch('showItem', {
|
||||
type: 'confirm',
|
||||
content: question,
|
||||
timeout: 10000, // 10 sec
|
||||
});
|
||||
},
|
||||
error({ dispatch, rootState }, error) {
|
||||
const item = { type: 'error' };
|
||||
if (error) {
|
||||
|
@ -48,7 +78,7 @@ export default {
|
|||
if (!item.content || item.content === '[object Object]') {
|
||||
item.content = 'Unknown error.';
|
||||
}
|
||||
dispatch('showItem', item);
|
||||
return dispatch('showItem', item);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user