Compare commits

..

3 Commits

Author SHA1 Message Date
Rainer Killinger
14b41beee2 refactor: upgrade to Capacitor 7 2025-08-12 18:18:48 +02:00
Rainer Killinger
4a48e330bc feat: add in app rating 2025-08-12 18:18:33 +02:00
Rainer Killinger
1c39483e9d refactor: upgrade to Capacitor 7 2025-08-12 18:18:33 +02:00
79 changed files with 1613 additions and 2793 deletions

View File

@@ -0,0 +1,6 @@
---
"@openstapps/backend": patch
"@openstapps/logger": patch
---
Updated nodemailer dependency

7
.vscode/launch.json vendored
View File

@@ -4,13 +4,6 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{
"name": "Launch Chrome",
"request": "launch",
"type": "chrome",
"url": "http://localhost:8100",
"webRoot": "${workspaceFolder}/frontend/app/www"
},
{ {
"type":"node", "type":"node",
"request": "launch", "request": "launch",

View File

@@ -1,24 +1,5 @@
# @openstapps/backend # @openstapps/backend
## 4.0.3
### Patch Changes
- 3a274a3a: Upgrade to Capacitor 7 and Anuglar 18
- @openstapps/core@4.0.2
- @openstapps/core-tools@4.0.2
- @openstapps/logger@4.0.2
## 4.0.2
### Patch Changes
- 6b06de40: Updated nodemailer dependency
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
- @openstapps/core@4.0.2
- @openstapps/core-tools@4.0.2
## 4.0.1 ## 4.0.1
### Patch Changes ### Patch Changes

View File

@@ -112,7 +112,7 @@ const menus = [
icon: 'school', icon: 'school',
items: [ items: [
{ {
icon: 'star', icon: 'grade',
route: '/favorites', route: '/favorites',
title: 'favorites', title: 'favorites',
translations: { translations: {

View File

@@ -5,8 +5,8 @@ const userGroupSetting = {
categories: ['profile'], categories: ['profile'],
defaultValue: 'students', defaultValue: 'students',
description: description:
'The user group the app is going to use primarily.' + 'The user group the app is going to be used.' +
' This settings for example is getting used for the predefined price category of mensa meals.', 'This settings for example is getting used for the predefined price category of mensa meals.',
inputType: SCSettingInputType.SingleChoice, inputType: SCSettingInputType.SingleChoice,
name: 'group', name: 'group',
order: 1, order: 1,
@@ -25,7 +25,7 @@ const userGroupSetting = {
}, },
en: { en: {
description: description:
'The user group the app is going to use primarily.' + 'The user group the app is going to be used.' +
' This settings for example is getting used for the predefined price category of mensa meals.', ' This settings for example is getting used for the predefined price category of mensa meals.',
name: 'Group', name: 'Group',
values: ['students', 'employees', 'guests'], values: ['students', 'employees', 'guests'],

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/backend", "name": "@openstapps/backend",
"description": "A reference implementation for a StApps backend", "description": "A reference implementation for a StApps backend",
"version": "4.0.3", "version": "4.0.1",
"private": true, "private": true,
"type": "module", "type": "module",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",

View File

@@ -1,12 +1,5 @@
# @openstapps/proxy # @openstapps/proxy
## 4.0.2
### Patch Changes
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/proxy", "name": "@openstapps/proxy",
"description": "NGINX proxy that is dynamically configured by a Node.js script", "description": "NGINX proxy that is dynamically configured by a Node.js script",
"version": "4.0.2", "version": "4.0.0",
"private": true, "private": true,
"type": "module", "type": "module",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",

View File

@@ -1,11 +1,5 @@
# @openstapps/backend-config # @openstapps/backend-config
## 4.0.3
### Patch Changes
- 3a274a3a: Upgrade to Capacitor 7 and Anuglar 18
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/backend-config", "name": "@openstapps/backend-config",
"description": "Backend Configuration for OpenStApps", "description": "Backend Configuration for OpenStApps",
"version": "4.0.3", "version": "4.0.0",
"private": true, "private": true,
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",

View File

@@ -10,7 +10,7 @@
<group title="canteen" title.de="Mensa" icon="local_cafe" route="/canteen"/> <group title="canteen" title.de="Mensa" icon="local_cafe" route="/canteen"/>
<group title="campus map" title.de="Campus Karte" icon="map" route="/map"/> <group title="campus map" title.de="Campus Karte" icon="map" route="/map"/>
<group title="my app" title.de="Meine App" icon="school" route="/profile"> <group title="my app" title.de="Meine App" icon="school" route="/profile">
<item title="favorites" title.de="Favoriten" icon="star" route="/favorites"/> <item title="favorites" title.de="Favoriten" icon="grade" route="/favorites"/>
<item title="schedule" title.de="Stundenplan" icon="calendar_today" route="/schedule"/> <item title="schedule" title.de="Stundenplan" icon="calendar_today" route="/schedule"/>
<item title="library account" title.de="Bibliothekskonto" icon="badge" route="/library-account" authProvider="paia"/> <item title="library account" title.de="Bibliothekskonto" icon="badge" route="/library-account" authProvider="paia"/>
<item title="settings" title.de="Einstellungen" icon="settings" route="/settings"/> <item title="settings" title.de="Einstellungen" icon="settings" route="/settings"/>

View File

@@ -10,7 +10,7 @@
<group title="canteen" title.de="Mensa" icon="local_cafe" route="/canteen"/> <group title="canteen" title.de="Mensa" icon="local_cafe" route="/canteen"/>
<group title="campus map" title.de="Campus Karte" icon="map" route="/map"/> <group title="campus map" title.de="Campus Karte" icon="map" route="/map"/>
<group title="my app" title.de="Meine App" icon="school" route="/profile"> <group title="my app" title.de="Meine App" icon="school" route="/profile">
<item title="favorites" title.de="Favoriten" icon="star" route="/favorites"/> <item title="favorites" title.de="Favoriten" icon="grade" route="/favorites"/>
<item title="schedule" title.de="Stundenplan" icon="calendar_today" route="/schedule"/> <item title="schedule" title.de="Stundenplan" icon="calendar_today" route="/schedule"/>
<item title="library account" title.de="Bibliothekskonto" icon="badge" route="/library-account" authProvider="paia"/> <item title="library account" title.de="Bibliothekskonto" icon="badge" route="/library-account" authProvider="paia"/>
<item title="settings" title.de="Einstellungen" icon="settings" route="/settings"/> <item title="settings" title.de="Einstellungen" icon="settings" route="/settings"/>

View File

@@ -1,11 +1,5 @@
# @openstapps/eslint-config # @openstapps/eslint-config
## 4.0.3
### Patch Changes
- 3a274a3a: Upgrade to Capacitor 7 and Anuglar 18
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/eslint-config", "name": "@openstapps/eslint-config",
"description": "A collection of configuration base files for StApps projects. Just an (unused) experiment for now.", "description": "A collection of configuration base files for StApps projects. Just an (unused) experiment for now.",
"version": "4.0.3", "version": "4.0.0",
"type": "commonjs", "type": "commonjs",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/eslint-config.git", "repository": "git@gitlab.com:openstapps/eslint-config.git",
@@ -22,8 +22,8 @@
"typescript": "5.4.2" "typescript": "5.4.2"
}, },
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/eslint-plugin": "7.11.0", "@typescript-eslint/eslint-plugin": "7.2.0",
"@typescript-eslint/parser": "7.11.0", "@typescript-eslint/parser": "7.2.0",
"eslint": "8.57.0", "eslint": "8.57.0",
"eslint-config-prettier": "9.1.0", "eslint-config-prettier": "9.1.0",
"eslint-plugin-jsdoc": "48.2.1", "eslint-plugin-jsdoc": "48.2.1",

View File

@@ -1,13 +1,5 @@
# @openstapps/projectmanagement # @openstapps/projectmanagement
## 4.0.2
### Patch Changes
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
- @openstapps/gitlab-api@4.0.2
## 4.0.1 ## 4.0.1
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/projectmanagement", "name": "@openstapps/projectmanagement",
"description": "Main documentation and scripts for maintenance.", "description": "Main documentation and scripts for maintenance.",
"version": "4.0.2", "version": "4.0.1",
"private": true, "private": true,
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",

View File

@@ -1,14 +1,5 @@
# @openstapps/minimal-connector # @openstapps/minimal-connector
## 4.0.2
### Patch Changes
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
- @openstapps/core@4.0.2
- @openstapps/api@4.0.2
## 4.0.1 ## 4.0.1
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/minimal-connector", "name": "@openstapps/minimal-connector",
"description": "This is a minimal connector which serves as an example", "description": "This is a minimal connector which serves as an example",
"version": "4.0.2", "version": "4.0.1",
"private": true, "private": true,
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",

View File

@@ -1,16 +1,5 @@
# @openstapps/minimal-plugin # @openstapps/minimal-plugin
## 4.0.2
### Patch Changes
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
- @openstapps/api-plugin@4.0.2
- @openstapps/core@4.0.2
- @openstapps/core-tools@4.0.2
- @openstapps/api@4.0.2
## 4.0.1 ## 4.0.1
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/minimal-plugin", "name": "@openstapps/minimal-plugin",
"description": "Minimal Plugin", "description": "Minimal Plugin",
"version": "4.0.2", "version": "4.0.1",
"private": true, "private": true,
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",

View File

@@ -1,21 +1,5 @@
# @openstapps/app # @openstapps/app
## 4.0.3
### Patch Changes
- 3a274a3a: Upgrade to Capacitor 7 and Anuglar 18
- @openstapps/api@4.0.2
- @openstapps/collection-utils@4.0.0
- @openstapps/core@4.0.2
## 4.0.2
### Patch Changes
- @openstapps/core@4.0.2
- @openstapps/api@4.0.2
## 4.0.1 ## 4.0.1
### Patch Changes ### Patch Changes

View File

@@ -27,7 +27,7 @@ include ':capacitor-filesystem'
project(':capacitor-filesystem').projectDir = new File('../../../node_modules/.pnpm/@capacitor+filesystem@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/filesystem/android') project(':capacitor-filesystem').projectDir = new File('../../../node_modules/.pnpm/@capacitor+filesystem@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/filesystem/android')
include ':capacitor-geolocation' include ':capacitor-geolocation'
project(':capacitor-geolocation').projectDir = new File('../../../node_modules/.pnpm/@capacitor+geolocation@7.1.5_@capacitor+core@7.4.2/node_modules/@capacitor/geolocation/android') project(':capacitor-geolocation').projectDir = new File('../../../node_modules/.pnpm/@capacitor+geolocation@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/geolocation/android')
include ':capacitor-haptics' include ':capacitor-haptics'
project(':capacitor-haptics').projectDir = new File('../../../node_modules/.pnpm/@capacitor+haptics@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/haptics/android') project(':capacitor-haptics').projectDir = new File('../../../node_modules/.pnpm/@capacitor+haptics@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/haptics/android')

View File

@@ -299,7 +299,7 @@
"icon": "school", "icon": "school",
"items": [ "items": [
{ {
"icon": "star", "icon": "grade",
"route": "/favorites", "route": "/favorites",
"title": "favorites", "title": "favorites",
"translations": { "translations": {

View File

@@ -33,9 +33,9 @@ describe('dashboard', async function () {
describe('schedule section', function () { describe('schedule section', function () {
it('should lead to the week overview', function () { it('should lead to the week overview', function () {
cy.get('.schedule') cy.get('.schedule')
.contains('a', /Wochen.*ansicht/) .contains('a', /Wochen.*übersicht/)
.click(); .click();
cy.url().should('include', '/schedule/weekly-view'); cy.url().should('include', '/schedule/week-overview');
}); });
it('should lead to the calendar', function () { it('should lead to the calendar', function () {

View File

@@ -100,7 +100,7 @@ describe('schedule', function () {
cy.get('ion-searchbar').click().type('a'); cy.get('ion-searchbar').click().type('a');
cy.wait('@search'); cy.wait('@search');
cy.wait('@chips'); cy.wait('@chips');
cy.wait(1000); cy.wait(200);
cy.contains('ion-item', 'UNIcert (Test)') cy.contains('ion-item', 'UNIcert (Test)')
.contains('stapps-add-event-action-chip', 'Termine Auswählen') .contains('stapps-add-event-action-chip', 'Termine Auswählen')
.click(); .click();

View File

@@ -20,7 +20,7 @@ const config = {
htmlGlob: 'src/**/*.html', htmlGlob: 'src/**/*.html',
scriptGlob: 'src/**/*.ts', scriptGlob: 'src/**/*.ts',
additionalIcons: { additionalIcons: {
about: ['copyright', 'campaign', 'policy', 'description', 'text_snippet', 'expand_more', 'expand_all'], about: ['copyright', 'campaign', 'policy', 'description', 'text_snippet'],
navigation: [ navigation: [
'home', 'home',
'newspaper', 'newspaper',
@@ -30,7 +30,7 @@ const config = {
'local_library', 'local_library',
'inventory_2', 'inventory_2',
'map', 'map',
'star', 'grade',
'account_circle', 'account_circle',
'settings', 'settings',
'info', 'info',

View File

@@ -19,7 +19,7 @@ def capacitor_pods
pod 'CapacitorDevice', :path => '../../../../node_modules/.pnpm/@capacitor+device@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/device' pod 'CapacitorDevice', :path => '../../../../node_modules/.pnpm/@capacitor+device@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/device'
pod 'CapacitorDialog', :path => '../../../../node_modules/.pnpm/@capacitor+dialog@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/dialog' pod 'CapacitorDialog', :path => '../../../../node_modules/.pnpm/@capacitor+dialog@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/dialog'
pod 'CapacitorFilesystem', :path => '../../../../node_modules/.pnpm/@capacitor+filesystem@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/filesystem' pod 'CapacitorFilesystem', :path => '../../../../node_modules/.pnpm/@capacitor+filesystem@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/filesystem'
pod 'CapacitorGeolocation', :path => '../../../../node_modules/.pnpm/@capacitor+geolocation@7.1.5_@capacitor+core@7.4.2/node_modules/@capacitor/geolocation' pod 'CapacitorGeolocation', :path => '../../../../node_modules/.pnpm/@capacitor+geolocation@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/geolocation'
pod 'CapacitorHaptics', :path => '../../../../node_modules/.pnpm/@capacitor+haptics@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/haptics' pod 'CapacitorHaptics', :path => '../../../../node_modules/.pnpm/@capacitor+haptics@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/haptics'
pod 'CapacitorKeyboard', :path => '../../../../node_modules/.pnpm/@capacitor+keyboard@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/keyboard' pod 'CapacitorKeyboard', :path => '../../../../node_modules/.pnpm/@capacitor+keyboard@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/keyboard'
pod 'CapacitorLocalNotifications', :path => '../../../../node_modules/.pnpm/@capacitor+local-notifications@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/local-notifications' pod 'CapacitorLocalNotifications', :path => '../../../../node_modules/.pnpm/@capacitor+local-notifications@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/local-notifications'

View File

@@ -19,9 +19,9 @@ PODS:
- CapacitorFilesystem (7.1.4): - CapacitorFilesystem (7.1.4):
- Capacitor - Capacitor
- IONFilesystemLib (~> 1.0.1) - IONFilesystemLib (~> 1.0.1)
- CapacitorGeolocation (7.1.5): - CapacitorGeolocation (7.1.4):
- Capacitor - Capacitor
- IONGeolocationLib (= 1.0.1) - IONGeolocationLib (~> 1.0)
- CapacitorHaptics (7.0.2): - CapacitorHaptics (7.0.2):
- Capacitor - Capacitor
- CapacitorKeyboard (7.0.2): - CapacitorKeyboard (7.0.2):
@@ -44,7 +44,7 @@ PODS:
- CordovaPlugins (7.4.2): - CordovaPlugins (7.4.2):
- CapacitorCordova - CapacitorCordova
- IONFilesystemLib (1.0.1) - IONFilesystemLib (1.0.1)
- IONGeolocationLib (1.0.1) - IONGeolocationLib (1.0.0)
- SwiftKeychainWrapper (4.0.1) - SwiftKeychainWrapper (4.0.1)
- TransistorsoftCapacitorBackgroundFetch (7.1.0): - TransistorsoftCapacitorBackgroundFetch (7.1.0):
- Capacitor - Capacitor
@@ -60,7 +60,7 @@ DEPENDENCIES:
- "CapacitorDevice (from `../../../../node_modules/.pnpm/@capacitor+device@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/device`)" - "CapacitorDevice (from `../../../../node_modules/.pnpm/@capacitor+device@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/device`)"
- "CapacitorDialog (from `../../../../node_modules/.pnpm/@capacitor+dialog@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/dialog`)" - "CapacitorDialog (from `../../../../node_modules/.pnpm/@capacitor+dialog@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/dialog`)"
- "CapacitorFilesystem (from `../../../../node_modules/.pnpm/@capacitor+filesystem@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/filesystem`)" - "CapacitorFilesystem (from `../../../../node_modules/.pnpm/@capacitor+filesystem@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/filesystem`)"
- "CapacitorGeolocation (from `../../../../node_modules/.pnpm/@capacitor+geolocation@7.1.5_@capacitor+core@7.4.2/node_modules/@capacitor/geolocation`)" - "CapacitorGeolocation (from `../../../../node_modules/.pnpm/@capacitor+geolocation@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/geolocation`)"
- "CapacitorHaptics (from `../../../../node_modules/.pnpm/@capacitor+haptics@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/haptics`)" - "CapacitorHaptics (from `../../../../node_modules/.pnpm/@capacitor+haptics@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/haptics`)"
- "CapacitorKeyboard (from `../../../../node_modules/.pnpm/@capacitor+keyboard@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/keyboard`)" - "CapacitorKeyboard (from `../../../../node_modules/.pnpm/@capacitor+keyboard@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/keyboard`)"
- "CapacitorLocalNotifications (from `../../../../node_modules/.pnpm/@capacitor+local-notifications@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/local-notifications`)" - "CapacitorLocalNotifications (from `../../../../node_modules/.pnpm/@capacitor+local-notifications@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/local-notifications`)"
@@ -101,7 +101,7 @@ EXTERNAL SOURCES:
CapacitorFilesystem: CapacitorFilesystem:
:path: "../../../../node_modules/.pnpm/@capacitor+filesystem@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/filesystem" :path: "../../../../node_modules/.pnpm/@capacitor+filesystem@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/filesystem"
CapacitorGeolocation: CapacitorGeolocation:
:path: "../../../../node_modules/.pnpm/@capacitor+geolocation@7.1.5_@capacitor+core@7.4.2/node_modules/@capacitor/geolocation" :path: "../../../../node_modules/.pnpm/@capacitor+geolocation@7.1.4_@capacitor+core@7.4.2/node_modules/@capacitor/geolocation"
CapacitorHaptics: CapacitorHaptics:
:path: "../../../../node_modules/.pnpm/@capacitor+haptics@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/haptics" :path: "../../../../node_modules/.pnpm/@capacitor+haptics@7.0.2_@capacitor+core@7.4.2/node_modules/@capacitor/haptics"
CapacitorKeyboard: CapacitorKeyboard:
@@ -136,7 +136,7 @@ SPEC CHECKSUMS:
CapacitorDevice: 81ae78d5d1942707caad79276badd458bf6ec603 CapacitorDevice: 81ae78d5d1942707caad79276badd458bf6ec603
CapacitorDialog: 5bf72a94b747fb339df6f64ef60812e5e4630ad2 CapacitorDialog: 5bf72a94b747fb339df6f64ef60812e5e4630ad2
CapacitorFilesystem: f9bd850c41e048180e5dc0cbb90f2033ede9d2cc CapacitorFilesystem: f9bd850c41e048180e5dc0cbb90f2033ede9d2cc
CapacitorGeolocation: 84f868bea4c2499aebc3bb3a88fd0a508f87ab87 CapacitorGeolocation: 32a1f849c38c72b5071de36a28ebc548ef3bb611
CapacitorHaptics: b3fb2869e72c4466e18ce9ccbeb60a3d8723b3d4 CapacitorHaptics: b3fb2869e72c4466e18ce9ccbeb60a3d8723b3d4
CapacitorKeyboard: a86aa9e4741b6444a802df26440a92ae041b34a6 CapacitorKeyboard: a86aa9e4741b6444a802df26440a92ae041b34a6
CapacitorLocalNotifications: 665188ae8accd40806129073896fb2b39322d858 CapacitorLocalNotifications: 665188ae8accd40806129073896fb2b39322d858
@@ -148,10 +148,10 @@ SPEC CHECKSUMS:
CapacitorSplashScreen: 157947576b59d913792063a8d442a79e6d283ee5 CapacitorSplashScreen: 157947576b59d913792063a8d442a79e6d283ee5
CordovaPlugins: 7b9a4f380c92ca7f28630723befaca556461f4c3 CordovaPlugins: 7b9a4f380c92ca7f28630723befaca556461f4c3
IONFilesystemLib: 89258b8e3e85465da93127d25d7ce37f977e8a6f IONFilesystemLib: 89258b8e3e85465da93127d25d7ce37f977e8a6f
IONGeolocationLib: 20f9d0248a0b5264511fb57a37e25dd2badf797a IONGeolocationLib: 81f33f88d025846946de2cf63b0c7628e7c6bc9d
SwiftKeychainWrapper: 807ba1d63c33a7d0613288512399cd1eda1e470c SwiftKeychainWrapper: 807ba1d63c33a7d0613288512399cd1eda1e470c
TransistorsoftCapacitorBackgroundFetch: 28e561636145a899f05025d31f627019c16791f5 TransistorsoftCapacitorBackgroundFetch: 28e561636145a899f05025d31f627019c16791f5
PODFILE CHECKSUM: 90bc09990a659848ea76c94331d39bad0b28024d PODFILE CHECKSUM: e0631161818ed4ac500327f0ee228d71857c0878
COCOAPODS: 1.16.2 COCOAPODS: 1.16.2

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/app", "name": "@openstapps/app",
"description": "The generic app tailored to fulfill needs of German universities, written using Ionic Framework.", "description": "The generic app tailored to fulfill needs of German universities, written using Ionic Framework.",
"version": "4.0.3", "version": "4.0.1",
"private": true, "private": true,
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>", "author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
@@ -48,13 +48,13 @@
"test:integration": "sh integration-test.sh" "test:integration": "sh integration-test.sh"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "18.2.13", "@angular/animations": "17.3.12",
"@angular/cdk": "18.2.13", "@angular/cdk": "17.3.10",
"@angular/common": "18.2.13", "@angular/common": "17.3.12",
"@angular/core": "18.2.13", "@angular/core": "17.3.12",
"@angular/forms": "18.2.13", "@angular/forms": "17.3.12",
"@angular/platform-browser": "18.2.13", "@angular/platform-browser": "17.3.12",
"@angular/router": "18.2.13", "@angular/router": "17.3.12",
"@awesome-cordova-plugins/calendar": "6.6.0", "@awesome-cordova-plugins/calendar": "6.6.0",
"@awesome-cordova-plugins/core": "6.6.0", "@awesome-cordova-plugins/core": "6.6.0",
"@capacitor-community/in-app-review": "7.0.1", "@capacitor-community/in-app-review": "7.0.1",
@@ -66,7 +66,7 @@
"@capacitor/device": "7.0.2", "@capacitor/device": "7.0.2",
"@capacitor/dialog": "7.0.2", "@capacitor/dialog": "7.0.2",
"@capacitor/filesystem": "7.1.4", "@capacitor/filesystem": "7.1.4",
"@capacitor/geolocation": "7.1.5", "@capacitor/geolocation": "7.1.4",
"@capacitor/haptics": "7.0.2", "@capacitor/haptics": "7.0.2",
"@capacitor/keyboard": "7.0.2", "@capacitor/keyboard": "7.0.2",
"@capacitor/local-notifications": "7.0.2", "@capacitor/local-notifications": "7.0.2",
@@ -75,8 +75,9 @@
"@capacitor/screen-orientation": "7.0.2", "@capacitor/screen-orientation": "7.0.2",
"@capacitor/share": "7.0.2", "@capacitor/share": "7.0.2",
"@capacitor/splash-screen": "7.0.2", "@capacitor/splash-screen": "7.0.2",
"@ionic/angular": "8.7.3", "@ionic-native/core": "5.36.0",
"@ionic/angular-server": "8.7.3", "@ionic/angular": "8.6.1",
"@ionic/angular-server": "8.6.1",
"@ionic/storage-angular": "4.0.0", "@ionic/storage-angular": "4.0.0",
"@maplibre/ngx-maplibre-gl": "17.4.1", "@maplibre/ngx-maplibre-gl": "17.4.1",
"@ngx-translate/core": "15.0.0", "@ngx-translate/core": "15.0.0",
@@ -93,8 +94,8 @@
"deepmerge": "4.3.1", "deepmerge": "4.3.1",
"form-data": "4.0.4", "form-data": "4.0.4",
"geojson": "0.5.0", "geojson": "0.5.0",
"ionic-appauth": "2.1.0", "ionic-appauth": "0.9.0",
"ionicons": "8.0.13", "ionicons": "7.4.0",
"jsonpath-plus": "10.3.0", "jsonpath-plus": "10.3.0",
"maplibre-gl": "4.0.2", "maplibre-gl": "4.0.2",
"material-symbols": "0.17.1", "material-symbols": "0.17.1",
@@ -110,31 +111,31 @@
"semver": "7.6.0", "semver": "7.6.0",
"swiper": "8.4.5", "swiper": "8.4.5",
"tslib": "2.6.2", "tslib": "2.6.2",
"zone.js": "0.14.10" "zone.js": "0.14.4"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/architect": "0.1802.20", "@angular-devkit/architect": "0.1703.17",
"@angular-devkit/build-angular": "18.2.20", "@angular-devkit/build-angular": "17.3.17",
"@angular-devkit/core": "18.2.20", "@angular-devkit/core": "17.3.17",
"@angular-devkit/schematics": "18.2.20", "@angular-devkit/schematics": "17.3.17",
"@angular-eslint/builder": "18.4.3", "@angular-eslint/builder": "17.5.3",
"@angular-eslint/eslint-plugin": "18.4.3", "@angular-eslint/eslint-plugin": "17.5.3",
"@angular-eslint/eslint-plugin-template": "18.4.3", "@angular-eslint/eslint-plugin-template": "17.5.3",
"@angular-eslint/schematics": "18.4.1", "@angular-eslint/schematics": "17.5.3",
"@angular-eslint/template-parser": "18.4.3", "@angular-eslint/template-parser": "17.5.3",
"@angular/cli": "18.2.20", "@angular/cli": "17.3.17",
"@angular/compiler": "18.2.13", "@angular/compiler": "17.3.12",
"@angular/compiler-cli": "18.2.13", "@angular/compiler-cli": "17.3.12",
"@angular/language-server": "18.2.0", "@angular/language-server": "17.3.2",
"@angular/language-service": "18.2.13", "@angular/language-service": "17.3.12",
"@angular/platform-browser-dynamic": "18.2.13", "@angular/platform-browser-dynamic": "17.3.12",
"@capacitor/android": "7.4.2", "@capacitor/android": "7.4.2",
"@capacitor/assets": "3.0.5", "@capacitor/assets": "3.0.5",
"@capacitor/cli": "7.4.2", "@capacitor/cli": "7.4.2",
"@capacitor/ios": "7.4.2", "@capacitor/ios": "7.4.2",
"@compodoc/compodoc": "1.1.23", "@compodoc/compodoc": "1.1.23",
"@cypress/schematic": "4.1.1", "@cypress/schematic": "3.0.0",
"@ionic/angular-toolkit": "12.3.0", "@ionic/angular-toolkit": "11.0.1",
"@ionic/cli": "7.2.0", "@ionic/cli": "7.2.0",
"@openstapps/prettier-config": "workspace:*", "@openstapps/prettier-config": "workspace:*",
"@openstapps/tsconfig": "workspace:*", "@openstapps/tsconfig": "workspace:*",
@@ -149,10 +150,10 @@
"@types/karma-jasmine": "4.0.5", "@types/karma-jasmine": "4.0.5",
"@types/node": "22.15.31", "@types/node": "22.15.31",
"@types/semver": "7.5.8", "@types/semver": "7.5.8",
"@typescript-eslint/eslint-plugin": "7.11.0", "@typescript-eslint/eslint-plugin": "7.2.0",
"@typescript-eslint/parser": "7.11.0", "@typescript-eslint/parser": "7.2.0",
"cordova-res": "0.15.4", "cordova-res": "0.15.4",
"cypress": "15.0.0", "cypress": "14.5.0",
"eslint": "8.57.0", "eslint": "8.57.0",
"eslint-plugin-jsdoc": "48.2.1", "eslint-plugin-jsdoc": "48.2.1",
"eslint-plugin-prettier": "5.1.3", "eslint-plugin-prettier": "5.1.3",

View File

@@ -33,7 +33,6 @@ import {sampleAuthConfiguration} from './_helpers/data/sample-configuration';
import {StorageProvider} from './modules/storage/storage.provider'; import {StorageProvider} from './modules/storage/storage.provider';
import {SimpleBrowser} from './util/browser.factory'; import {SimpleBrowser} from './util/browser.factory';
import {provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; import {provideHttpClient, withInterceptorsFromDi} from '@angular/common/http';
import {InAppReviewProvider} from './modules/settings/in-app-review/in-app-review.provider';
describe('AppComponent', () => { describe('AppComponent', () => {
let platformReadySpy: any; let platformReadySpy: any;
@@ -41,7 +40,6 @@ describe('AppComponent', () => {
let translateServiceSpy: jasmine.SpyObj<TranslateService>; let translateServiceSpy: jasmine.SpyObj<TranslateService>;
let thingTranslateServiceSpy: jasmine.SpyObj<ThingTranslateService>; let thingTranslateServiceSpy: jasmine.SpyObj<ThingTranslateService>;
let settingsProvider: jasmine.SpyObj<SettingsProvider>; let settingsProvider: jasmine.SpyObj<SettingsProvider>;
let inAppReviewProvider: jasmine.SpyObj<InAppReviewProvider>;
let configProvider: jasmine.SpyObj<ConfigProvider>; let configProvider: jasmine.SpyObj<ConfigProvider>;
let ngxLogger: jasmine.SpyObj<NGXLogger>; let ngxLogger: jasmine.SpyObj<NGXLogger>;
let scheduleSyncServiceSpy: jasmine.SpyObj<ScheduleSyncService>; let scheduleSyncServiceSpy: jasmine.SpyObj<ScheduleSyncService>;
@@ -87,7 +85,6 @@ describe('AppComponent', () => {
{provide: ThingTranslateService, useValue: thingTranslateServiceSpy}, {provide: ThingTranslateService, useValue: thingTranslateServiceSpy},
{provide: ScheduleSyncService, useValue: scheduleSyncServiceSpy}, {provide: ScheduleSyncService, useValue: scheduleSyncServiceSpy},
{provide: SettingsProvider, useValue: settingsProvider}, {provide: SettingsProvider, useValue: settingsProvider},
{provide: InAppReviewProvider, useValue: inAppReviewProvider},
{provide: ConfigProvider, useValue: configProvider}, {provide: ConfigProvider, useValue: configProvider},
{provide: NGXLogger, useValue: ngxLogger}, {provide: NGXLogger, useValue: ngxLogger},
{provide: StorageProvider, useValue: storageProvider}, {provide: StorageProvider, useValue: storageProvider},

View File

@@ -17,7 +17,10 @@ import {Router} from '@angular/router';
import {App, URLOpenListenerEvent} from '@capacitor/app'; import {App, URLOpenListenerEvent} from '@capacitor/app';
import {Platform, ToastController} from '@ionic/angular/standalone'; import {Platform, ToastController} from '@ionic/angular/standalone';
import {SettingsProvider} from './modules/settings/settings.provider'; import {SettingsProvider} from './modules/settings/settings.provider';
import {InAppReviewProvider} from './modules/settings/in-app-review/in-app-review.provider'; import {
increaseSessionCount,
startInappRatingIfFeasible,
} from './modules/settings/inapp-rating/inapp-rating.provider.js';
import {AuthHelperService} from './modules/auth/auth-helper.service'; import {AuthHelperService} from './modules/auth/auth-helper.service';
import {environment} from '../environments/environment'; import {environment} from '../environments/environment';
import {Capacitor} from '@capacitor/core'; import {Capacitor} from '@capacitor/core';
@@ -25,6 +28,7 @@ import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.s
import {Keyboard, KeyboardResize} from '@capacitor/keyboard'; import {Keyboard, KeyboardResize} from '@capacitor/keyboard';
import {AppVersionService} from './modules/about/app-version.service'; import {AppVersionService} from './modules/about/app-version.service';
import {SplashScreen} from '@capacitor/splash-screen'; import {SplashScreen} from '@capacitor/splash-screen';
import {StorageProvider} from './modules/storage/storage.provider.js';
/** /**
* TODO * TODO
@@ -56,7 +60,7 @@ export class AppComponent implements AfterContentInit {
constructor( constructor(
private readonly platform: Platform, private readonly platform: Platform,
private readonly settingsProvider: SettingsProvider, private readonly settingsProvider: SettingsProvider,
private readonly inAppReviewProvider: InAppReviewProvider, private readonly storageProvider: StorageProvider,
private readonly router: Router, private readonly router: Router,
private readonly zone: NgZone, private readonly zone: NgZone,
private readonly authHelper: AuthHelperService, private readonly authHelper: AuthHelperService,
@@ -88,8 +92,8 @@ export class AppComponent implements AfterContentInit {
async hideSplash() { async hideSplash() {
if (Capacitor.isNativePlatform()) { if (Capacitor.isNativePlatform()) {
void SplashScreen.hide(); void SplashScreen.hide();
await this.inAppReviewProvider.increaseSessionCount(); void increaseSessionCount(this.storageProvider);
void this.inAppReviewProvider.startInAppReviewIfFeasible(); void startInappRatingIfFeasible(this.storageProvider);
} }
} }

View File

@@ -19,7 +19,7 @@
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<div #schedule class="schedule"> <div #schedule class="schedule">
<a [routerLink]="['/schedule/weekly-view']"> <a [routerLink]="['/schedule/week-overview']">
<ion-icon [size]="36" [weight]="300" name="calendar_month"></ion-icon> <ion-icon [size]="36" [weight]="300" name="calendar_month"></ion-icon>
<ion-label [innerHTML]="'schedule.recurring' | translate"></ion-label> <ion-label [innerHTML]="'schedule.recurring' | translate"></ion-label>
</a> </a>

View File

@@ -127,7 +127,6 @@ export class AddEventActionChipComponent {
.filter(it => it.selected) .filter(it => it.selected)
.map(it => it.item), .map(it => it.item),
}, },
mode: 'md', // TODO Remove if Issue 239 is solved.
}); });
await modal.present(); await modal.present();

View File

@@ -36,7 +36,7 @@ export class ChipFilterComponent {
/** /**
* Emits when the chip has been activated/deactivated * Emits when the chip has been activated/deactivated
*/ */
@Output() toggled = new EventEmitter<unknown>(); @Output() toggle = new EventEmitter<unknown>();
/** /**
* Value to emit when chip has been activated/deactivated * Value to emit when chip has been activated/deactivated
@@ -47,6 +47,6 @@ export class ChipFilterComponent {
* Signalize that the chip filter has been activated/deactivated * Signalize that the chip filter has been activated/deactivated
*/ */
emitToggle(value: unknown) { emitToggle(value: unknown) {
this.toggled.emit(value); this.toggle.emit(value);
} }
} }

View File

@@ -19,6 +19,6 @@
[size]="24" [size]="24"
[fill]="(isFavorite$ | async) || false" [fill]="(isFavorite$ | async) || false"
[class.selected]="isFavorite$ | async" [class.selected]="isFavorite$ | async"
name="star" name="grade"
></ion-icon> ></ion-icon>
</ion-button> </ion-button>

View File

@@ -31,7 +31,7 @@
slot="icon-only" slot="icon-only"
[size]="32" [size]="32"
color="medium" color="medium"
name="star" name="grade"
></ion-icon> ></ion-icon>
} }
<label class="thank-you">{{ 'ratings.thank_you' | translate }}</label> <label class="thank-you">{{ 'ratings.thank_you' | translate }}</label>

View File

@@ -383,7 +383,6 @@ export class SearchPageComponent implements OnInit {
cssClass: 'context-menu-modal', cssClass: 'context-menu-modal',
showBackdrop: true, showBackdrop: true,
backdropDismiss: true, backdropDismiss: true,
mode: 'md', // TODO has to be fixed to md for now. ios mode is unresponsive. Remove if Issue 239 is solved
enterAnimation: (baseElement: HTMLElement) => enterAnimation(baseElement, this.animationController), enterAnimation: (baseElement: HTMLElement) => enterAnimation(baseElement, this.animationController),
leaveAnimation: (baseElement: HTMLElement) => leaveAnimation(baseElement, this.animationController), leaveAnimation: (baseElement: HTMLElement) => leaveAnimation(baseElement, this.animationController),
componentProps: { componentProps: {

View File

@@ -37,8 +37,7 @@
> >
</ion-searchbar> </ion-searchbar>
@if (showContextMenu) { @if (showContextMenu) {
<!-- TODO has to be fixed to md for now. ios mode displays broken/missing icon --> <ion-menu-button menu="context" auto-hide="false" slot="end" (click)="openContextMenu()">
<ion-menu-button mode="md" menu="context" auto-hide="false" slot="end" (click)="openContextMenu()">
<ion-icon name="tune"></ion-icon> <ion-icon name="tune"></ion-icon>
</ion-menu-button> </ion-menu-button>
} }

View File

@@ -25,7 +25,7 @@ import {FilterContext, SortContext} from './context-type';
import {provideIonicAngular, ModalController} from '@ionic/angular/standalone'; import {provideIonicAngular, ModalController} from '@ionic/angular/standalone';
import {BehaviorSubject, of} from 'rxjs'; import {BehaviorSubject, of} from 'rxjs';
import {addIcons} from 'ionicons'; import {addIcons} from 'ionicons';
import {swapVertical, trash, menu} from 'ionicons/icons'; import {swapVertical, trash} from 'ionicons/icons';
describe('ContextMenuModalComponent', () => { describe('ContextMenuModalComponent', () => {
let fixture: ComponentFixture<ContextMenuModalComponent>; let fixture: ComponentFixture<ContextMenuModalComponent>;
@@ -37,7 +37,6 @@ describe('ContextMenuModalComponent', () => {
addIcons({ addIcons({
delete: trash, delete: trash,
sort: swapVertical, sort: swapVertical,
menu: menu,
}); });
beforeEach(async () => { beforeEach(async () => {

View File

@@ -62,9 +62,7 @@ export class TabsComponent {
void this.loadMenuEntries(); void this.loadMenuEntries();
this.router.events.subscribe((event: unknown) => { this.router.events.subscribe((event: unknown) => {
if (event instanceof NavigationEnd) { if (event instanceof NavigationEnd) {
setTimeout(() => { this.selectTab(event.url);
this.selectTab(event.url);
}, 300);
} }
}); });
this.selectTab(router.url); this.selectTab(router.url);

View File

@@ -136,7 +136,7 @@ export class SchedulePageComponent implements OnInit, AfterViewInit {
onInit() { onInit() {
this.tabChoreographer = new SharedAxisChoreographer(this.activatedRoute.snapshot.paramMap.get('mode'), [ this.tabChoreographer = new SharedAxisChoreographer(this.activatedRoute.snapshot.paramMap.get('mode'), [
'calendar', 'calendar',
'weekly-view', 'week-overview',
'single', 'single',
]); ]);
} }

View File

@@ -21,7 +21,7 @@
@if (tabChoreographer.currentValue === 'calendar') { @if (tabChoreographer.currentValue === 'calendar') {
<ion-title [innerHTML]="'schedule.calendar' | translate | titlecase"></ion-title> <ion-title [innerHTML]="'schedule.calendar' | translate | titlecase"></ion-title>
} }
@if (tabChoreographer.currentValue === 'weekly-view') { @if (tabChoreographer.currentValue === 'week-overview') {
<ion-title [innerHTML]="'schedule.recurring' | translate | titlecase"></ion-title> <ion-title [innerHTML]="'schedule.recurring' | translate | titlecase"></ion-title>
} }
@if (tabChoreographer.currentValue === 'single') { @if (tabChoreographer.currentValue === 'single') {
@@ -39,7 +39,7 @@
<ion-label class="ion-text-wrap" [innerHTML]="'schedule.calendar' | translate"></ion-label> <ion-label class="ion-text-wrap" [innerHTML]="'schedule.calendar' | translate"></ion-label>
<ion-icon name="calendar_today"></ion-icon> <ion-icon name="calendar_today"></ion-icon>
</ion-segment-button> </ion-segment-button>
<ion-segment-button value="weekly-view" layout="icon-start"> <ion-segment-button value="week-overview" layout="icon-start">
<ion-label class="ion-text-wrap" [innerHTML]="'schedule.recurring' | translate"></ion-label> <ion-label class="ion-text-wrap" [innerHTML]="'schedule.recurring' | translate"></ion-label>
<ion-icon name="event_repeat"></ion-icon> <ion-icon name="event_repeat"></ion-icon>
</ion-segment-button> </ion-segment-button>
@@ -61,7 +61,7 @@
<stapps-calendar-view [layout]="layout"></stapps-calendar-view> <stapps-calendar-view [layout]="layout"></stapps-calendar-view>
} }
<!-- Schedule view needs full week --> <!-- Schedule view needs full week -->
@case ('weekly-view') { @case ('week-overview') {
<stapps-schedule-view [layout]="layout"></stapps-schedule-view> <stapps-schedule-view [layout]="layout"></stapps-schedule-view>
} }
@case ('single') { @case ('single') {

View File

@@ -66,7 +66,7 @@ import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive';
const settingsRoutes: Routes = [ const settingsRoutes: Routes = [
{path: 'schedule', redirectTo: 'schedule/calendar/now'}, {path: 'schedule', redirectTo: 'schedule/calendar/now'},
{path: 'schedule/calendar', redirectTo: 'schedule/calendar/now'}, {path: 'schedule/calendar', redirectTo: 'schedule/calendar/now'},
{path: 'schedule/weekly-view', redirectTo: 'schedule/weekly-view/now'}, {path: 'schedule/week-overview', redirectTo: 'schedule/week-overview/now'},
{path: 'schedule/single', redirectTo: 'schedule/single/now'}, {path: 'schedule/single', redirectTo: 'schedule/single/now'},
// calendar | recurring | single // calendar | recurring | single
{path: 'schedule/:mode/:date', component: SchedulePageComponent}, {path: 'schedule/:mode/:date', component: SchedulePageComponent},

View File

@@ -1,94 +0,0 @@
/*
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
/* eslint-disable unicorn/no-useless-undefined, @typescript-eslint/no-non-null-assertion */
import {TestBed} from '@angular/core/testing';
import {StorageProvider} from '../../storage/storage.provider';
import {
InAppReviewProvider,
IN_APP_REVIEW_COOLDOWN_DAYS,
IN_APP_REVIEW_NECESSARY_SESSIONS,
IN_APP_REVIEW_SETTINGS_KEY,
IN_APP_REVIEW_SESSIONS_KEY,
IN_APP_REVIEW_LAST_RATING_KEY,
} from './in-app-review.provider';
describe('InappRatingProvider', () => {
let storageProviderSpy: jasmine.SpyObj<StorageProvider>;
let inappRatingProvider: InAppReviewProvider;
const ONE_DAY_IN_MILLIS = 1000 * 3600 * 24;
beforeEach(async () => {
storageProviderSpy = jasmine.createSpyObj('StorageProvider', ['init', 'get', 'has', 'put']);
TestBed.configureTestingModule({
imports: [],
providers: [
InAppReviewProvider,
{
provide: StorageProvider,
useValue: storageProviderSpy,
},
],
});
// set settings returned from config
inappRatingProvider = TestBed.inject(InAppReviewProvider);
storageProviderSpy.has.and.returnValue(Promise.resolve(false));
});
it('should set user sessions count starting with one', async () => {
storageProviderSpy.get.and.returnValue(Promise.resolve(0));
const sessionCount = await inappRatingProvider.increaseSessionCount();
expect(sessionCount).toEqual(1);
});
it('should start in app rating/review flow if contitions are met', async () => {
const nowMinusCooldownDays = Date.now() - (IN_APP_REVIEW_COOLDOWN_DAYS + 1) * ONE_DAY_IN_MILLIS;
spyOn(inappRatingProvider, 'requestReview').and.returnValue(Promise.resolve());
storageProviderSpy.get
.withArgs(`${IN_APP_REVIEW_SETTINGS_KEY}.${IN_APP_REVIEW_SESSIONS_KEY}`)
.and.returnValue(Promise.resolve(IN_APP_REVIEW_NECESSARY_SESSIONS));
storageProviderSpy.get
.withArgs(`${IN_APP_REVIEW_SETTINGS_KEY}.${IN_APP_REVIEW_LAST_RATING_KEY}`)
.and.returnValue(Promise.resolve(nowMinusCooldownDays));
await inappRatingProvider.startInAppReviewIfFeasible();
expect(inappRatingProvider.requestReview).toHaveBeenCalledTimes(1);
});
it('should not start in app rating/review flow if contitions are not met', async () => {
const nowMinusCooldownDays = Date.now() - IN_APP_REVIEW_COOLDOWN_DAYS * ONE_DAY_IN_MILLIS;
spyOn(inappRatingProvider, 'requestReview').and.returnValue(Promise.resolve());
storageProviderSpy.get
.withArgs(`${IN_APP_REVIEW_SETTINGS_KEY}.${IN_APP_REVIEW_SESSIONS_KEY}`)
.and.returnValue(Promise.resolve(IN_APP_REVIEW_NECESSARY_SESSIONS - 1));
storageProviderSpy.get
.withArgs(`${IN_APP_REVIEW_SETTINGS_KEY}.${IN_APP_REVIEW_LAST_RATING_KEY}`)
.and.returnValue(Promise.resolve(nowMinusCooldownDays));
await inappRatingProvider.startInAppReviewIfFeasible();
storageProviderSpy.get
.withArgs(`${IN_APP_REVIEW_SETTINGS_KEY}.${IN_APP_REVIEW_SESSIONS_KEY}`)
.and.returnValue(Promise.resolve(IN_APP_REVIEW_NECESSARY_SESSIONS));
storageProviderSpy.get
.withArgs(`${IN_APP_REVIEW_SETTINGS_KEY}.${IN_APP_REVIEW_LAST_RATING_KEY}`)
.and.returnValue(Promise.resolve(nowMinusCooldownDays + ONE_DAY_IN_MILLIS));
await inappRatingProvider.startInAppReviewIfFeasible();
expect(inappRatingProvider.requestReview).toHaveBeenCalledTimes(0);
});
});

View File

@@ -1,120 +0,0 @@
import {Injectable} from '@angular/core';
import {InAppReview} from '@capacitor-community/in-app-review';
import {StorageProvider} from '../../storage/storage.provider';
export const IN_APP_REVIEW_COOLDOWN_DAYS = 365;
export const IN_APP_REVIEW_NECESSARY_SESSIONS = 3;
export const IN_APP_REVIEW_SETTINGS_KEY = 'inapp-rating';
export const IN_APP_REVIEW_SESSIONS_KEY = 'sessions';
export const IN_APP_REVIEW_LAST_RATING_KEY = 'last-rating';
export type IN_APP_REVIEW_KEYS = typeof IN_APP_REVIEW_SESSIONS_KEY | typeof IN_APP_REVIEW_LAST_RATING_KEY;
/**
* Provider for In-App Review
*/
@Injectable()
export class InAppReviewProvider {
requestReview: () => Promise<void>;
/**
* @param storageProvider TODO
*/
constructor(private readonly storageProvider: StorageProvider) {
this.requestReview = InAppReview.requestReview;
}
/**
*
*/
private inappRatingSettingStorageKey(key: string): string {
return `${IN_APP_REVIEW_SETTINGS_KEY}.${key}`;
}
/**
*
*/
private async getInAppReviewSetting<T>(
key: IN_APP_REVIEW_KEYS,
defaultValue: T,
): Promise<typeof defaultValue> {
try {
return await this.storageProvider.get<typeof defaultValue>(this.inappRatingSettingStorageKey(key));
} catch {
return defaultValue;
}
}
/**
*
*/
private async setInAppReviewSetting<T>(key: IN_APP_REVIEW_KEYS, value: T) {
return this.storageProvider.put<typeof value>(this.inappRatingSettingStorageKey(key), value);
}
/**
*
*/
private async setInAppReviewSessions(value: number) {
return this.setInAppReviewSetting(IN_APP_REVIEW_SESSIONS_KEY, value);
}
/**
*
*/
private async getInAppReviewSessions(): Promise<number> {
return this.getInAppReviewSetting(IN_APP_REVIEW_SESSIONS_KEY, 0);
}
/**
*
*/
private async setInAppReviewLastRating(value: Date) {
return this.setInAppReviewSetting(IN_APP_REVIEW_LAST_RATING_KEY, value.getTime());
}
/**
*
*/
private async getInAppReviewLastRating(): Promise<Date> {
return this.getInAppReviewSetting(IN_APP_REVIEW_LAST_RATING_KEY, 0).then(timestamp => {
return new Date(timestamp);
});
}
/**
* Increases session count to keep local info how often the app was used.
*/
public async increaseSessionCount(increment = 1): Promise<number> {
try {
const currentSessions = await this.getInAppReviewSessions();
await this.setInAppReviewSessions(currentSessions + increment);
return currentSessions + increment;
} catch {
return -1;
}
}
/**
* Invokes In App Review Flow/Views depending on the OS iff conditions are met.
*/
public async startInAppReviewIfFeasible(): Promise<boolean> {
try {
const currentSessions = await this.getInAppReviewSessions();
const lastRating = await this.getInAppReviewLastRating();
const dateDiffMillis = Math.abs(lastRating.getTime() - Date.now());
const dateDiffDays = Math.floor(dateDiffMillis / (1000 * 3600 * 24));
if (currentSessions < IN_APP_REVIEW_NECESSARY_SESSIONS || dateDiffDays < IN_APP_REVIEW_COOLDOWN_DAYS) {
return false;
}
await this.requestReview();
await this.setInAppReviewLastRating(new Date());
return true;
} catch {
return false;
}
}
}

View File

@@ -0,0 +1,106 @@
import {InAppReview} from '@capacitor-community/in-app-review';
import {StorageProvider} from '../../storage/storage.provider';
export const INAPP_RATING_COOLDOWN_DAYS = 365;
export const INAPP_RATING_NECESSARY_SESSIONS = 2;
export const INAPP_RATING_SETTINGS_KEY = 'inapp-rating';
export const INAPP_RATING_SESSIONS_KEY = 'sessions';
export const INAPP_RATING_LAST_RATING_KEY = 'last-rating';
export type INAPP_RATING_KEYS = typeof INAPP_RATING_SESSIONS_KEY | typeof INAPP_RATING_LAST_RATING_KEY;
/**
*
*/
function inappRatingSettingStorageKey(key: string): string {
return `${INAPP_RATING_SETTINGS_KEY}.${key}`;
}
/**
*
*/
async function getInappRatingSetting<T>(
storageProvider: StorageProvider,
key: INAPP_RATING_KEYS,
defaultValue: T,
): Promise<typeof defaultValue> {
try {
return await storageProvider.get<typeof defaultValue>(inappRatingSettingStorageKey(key));
} catch {
return defaultValue;
}
}
/**
*
*/
async function putInappRatingSetting<T>(storageProvider: StorageProvider, key: INAPP_RATING_KEYS, value: T) {
return storageProvider.put<typeof value>(inappRatingSettingStorageKey(key), value);
}
/**
*
*/
async function putInappRatingSessions(storageProvider: StorageProvider, value: number) {
return putInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, value);
}
/**
*
*/
async function getInappRatingSessions(storageProvider: StorageProvider): Promise<number> {
return getInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, 0);
}
/**
*
*/
async function putInappRatingLastRating(storageProvider: StorageProvider, value: Date) {
return putInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, value.getTime());
}
/**
*
*/
async function getInappRatingLastRating(storageProvider: StorageProvider): Promise<Date> {
return getInappRatingSetting(storageProvider, INAPP_RATING_SESSIONS_KEY, 0).then(timestamp => {
return new Date(timestamp);
});
}
/**
*
*/
export async function increaseSessionCount(storageProvider: StorageProvider, increment = 1): Promise<number> {
try {
const currentSessions = await getInappRatingSessions(storageProvider);
await putInappRatingSessions(storageProvider, currentSessions + increment);
return currentSessions + increment;
} catch {
return -1;
}
}
/**
*
*/
export async function startInappRatingIfFeasible(storageProvider: StorageProvider): Promise<boolean> {
try {
const currentSessions = await getInappRatingSessions(storageProvider);
const lastRating = await getInappRatingLastRating(storageProvider);
const dateDiffMillis = Math.abs(lastRating.getTime() - Date.now());
const diffDays = Math.ceil(dateDiffMillis / (1000 * 3600 * 24));
if (currentSessions < INAPP_RATING_NECESSARY_SESSIONS || diffDays < INAPP_RATING_COOLDOWN_DAYS) {
return false;
}
await InAppReview.requestReview();
await putInappRatingLastRating(storageProvider, new Date());
return true;
} catch {
return false;
}
}

View File

@@ -33,7 +33,7 @@
} }
<ion-card-content> <ion-card-content>
@if (!compactView) { @if (!compactView) {
<ion-note>{{ 'description' | thingTranslate: setting }}</ion-note> <ion-note>{{ 'description' | thingTranslate: setting | titlecase }}</ion-note>
} }
@if (isVisible) { @if (isVisible) {
<div> <div>

View File

@@ -55,7 +55,6 @@ import {
IonToolbar, IonToolbar,
} from '@ionic/angular/standalone'; } from '@ionic/angular/standalone';
import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive';
import {InAppReviewProvider} from './in-app-review/in-app-review.provider';
const settingsRoutes: Routes = [{path: 'settings', component: SettingsPageComponent}]; const settingsRoutes: Routes = [{path: 'settings', component: SettingsPageComponent}];
@@ -102,13 +101,6 @@ const settingsRoutes: Routes = [{path: 'settings', component: SettingsPageCompon
IonInput, IonInput,
IonNote, IonNote,
], ],
providers: [ providers: [ScheduleSyncService, SettingsProvider, CalendarService, ScheduleProvider, ThingTranslatePipe],
ScheduleSyncService,
SettingsProvider,
InAppReviewProvider,
CalendarService,
ScheduleProvider,
ThingTranslatePipe,
],
}) })
export class SettingsModule {} export class SettingsModule {}

View File

@@ -304,8 +304,8 @@ describe('SettingsProvider', () => {
}, },
en: { en: {
description: description:
'The user group the app is going to use primarily.' + 'The user group the app is going to be used.' +
' This settings for example is getting used for the predefined price category of mensa meals.', 'This settings for example is getting used for the predefined price category of mensa meals.',
name: 'Group', name: 'Group',
}, },
}, },

View File

@@ -106,6 +106,7 @@ describe('StorageProvider', () => {
}); });
it('should put multiple values into the storage', async () => { it('should put multiple values into the storage', async () => {
// @ts-expect-error no need to return anything for this case
spyOn(storageProvider, 'put').and.callFake(() => Promise.resolve()); spyOn(storageProvider, 'put').and.callFake(() => Promise.resolve());
await storageProvider.putMultiple(sampleEntries); await storageProvider.putMultiple(sampleEntries);

View File

@@ -150,7 +150,7 @@ const iconMap = new Map<string, MaterialSymbol>([
[menuSharp, SCIcon.menu], [menuSharp, SCIcon.menu],
[searchOutline, SCIcon.search], [searchOutline, SCIcon.search],
[searchSharp, SCIcon.search], [searchSharp, SCIcon.search],
[chevronExpand, SCIcon.expand_all], [chevronExpand, SCIcon.expand_more],
[caretDownSharp, SCIcon.expand_more], [caretDownSharp, SCIcon.expand_more],
[close, SCIcon.close], [close, SCIcon.close],
[closeSharp, SCIcon.close], [closeSharp, SCIcon.close],

File diff suppressed because one or more lines are too long

View File

@@ -500,7 +500,7 @@
"view": { "view": {
"today": "Heute" "today": "Heute"
}, },
"recurring": "Wochen&shy;ansicht", "recurring": "Wochen&shy;übersicht",
"calendar": "Kalender", "calendar": "Kalender",
"single": "Einzel&shy;termine", "single": "Einzel&shy;termine",
"addEventPage": { "addEventPage": {

View File

@@ -500,7 +500,7 @@
"view": { "view": {
"today": "Today" "today": "Today"
}, },
"recurring": "Weekly View", "recurring": "Week Overview",
"calendar": "Calendar", "calendar": "Calendar",
"single": "Single Events", "single": "Single Events",
"addEventPage": { "addEventPage": {

View File

@@ -62,7 +62,7 @@ export const profilePageSections: SCSection[] = [
links: [ links: [
{ {
name: 'Favorites', name: 'Favorites',
icon: SCIcon.star, icon: SCIcon.grade,
link: ['/favorites'], link: ['/favorites'],
translations: { translations: {
de: { de: {

View File

@@ -17,13 +17,14 @@ $icon-size: 22px;
app-root ion-searchbar[class*='sc-ion-searchbar-'] { app-root ion-searchbar[class*='sc-ion-searchbar-'] {
--border-radius: var(--border-radius-default); --border-radius: var(--border-radius-default);
--background: var(--ion-item-background) !important; --background: var(--ion-item-background) !important;
--box-shadow: none;
height: 38px; height: 38px;
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
&.filterable { &.filterable {
--box-shadow: none;
position: relative; position: relative;
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;

View File

@@ -1,11 +1,5 @@
# @openstapps/app-builder-image # @openstapps/app-builder-image
## 4.0.3
### Patch Changes
- 3a274a3a: Upgrade to Capacitor 7 and Anuglar 18
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@openstapps/app-builder-image", "name": "@openstapps/app-builder-image",
"version": "4.0.3", "version": "4.0.0",
"private": true, "private": true,
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",

View File

@@ -1,15 +1,5 @@
# @openstapps/api-cli # @openstapps/api-cli
## 4.0.2
### Patch Changes
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
- @openstapps/core@4.0.2
- @openstapps/core-tools@4.0.2
- @openstapps/api@4.0.2
## 4.0.1 ## 4.0.1
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/api-cli", "name": "@openstapps/api-cli",
"description": "CLI client for @openstapps/api", "description": "CLI client for @openstapps/api",
"version": "4.0.2", "version": "4.0.1",
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/api.git", "repository": "git@gitlab.com:openstapps/api.git",

View File

@@ -1,15 +1,5 @@
# @openstapps/api-plugin # @openstapps/api-plugin
## 4.0.2
### Patch Changes
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
- @openstapps/core@4.0.2
- @openstapps/core-tools@4.0.2
- @openstapps/api@4.0.2
## 4.0.1 ## 4.0.1
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/api-plugin", "name": "@openstapps/api-plugin",
"description": "Node.js library to interact with the StApps backend service", "description": "Node.js library to interact with the StApps backend service",
"version": "4.0.2", "version": "4.0.1",
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/api.git", "repository": "git@gitlab.com:openstapps/api.git",

View File

@@ -1,11 +1,5 @@
# @openstapps/api # @openstapps/api
## 4.0.2
### Patch Changes
- @openstapps/core@4.0.2
## 4.0.1 ## 4.0.1
### Patch Changes ### Patch Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/api", "name": "@openstapps/api",
"description": "Node.js library to interact with the StApps backend service", "description": "Node.js library to interact with the StApps backend service",
"version": "4.0.2", "version": "4.0.1",
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/api.git", "repository": "git@gitlab.com:openstapps/api.git",

View File

@@ -1,13 +1,5 @@
# @openstapps/core-tools # @openstapps/core-tools
## 4.0.2
### Patch Changes
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
- @openstapps/easy-ast@4.0.2
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/core-tools", "name": "@openstapps/core-tools",
"description": "Tools to convert and validate StAppsCore", "description": "Tools to convert and validate StAppsCore",
"version": "4.0.2", "version": "4.0.0",
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/core-tools.git", "repository": "git@gitlab.com:openstapps/core-tools.git",

View File

@@ -1,11 +1,5 @@
# @openstapps/core # @openstapps/core
## 4.0.2
### Patch Changes
- @openstapps/core-tools@4.0.2
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/core", "name": "@openstapps/core",
"description": "StAppsCore - Generalized model of data", "description": "StAppsCore - Generalized model of data",
"version": "4.0.2", "version": "4.0.0",
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/core.git", "repository": "git@gitlab.com:openstapps/core.git",

View File

@@ -1,12 +1,5 @@
# @openstapps/easy-ast # @openstapps/easy-ast
## 4.0.2
### Patch Changes
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/easy-ast", "name": "@openstapps/easy-ast",
"description": "Tool to easily handle TypeScript AST", "description": "Tool to easily handle TypeScript AST",
"version": "4.0.2", "version": "4.0.0",
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/core-tools.git", "repository": "git@gitlab.com:openstapps/core-tools.git",

View File

@@ -1,6 +1,5 @@
{ {
"extension": ["ts"], "extension": ["ts"],
"node-option": ["no-experimental-strip-types"],
"require": "ts-node/register", "require": "ts-node/register",
"reporter": "mocha-junit-reporter", "reporter": "mocha-junit-reporter",
"reporter-option": ["mochaFile=coverage/report-junit.xml"], "reporter-option": ["mochaFile=coverage/report-junit.xml"],

View File

@@ -18,6 +18,7 @@
"noUnusedParameters": true, "noUnusedParameters": true,
"outDir": "./lib/", "outDir": "./lib/",
"strict": true, "strict": true,
"skipLibCheck": true,
"target": "ES2020" "target": "ES2020"
}, },
"exclude": ["./lib/", "./test/"] "exclude": ["./lib/", "./test/"]

View File

@@ -1,12 +1,5 @@
# @openstapps/gitlab-api # @openstapps/gitlab-api
## 4.0.2
### Patch Changes
- Updated dependencies [6b06de40]
- @openstapps/logger@4.0.2
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/gitlab-api", "name": "@openstapps/gitlab-api",
"description": "Wraps common GitLab API calls in a TypeScript class.", "description": "Wraps common GitLab API calls in a TypeScript class.",
"version": "4.0.2", "version": "4.0.0",
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/gitlab-api.git", "repository": "git@gitlab.com:openstapps/gitlab-api.git",

View File

@@ -1,11 +1,5 @@
# @openstapps/logger # @openstapps/logger
## 4.0.2
### Patch Changes
- 6b06de40: Updated nodemailer dependency
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,7 +1,7 @@
{ {
"name": "@openstapps/logger", "name": "@openstapps/logger",
"description": "A cli logger with colors, log-levels and the possibility to use a transport system for errors", "description": "A cli logger with colors, log-levels and the possibility to use a transport system for errors",
"version": "4.0.2", "version": "4.0.0",
"type": "module", "type": "module",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/logger.git", "repository": "git@gitlab.com:openstapps/logger.git",

3598
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,17 +6,19 @@ packages:
- packages/* - packages/*
- images/* - images/*
forceLegacyDeploy: true
onlyBuiltDependencies: onlyBuiltDependencies:
- '@compodoc/compodoc' - '@compodoc/compodoc'
- cpu-features - cpu-features
- cypress - cypress
- esbuild - esbuild
- lmdb
- msgpackr-extract
- nice-napi - nice-napi
- re2 - re2
- sharp - sharp
- ssh2 - ssh2
- swiper - swiper
# PNPM 8 defaults:
forceLegacyDeploy: True
# linkWorkspacePackages: true
# hoistWorkspacePackages: false
# dedupePeerDependents: false