diff --git a/frontend/app/angular.json b/frontend/app/angular.json index b2c7239b..3ce45bbb 100644 --- a/frontend/app/angular.json +++ b/frontend/app/angular.json @@ -40,14 +40,17 @@ "glob": "CHANGELOG.md", "input": ".", "output": "assets" - } + }, + "src/manifest.webmanifest" ], "styles": [ { "input": "src/global.scss", "inject": true } - ] + ], + "serviceWorker": true, + "ngswConfigPath": "ngsw-config.json" }, "configurations": { "production": { @@ -129,7 +132,8 @@ "glob": "**/*", "input": "src/assets", "output": "/assets" - } + }, + "src/manifest.webmanifest" ] } }, diff --git a/frontend/app/ngsw-config.json b/frontend/app/ngsw-config.json new file mode 100644 index 00000000..b4f5aa44 --- /dev/null +++ b/frontend/app/ngsw-config.json @@ -0,0 +1,21 @@ +{ + "$schema": "./node_modules/@angular/service-worker/config/schema.json", + "index": "/index.html", + "assetGroups": [ + { + "name": "app", + "installMode": "prefetch", + "resources": { + "files": ["/favicon.ico", "/index.html", "/manifest.webmanifest", "/*.css", "/*.js"] + } + }, + { + "name": "assets", + "installMode": "lazy", + "updateMode": "prefetch", + "resources": { + "files": ["/assets/**", "/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"] + } + } + ] +} diff --git a/frontend/app/package.json b/frontend/app/package.json index e52845cc..0359bae0 100644 --- a/frontend/app/package.json +++ b/frontend/app/package.json @@ -59,6 +59,7 @@ "@angular/forms": "17.3.0", "@angular/platform-browser": "17.3.0", "@angular/router": "17.3.0", + "@angular/service-worker": "17.3.0", "@awesome-cordova-plugins/calendar": "6.6.0", "@awesome-cordova-plugins/core": "6.6.0", "@capacitor-community/screen-brightness": "6.0.0", diff --git a/frontend/app/resources/logo_pwa.svg b/frontend/app/resources/logo_pwa.svg new file mode 100644 index 00000000..cc119dcf --- /dev/null +++ b/frontend/app/resources/logo_pwa.svg @@ -0,0 +1,73 @@ + + + + diff --git a/frontend/app/src/app/app.module.ts b/frontend/app/src/app/app.module.ts index 80c0fcd6..e08b7b2c 100644 --- a/frontend/app/src/app/app.module.ts +++ b/frontend/app/src/app/app.module.ts @@ -15,7 +15,7 @@ import {CommonModule, LocationStrategy, PathLocationStrategy, registerLocaleData} from '@angular/common'; import {HTTP_INTERCEPTORS, HttpClient, HttpClientModule} from '@angular/common/http'; import localeDe from '@angular/common/locales/de'; -import {APP_INITIALIZER, NgModule} from '@angular/core'; +import {APP_INITIALIZER, NgModule, isDevMode} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {RouteReuseStrategy} from '@angular/router'; import {IonicModule, IonicRouteStrategy, Platform} from '@ionic/angular'; @@ -71,6 +71,7 @@ import {Capacitor} from '@capacitor/core'; import {SplashScreen} from '@capacitor/splash-screen'; import maplibregl from 'maplibre-gl'; import {Protocol} from 'pmtiles'; +import {ServiceWorkerModule} from '@angular/service-worker'; registerLocaleData(localeDe); @@ -185,6 +186,12 @@ export function createTranslateLoader(http: HttpClient) { LoggerModule.forRoot({ level: environment.production ? NgxLoggerLevel.FATAL : NgxLoggerLevel.TRACE, }), + ServiceWorkerModule.register('ngsw-worker.js', { + enabled: !isDevMode(), + // Register the ServiceWorker as soon as the application is stable + // or after 30 seconds (whichever comes first). + registrationStrategy: 'registerWhenStable:30000', + }), ], providers: [ { diff --git a/frontend/app/src/assets/icons/icon-128x128.png b/frontend/app/src/assets/icons/icon-128x128.png new file mode 100644 index 00000000..7eb6cbe9 Binary files /dev/null and b/frontend/app/src/assets/icons/icon-128x128.png differ diff --git a/frontend/app/src/assets/icons/icon-144x144.png b/frontend/app/src/assets/icons/icon-144x144.png new file mode 100644 index 00000000..54ab9046 Binary files /dev/null and b/frontend/app/src/assets/icons/icon-144x144.png differ diff --git a/frontend/app/src/assets/icons/icon-152x152.png b/frontend/app/src/assets/icons/icon-152x152.png new file mode 100644 index 00000000..e81c54f9 Binary files /dev/null and b/frontend/app/src/assets/icons/icon-152x152.png differ diff --git a/frontend/app/src/assets/icons/icon-192x192.png b/frontend/app/src/assets/icons/icon-192x192.png new file mode 100644 index 00000000..5667d0d2 Binary files /dev/null and b/frontend/app/src/assets/icons/icon-192x192.png differ diff --git a/frontend/app/src/assets/icons/icon-384x384.png b/frontend/app/src/assets/icons/icon-384x384.png new file mode 100644 index 00000000..5b9591d3 Binary files /dev/null and b/frontend/app/src/assets/icons/icon-384x384.png differ diff --git a/frontend/app/src/assets/icons/icon-512x512.png b/frontend/app/src/assets/icons/icon-512x512.png new file mode 100644 index 00000000..48b087cc Binary files /dev/null and b/frontend/app/src/assets/icons/icon-512x512.png differ diff --git a/frontend/app/src/assets/icons/icon-72x72.png b/frontend/app/src/assets/icons/icon-72x72.png new file mode 100644 index 00000000..1aa709e1 Binary files /dev/null and b/frontend/app/src/assets/icons/icon-72x72.png differ diff --git a/frontend/app/src/assets/icons/icon-96x96.png b/frontend/app/src/assets/icons/icon-96x96.png new file mode 100644 index 00000000..15563589 Binary files /dev/null and b/frontend/app/src/assets/icons/icon-96x96.png differ diff --git a/frontend/app/src/assets/screenshots/canteens-wide.png b/frontend/app/src/assets/screenshots/canteens-wide.png new file mode 100644 index 00000000..c68242b2 Binary files /dev/null and b/frontend/app/src/assets/screenshots/canteens-wide.png differ diff --git a/frontend/app/src/assets/screenshots/canteens.png b/frontend/app/src/assets/screenshots/canteens.png new file mode 100644 index 00000000..5b9e8f42 Binary files /dev/null and b/frontend/app/src/assets/screenshots/canteens.png differ diff --git a/frontend/app/src/assets/screenshots/map-wide.png b/frontend/app/src/assets/screenshots/map-wide.png new file mode 100644 index 00000000..21b790de Binary files /dev/null and b/frontend/app/src/assets/screenshots/map-wide.png differ diff --git a/frontend/app/src/assets/screenshots/map.png b/frontend/app/src/assets/screenshots/map.png new file mode 100644 index 00000000..449be0ca Binary files /dev/null and b/frontend/app/src/assets/screenshots/map.png differ diff --git a/frontend/app/src/assets/screenshots/my-app-wide.png b/frontend/app/src/assets/screenshots/my-app-wide.png new file mode 100644 index 00000000..2f03c0ee Binary files /dev/null and b/frontend/app/src/assets/screenshots/my-app-wide.png differ diff --git a/frontend/app/src/assets/screenshots/my-app.png b/frontend/app/src/assets/screenshots/my-app.png new file mode 100644 index 00000000..65398f0a Binary files /dev/null and b/frontend/app/src/assets/screenshots/my-app.png differ diff --git a/frontend/app/src/assets/screenshots/overview-wide.png b/frontend/app/src/assets/screenshots/overview-wide.png new file mode 100644 index 00000000..995e53bc Binary files /dev/null and b/frontend/app/src/assets/screenshots/overview-wide.png differ diff --git a/frontend/app/src/assets/screenshots/overview.png b/frontend/app/src/assets/screenshots/overview.png new file mode 100644 index 00000000..14615cee Binary files /dev/null and b/frontend/app/src/assets/screenshots/overview.png differ diff --git a/frontend/app/src/index.html b/frontend/app/src/index.html index cf3ded06..98732253 100644 --- a/frontend/app/src/index.html +++ b/frontend/app/src/index.html @@ -23,8 +23,11 @@ + + + diff --git a/frontend/app/src/main.ts b/frontend/app/src/main.ts index c7b912ea..a9c1785c 100644 --- a/frontend/app/src/main.ts +++ b/frontend/app/src/main.ts @@ -12,6 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ +import '@capacitor/core'; import {enableProdMode} from '@angular/core'; import {platformBrowser} from '@angular/platform-browser'; import {AppModule} from './app/app.module'; diff --git a/frontend/app/src/manifest.webmanifest b/frontend/app/src/manifest.webmanifest new file mode 100644 index 00000000..e225be7c --- /dev/null +++ b/frontend/app/src/manifest.webmanifest @@ -0,0 +1,140 @@ +{ + "name": "StApps", + "short_name": "StApps", + "description": "Goethe-Uni App (powered by Open StApps)\n\nMit der Goethe-Uni App kannst dein Studium noch besser organisieren. Informationen über die Universität, Bibliotheken, Räumen, Veranstaltungen und Personen sind leicht über die Suche auffindbar. Zudem sind nun die Bibliotheksdienste und Notenübersicht integriert. Die Informationssysteme des Fachbereich 16 sind nicht integriert.\n\nBei Fragen und Anregungen kann das Feedback Tool in der App genutzt werden.\n\nWeiterhin ist das App-Team der Goethe-Universität unter app@rz.uni-frankfurt.de erreichbar.\n\nFeatures:\n\n- aktuelle Uni News\n- Vorlesungsverzeichnis\n- Umfassende Suche\n- Stellenangebote des Career Service\n- Bibliotheksdienste & Bibliothekskatalog\n- Notenübersicht\n- tagesaktuelle Speisepläne der Mensen und Cafeterien\n- Favoritenliste anlegen und verwalten\n- persönlichen Stundenplan erstellen (nicht mit QIS/LSF synchronisiert)", + "theme_color": "#3880ff", + "background_color": "#3880ff", + "display": "standalone", + "scope": "./", + "start_url": "./", + "prefer_related_applications": true, + "related_applications": [ + { + "platform": "play", + "id": "de.goetheuni" + } + ], + "categories": ["education"], + "shortcuts": [ + { + "name": "Mensa", + "url": "/canteen" + }, + { + "name": "Karte", + "url": "/map" + }, + { + "name": "Kalender", + "url": "/schedule/now" + }, + { + "name": "Wochenübersicht", + "url": "/schedule/week-overview" + }, + { + "name": "Suche", + "url": "/search" + }, + { + "name": "Meine App", + "url": "/profile" + } + ], + "icons": [ + { + "src": "assets/icons/icon-72x72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-96x96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-128x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-152x152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-384x384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable any" + } + ], + "screnshots": [ + { + "src": "assets/screenshots/overview.png", + "type": "image/png", + "sizes": "664x1440" + }, + { + "src": "assets/screenshots/canteens.png", + "type": "image/png", + "sizes": "664x1440" + }, + { + "src": "assets/screenshots/map.png", + "type": "image/png", + "sizes": "664x1440" + }, + { + "src": "assets/screenshots/my-app.png", + "type": "image/png", + "sizes": "664x1440" + }, + { + "src": "assets/screenshots/overview-wide.png", + "type": "image/png", + "sizes": "3204x1440", + "form_factor": "wide" + }, + { + "src": "assets/screenshots/canteens-wide.png", + "type": "image/png", + "sizes": "3204x1440", + "form_factor": "wide" + }, + { + "src": "assets/screenshots/map-wide.png", + "type": "image/png", + "sizes": "3204x1440", + "form_factor": "wide" + }, + { + "src": "assets/screenshots/my-app-wide.png", + "type": "image/png", + "sizes": "3204x1440", + "form_factor": "wide" + } + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index debfce69..ca4598bb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -722,6 +722,9 @@ importers: '@angular/router': specifier: 17.3.0 version: 17.3.0(@angular/common@17.3.0)(@angular/core@17.3.0)(@angular/platform-browser@17.3.0)(rxjs@7.8.1) + '@angular/service-worker': + specifier: 17.3.0 + version: 17.3.0(@angular/common@17.3.0)(@angular/core@17.3.0) '@awesome-cordova-plugins/calendar': specifier: 6.6.0 version: 6.6.0(@awesome-cordova-plugins/core@6.6.0)(rxjs@7.8.1) @@ -887,7 +890,7 @@ importers: version: 0.1703.0 '@angular-devkit/build-angular': specifier: 17.3.0 - version: 17.3.0(@angular/compiler-cli@17.3.0)(@types/node@18.15.3)(karma@6.4.3)(typescript@5.4.2) + version: 17.3.0(@angular/compiler-cli@17.3.0)(@angular/service-worker@17.3.0)(@types/node@18.15.3)(karma@6.4.3)(typescript@5.4.2) '@angular-devkit/core': specifier: 17.3.0 version: 17.3.0 @@ -2076,7 +2079,7 @@ packages: - chokidar dev: true - /@angular-devkit/build-angular@17.3.0(@angular/compiler-cli@17.3.0)(@types/node@18.15.3)(karma@6.4.3)(typescript@5.4.2): + /@angular-devkit/build-angular@17.3.0(@angular/compiler-cli@17.3.0)(@angular/service-worker@17.3.0)(@types/node@18.15.3)(karma@6.4.3)(typescript@5.4.2): resolution: {integrity: sha512-mC70mZK/liITM4VlGL6hmYPkVsZwAb+X3TxwodBl/g8p/sYijDhK/4QJHzmcHTxLYQQS6nS5CUcr9ARQFkGN2w==} engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: @@ -2122,6 +2125,7 @@ packages: '@angular-devkit/build-webpack': 0.1703.0(webpack-dev-server@4.15.1)(webpack@5.90.3) '@angular-devkit/core': 17.3.0 '@angular/compiler-cli': 17.3.0(@angular/compiler@17.3.0)(typescript@5.4.2) + '@angular/service-worker': 17.3.0(@angular/common@17.3.0)(@angular/core@17.3.0) '@babel/core': 7.24.0 '@babel/generator': 7.23.6 '@babel/helper-annotate-as-pure': 7.22.5 @@ -2602,6 +2606,18 @@ packages: tslib: 2.6.2 dev: false + /@angular/service-worker@17.3.0(@angular/common@17.3.0)(@angular/core@17.3.0): + resolution: {integrity: sha512-kpwuK3aaUrVm1T2YS4Vq7IFBAEW3H83Xyl9KVSpRbdUOEAJjG9hgiPBVz/iu0W1j0T9JkS2GJt/3vP3OW5Tkhg==} + engines: {node: ^18.13.0 || >=20.9.0} + hasBin: true + peerDependencies: + '@angular/common': 17.3.0 + '@angular/core': 17.3.0 + dependencies: + '@angular/common': 17.3.0(@angular/core@17.3.0)(rxjs@7.8.1) + '@angular/core': 17.3.0(rxjs@7.8.1)(zone.js@0.14.4) + tslib: 2.6.2 + /@awesome-cordova-plugins/calendar@6.6.0(@awesome-cordova-plugins/core@6.6.0)(rxjs@7.8.1): resolution: {integrity: sha512-NobAl4xvmq2zBeOnLI+pqRVpC66p7OpCwd3jzrQ26h8kqhr0o5wqaNcWN6WBjmgD+/AInVnLUzsziL2QpcmD7g==} peerDependencies: