Add service worker
parent
de4bb84e40
commit
36e2f9d9ff
|
@ -32,5 +32,8 @@ return [
|
|||
|
||||
// Config API
|
||||
['name' => 'api#setUserConfig', 'url' => '/api/config/{key}', 'verb' => 'PUT'],
|
||||
|
||||
// Service worker
|
||||
['name' => 'api#serviceWorker', 'url' => '/service-worker.js', 'verb' => 'GET'],
|
||||
]
|
||||
];
|
||||
|
|
|
@ -33,6 +33,8 @@ use OCP\App\IAppManager;
|
|||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\AppFramework\Http\StreamResponse;
|
||||
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
|
@ -637,4 +639,22 @@ class ApiController extends Controller {
|
|||
$this->config->setUserValue($userId, Application::APPNAME, $key, $value);
|
||||
return new JSONResponse([], Http::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function serviceWorker(): StreamResponse {
|
||||
$response = new StreamResponse(__DIR__.'/../../js/memories-service-worker.js');
|
||||
$response->setHeaders([
|
||||
'Content-Type' => 'application/javascript',
|
||||
'Service-Worker-Allowed' => '/'
|
||||
]);
|
||||
$policy = new ContentSecurityPolicy();
|
||||
$policy->addAllowedWorkerSrcDomain("'self'");
|
||||
$policy->addAllowedScriptDomain("'self'");
|
||||
$policy->addAllowedConnectDomain("'self'");
|
||||
$response->setContentSecurityPolicy($policy);
|
||||
return $response;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ use OCA\Files\Event\LoadSidebar;
|
|||
use OCP\AppFramework\Controller;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Util;
|
||||
|
@ -71,7 +72,12 @@ class PageController extends Controller {
|
|||
$this->initialState->provideInitialState('recognize', $this->appManager->isEnabledForUser('recognize') === true);
|
||||
$this->initialState->provideInitialState('version', $this->appManager->getAppInfo('memories')["version"]);
|
||||
|
||||
$policy = new ContentSecurityPolicy();
|
||||
$policy->addAllowedWorkerSrcDomain("'self'");
|
||||
$policy->addAllowedScriptDomain("'self'");
|
||||
|
||||
$response = new TemplateResponse($this->appName, 'main');
|
||||
$response->setContentSecurityPolicy($policy);
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,6 +65,7 @@
|
|||
"@types/url-parse": "^1.4.8",
|
||||
"playwright": "^1.27.1",
|
||||
"ts-loader": "^9.4.1",
|
||||
"typescript": "^4.8.4"
|
||||
"typescript": "^4.8.4",
|
||||
"workbox-webpack-plugin": "^6.5.4"
|
||||
}
|
||||
}
|
||||
|
|
18
src/App.vue
18
src/App.vue
|
@ -57,6 +57,7 @@ import {
|
|||
NcContent, NcAppContent, NcAppNavigation,
|
||||
NcAppNavigationItem, NcAppNavigationSettings,
|
||||
} from '@nextcloud/vue';
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
|
||||
import Timeline from './components/Timeline.vue'
|
||||
import Settings from './components/Settings.vue'
|
||||
|
@ -104,6 +105,23 @@ export default class App extends Mixins(GlobalMixin, UserConfig) {
|
|||
contentVue.classList.add('nextcloud-major-' + version[0]);
|
||||
}
|
||||
}
|
||||
|
||||
async beforeMount() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
// Use the window load event to keep the page load performant
|
||||
window.addEventListener('load', async () => {
|
||||
try {
|
||||
const url = generateUrl('/apps/memories/service-worker.js');
|
||||
const registration = await navigator.serviceWorker.register(url, { scope: generateUrl('/apps/memories') });
|
||||
console.log('SW registered: ', registration);
|
||||
} catch (error) {
|
||||
console.error('SW registration failed: ', error);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.debug('Service Worker is not enabled on this browser.')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
43
webpack.js
43
webpack.js
|
@ -1,6 +1,10 @@
|
|||
const webpackConfig = require('@nextcloud/webpack-vue-config')
|
||||
const WorkboxPlugin = require('workbox-webpack-plugin')
|
||||
const path = require('path')
|
||||
|
||||
const buildMode = process.env.NODE_ENV
|
||||
const isDev = buildMode === 'development'
|
||||
|
||||
webpackConfig.module.rules.push({
|
||||
test: /\.ts?$/,
|
||||
loader: 'ts-loader',
|
||||
|
@ -21,4 +25,43 @@ webpackConfig.watchOptions = {
|
|||
aggregateTimeout: 300,
|
||||
};
|
||||
|
||||
if (!isDev) {
|
||||
webpackConfig.plugins.push(
|
||||
new WorkboxPlugin.GenerateSW({
|
||||
swDest: 'memories-service-worker.js',
|
||||
clientsClaim: true,
|
||||
skipWaiting: true,
|
||||
exclude: [new RegExp('.*')], // don't do precaching
|
||||
inlineWorkboxRuntime: true,
|
||||
sourcemap: false,
|
||||
|
||||
// Define runtime caching rules.
|
||||
runtimeCaching: [{
|
||||
// Match any preview file request
|
||||
urlPattern: /^.*\/core\/preview\?fileId=.*/,
|
||||
handler: 'CacheFirst',
|
||||
|
||||
options: {
|
||||
cacheName: 'images',
|
||||
expiration: {
|
||||
maxAgeSeconds: 3600 * 24 * 7, // one week
|
||||
maxEntries: 20000, // 20k images
|
||||
},
|
||||
},
|
||||
}, {
|
||||
// Match page requests
|
||||
urlPattern: /^.*\/.*$/,
|
||||
handler: 'NetworkFirst',
|
||||
options: {
|
||||
cacheName: 'pages',
|
||||
expiration: {
|
||||
maxAgeSeconds: 3600 * 24 * 7, // one week
|
||||
maxEntries: 2000, // assets
|
||||
},
|
||||
},
|
||||
}],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = webpackConfig
|
||||
|
|
Loading…
Reference in New Issue