From 982c0cc57c97a1a238c318d8e506950b578f7bfd Mon Sep 17 00:00:00 2001 From: Rainer Killinger Date: Thu, 17 Sep 2026 14:32:59 +0200 Subject: [PATCH] refactor: apply Angular 20 inject rules --- .../src/app/_helpers/data/sample-things.ts | 6 ++- .../_helpers/service-handler.interceptor.ts | 4 +- frontend/app/src/app/app.component.ts | 32 +++++++----- frontend/app/src/app/app.module.ts | 4 +- .../modules/about/about-licenses.component.ts | 6 +-- .../about/about-page/about-page.component.ts | 11 ++-- .../app/modules/about/app-version.service.ts | 12 ++--- .../modules/about/release-notes.component.ts | 6 +-- .../assessments/assessments.provider.ts | 14 +++--- .../detail/assessments-detail.component.ts | 18 ++++--- .../assessments-simple-data-list.component.ts | 12 ++--- .../page/assessments-page.component.ts | 21 ++++---- .../page/auth-callback-page.component.ts | 17 ++++--- .../app/modules/auth/auth-guard.service.ts | 9 ++-- .../app/modules/auth/auth-helper.service.ts | 23 +++++---- .../app/modules/auth/default-auth.service.ts | 25 +++++++--- .../modules/auth/factories/http.factory.ts | 5 +- .../src/app/modules/auth/ng-http.service.ts | 4 +- .../schedule/schedule-sync.service.ts | 21 ++++---- .../add-event-review-modal.component.ts | 14 +++--- .../app/modules/calendar/calendar.service.ts | 11 ++-- .../app/modules/calendar/schedule.provider.ts | 4 +- .../app/modules/catalog/catalog.component.ts | 23 +++++---- .../app/modules/catalog/catalog.provider.ts | 4 +- .../src/app/modules/config/config.provider.ts | 20 ++++---- .../modules/dashboard/dashboard.component.ts | 24 +++++---- .../modules/dashboard/dashboard.provider.ts | 6 ++- .../favorites-section.component.ts | 6 +-- .../mensa-section-content.component.ts | 6 +-- .../mensa-section/mensa-section.component.ts | 6 +-- .../news-section/news-section.component.ts | 6 +-- .../search-section.component.ts | 6 +-- .../data/add-event-action-chip.component.ts | 15 +++--- .../chips/edit-event-selection.component.ts | 17 ++++--- .../data/coordinated-search.provider.ts | 4 +- .../app/src/app/modules/data/data.provider.ts | 12 ++--- .../data/debug-data-collector.service.ts | 19 ++++--- .../detail/data-detail-content.component.ts | 6 +-- .../data/detail/data-detail.component.ts | 31 ++++++++---- .../data/detail/data-path.component.ts | 15 +++--- .../data/elements/external-link.component.ts | 5 +- .../elements/favorite-button.component.ts | 6 +-- .../data/elements/offers-in-list.component.ts | 6 +-- .../modules/data/elements/rating.component.ts | 11 ++-- .../data/elements/share-button.component.ts | 6 +-- .../list/data-list-item-host.directive.ts | 6 +-- .../data/list/data-list-item.component.ts | 6 +-- .../data/list/food-data-list.component.ts | 7 ++- .../data/list/search-page.component.ts | 50 +++++++++---------- .../data/list/simple-data-list.component.ts | 9 ++-- .../src/app/modules/data/rating.provider.ts | 14 +++--- .../data/stapps-web-http-client.provider.ts | 12 ++--- .../catalog-detail-content.component.ts | 6 +-- .../date-series-detail-content.component.ts | 13 ++--- .../message-detail-content.component.ts | 4 +- .../person/person-detail-content.component.ts | 6 +-- .../place/place-detail-content.component.ts | 7 ++- .../types/place/place-list-item.component.ts | 6 +-- .../mensa/place-mensa-detail.component.ts | 15 +++--- .../special/mensa/place-mensa-service.ts | 9 ++-- .../favorites/favorites-page.component.ts | 43 ++-------------- .../modules/favorites/favorites.service.ts | 16 +++--- .../feedback/feedback-page.component.ts | 20 ++++---- .../app/modules/map/cluster-leaves.pipe.ts | 6 +-- .../map/controls/compass-control.component.ts | 8 +-- .../controls/geolocate-control.component.ts | 5 +- .../elements/building-markers.component.ts | 14 +++--- .../map/elements/poi-marker.component.ts | 11 ++-- .../modules/map/geo-navigation.directive.ts | 20 ++++---- .../src/app/modules/map/map-page.component.ts | 11 ++-- .../app/modules/map/map-size-fix.directive.ts | 11 ++-- .../context/context-menu-modal.component.ts | 11 ++-- .../menu/context/context-menu.service.ts | 11 ++-- .../menu/navigation/navigation.component.ts | 19 ++++--- .../menu/navigation/navigation.service.ts | 9 ++-- .../navigation/offline-notice.component.ts | 14 +++--- .../menu/navigation/root-link.directive.ts | 18 ++++--- .../modules/menu/navigation/tabs.component.ts | 20 +++++--- .../app/src/app/modules/news/news.provider.ts | 9 ++-- .../modules/news/page/news-page.component.ts | 6 +-- .../app/modules/profile/id-card.component.ts | 14 +++--- .../app/modules/profile/id-cards.component.ts | 6 +-- .../app/modules/profile/id-cards.provider.ts | 15 +++--- .../src/app/modules/profile/id-cards.spec.ts | 6 +-- .../profile/page/my-courses.component.ts | 6 +-- .../profile/page/profile-page.component.ts | 14 +++--- .../schedule/page/calendar-view.component.ts | 11 +--- .../page/components/calendar.component.ts | 12 ++--- .../page/grid/schedule-card.component.ts | 6 +-- .../page/grid/schedule-day.component.ts | 6 +-- .../schedule/page/schedule-page.component.ts | 23 +++++---- .../page/schedule-single-events.component.ts | 4 +- .../schedule/page/schedule-view.component.ts | 11 +--- .../in-app-review/in-app-review.provider.ts | 8 +-- .../settings/item/settings-item.component.ts | 19 +++---- .../page/calendar-sync-settings.component.ts | 26 ++++++---- .../settings/page/settings-page.component.ts | 25 +++++----- .../settings/setting-translate.pipe.ts | 11 ++-- .../app/modules/settings/settings.provider.ts | 16 +++--- .../storage/encrypted-storage.provider.ts | 4 +- .../app/modules/storage/storage.provider.ts | 7 +-- .../app/translation/common-string-pipes.ts | 26 ++++++++-- .../property-name-translate.pipe.ts | 11 ++-- .../app/translation/thing-translate.pipe.ts | 12 ++--- .../translation/thing-translate.service.ts | 29 +++++++---- .../app/translation/translate-simple.pipe.ts | 4 +- .../app/src/app/util/edit-modal.component.ts | 32 ++++++++---- .../app/util/element-size-change.directive.ts | 6 +-- .../app/util/full-screen-image.directive.ts | 6 ++- .../app/util/internet-connection.service.ts | 11 ++-- .../util/ion-content-parallax.directive.ts | 6 +-- .../app/util/ion-icon/ion-icon.directive.ts | 6 +-- frontend/app/src/app/util/lazy.pipe.ts | 4 +- .../app/src/app/util/routing-stack.service.ts | 6 ++- .../app/util/searchbar-autofocus.directive.ts | 6 +-- .../app/src/app/util/section.component.ts | 13 +++-- 116 files changed, 754 insertions(+), 665 deletions(-) diff --git a/frontend/app/src/app/_helpers/data/sample-things.ts b/frontend/app/src/app/_helpers/data/sample-things.ts index d14e6711..ac08f97c 100644 --- a/frontend/app/src/app/_helpers/data/sample-things.ts +++ b/frontend/app/src/app/_helpers/data/sample-things.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {HttpClient} from '@angular/common/http'; -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import { SCAcademicEvent, SCArticle, @@ -395,7 +395,9 @@ export class SampleThings { */ http: HttpClient; - constructor(http: HttpClient) { + constructor() { + const http = inject(HttpClient); + this.http = http; } diff --git a/frontend/app/src/app/_helpers/service-handler.interceptor.ts b/frontend/app/src/app/_helpers/service-handler.interceptor.ts index c7a71b9d..c49733c4 100644 --- a/frontend/app/src/app/_helpers/service-handler.interceptor.ts +++ b/frontend/app/src/app/_helpers/service-handler.interceptor.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse} from '@angular/common/http'; import {Observable, throwError} from 'rxjs'; import {NGXLogger} from 'ngx-logger'; @@ -21,7 +21,7 @@ import {catchError} from 'rxjs/operators'; @Injectable() export class ServiceHandlerInterceptor implements HttpInterceptor { - constructor(private readonly logger: NGXLogger) {} + private readonly logger = inject(NGXLogger); intercept(request: HttpRequest, next: HttpHandler): Observable> { return next.handle(request).pipe( diff --git a/frontend/app/src/app/app.component.ts b/frontend/app/src/app/app.component.ts index b3c5c586..a5ecf0bb 100644 --- a/frontend/app/src/app/app.component.ts +++ b/frontend/app/src/app/app.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {AfterContentInit, Component, NgZone} from '@angular/core'; +import {AfterContentInit, Component, NgZone, inject} from '@angular/core'; import {Router} from '@angular/router'; import {App, URLOpenListenerEvent} from '@capacitor/app'; import {Platform, ToastController} from '@ionic/angular/standalone'; @@ -35,6 +35,24 @@ import {SplashScreen} from '@capacitor/splash-screen'; standalone: false, }) export class AppComponent implements AfterContentInit { + private readonly platform = inject(Platform); + + private readonly settingsProvider = inject(SettingsProvider); + + private readonly inAppReviewProvider = inject(InAppReviewProvider); + + private readonly router = inject(Router); + + private readonly zone = inject(NgZone); + + private readonly authHelper = inject(AuthHelperService); + + private readonly toastController = inject(ToastController); + + private readonly scheduleSyncService = inject(ScheduleSyncService); + + private readonly versionService = inject(AppVersionService); + /** * TODO */ @@ -54,17 +72,7 @@ export class AppComponent implements AfterContentInit { */ ommitedEventSources = ['ion-input', 'ion-searchbar']; - constructor( - private readonly platform: Platform, - private readonly settingsProvider: SettingsProvider, - private readonly inAppReviewProvider: InAppReviewProvider, - private readonly router: Router, - private readonly zone: NgZone, - private readonly authHelper: AuthHelperService, - private readonly toastController: ToastController, - private readonly scheduleSyncService: ScheduleSyncService, - private readonly versionService: AppVersionService, - ) { + constructor() { void this.initializeApp(); } diff --git a/frontend/app/src/app/app.module.ts b/frontend/app/src/app/app.module.ts index 2f738883..894e72f4 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, provideHttpClient, withInterceptorsFromDi} from '@angular/common/http'; import localeDe from '@angular/common/locales/de'; -import {APP_INITIALIZER, NgModule} from '@angular/core'; +import {APP_INITIALIZER, NgModule, inject} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {RouteReuseStrategy} from '@angular/router'; import {IonicRouteStrategy, Platform, provideIonicAngular, IonApp} from '@ionic/angular/standalone'; @@ -216,5 +216,5 @@ export function createTranslateLoader(http: HttpClient) { ], }) export class AppModule { - constructor(public debugDataCollectorService: DebugDataCollectorService) {} + debugDataCollectorService = inject(DebugDataCollectorService); } diff --git a/frontend/app/src/app/modules/about/about-licenses.component.ts b/frontend/app/src/app/modules/about/about-licenses.component.ts index 6557de3a..fe56c7ea 100644 --- a/frontend/app/src/app/modules/about/about-licenses.component.ts +++ b/frontend/app/src/app/modules/about/about-licenses.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, inject} from '@angular/core'; import {ModalController} from '@ionic/angular/standalone'; import {AboutLicenseModalComponent} from './about-license-modal.component'; import licensesFile from 'src/assets/about/licenses.json'; @@ -35,9 +35,9 @@ export interface License { standalone: false, }) export class AboutLicensesComponent implements OnInit { - licenses: License[]; + private modalController = inject(ModalController); - constructor(private modalController: ModalController) {} + licenses: License[]; ngOnInit() { this.licenses = this.loadLicenses(); diff --git a/frontend/app/src/app/modules/about/about-page/about-page.component.ts b/frontend/app/src/app/modules/about/about-page/about-page.component.ts index 54aaa5a3..d4869014 100644 --- a/frontend/app/src/app/modules/about/about-page/about-page.component.ts +++ b/frontend/app/src/app/modules/about/about-page/about-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, inject} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {SCAboutPage, SCAppConfiguration} from '@openstapps/core'; import {ConfigProvider} from '../../config/config.provider'; @@ -28,6 +28,10 @@ import {Capacitor} from '@capacitor/core'; standalone: false, }) export class AboutPageComponent implements OnInit { + private readonly route = inject(ActivatedRoute); + + private readonly configProvider = inject(ConfigProvider); + content: SCAboutPage; name = config.appName; @@ -36,11 +40,6 @@ export class AboutPageComponent implements OnInit { version: string; - constructor( - private readonly route: ActivatedRoute, - private readonly configProvider: ConfigProvider, - ) {} - async ngOnInit() { const route = this.route.snapshot.url.map(it => it.path).join('/'); this.content = diff --git a/frontend/app/src/app/modules/about/app-version.service.ts b/frontend/app/src/app/modules/about/app-version.service.ts index 2a53c721..87104b52 100644 --- a/frontend/app/src/app/modules/about/app-version.service.ts +++ b/frontend/app/src/app/modules/about/app-version.service.ts @@ -1,4 +1,4 @@ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {StorageProvider} from '../storage/storage.provider'; import {ConfigProvider} from '../config/config.provider'; import {ModalController} from '@ionic/angular/standalone'; @@ -12,11 +12,11 @@ export const RELEASE_NOTES_SHOWN_KEY = 'release_notes_shown'; @Injectable({providedIn: 'root'}) export class AppVersionService { - constructor( - private storage: StorageProvider, - private config: ConfigProvider, - private modalController: ModalController, - ) {} + private storage = inject(StorageProvider); + + private config = inject(ConfigProvider); + + private modalController = inject(ModalController); /** * Get the latest release notes that have not been presented yet diff --git a/frontend/app/src/app/modules/about/release-notes.component.ts b/frontend/app/src/app/modules/about/release-notes.component.ts index 1bd6338a..115854d2 100644 --- a/frontend/app/src/app/modules/about/release-notes.component.ts +++ b/frontend/app/src/app/modules/about/release-notes.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, inject} from '@angular/core'; import {SCAppVersionInfo} from '@openstapps/core'; import {MarkdownModule} from 'ngx-markdown'; import {ThingTranslateModule} from '../../translation/thing-translate.module'; @@ -31,7 +31,7 @@ import {UtilModule} from '../../util/util.module'; ], }) export class ReleaseNotesComponent { - @Input() versionInfos: SCAppVersionInfo[]; + readonly modalController = inject(ModalController); - constructor(readonly modalController: ModalController) {} + @Input() versionInfos: SCAppVersionInfo[]; } diff --git a/frontend/app/src/app/modules/assessments/assessments.provider.ts b/frontend/app/src/app/modules/assessments/assessments.provider.ts index b0f94abf..6c419e75 100644 --- a/frontend/app/src/app/modules/assessments/assessments.provider.ts +++ b/frontend/app/src/app/modules/assessments/assessments.provider.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {ConfigProvider} from '../config/config.provider'; import {SCAssessment, SCUuid} from '@openstapps/core'; import {DefaultAuthService} from '../auth/default-auth.service'; @@ -51,6 +51,12 @@ export function toAssessmentMap(data: SCAssessment[]): Record { await this.getAssessments(accessToken, forceFetch); diff --git a/frontend/app/src/app/modules/assessments/detail/assessments-detail.component.ts b/frontend/app/src/app/modules/assessments/detail/assessments-detail.component.ts index 474afdd1..f47ac9db 100644 --- a/frontend/app/src/app/modules/assessments/detail/assessments-detail.component.ts +++ b/frontend/app/src/app/modules/assessments/detail/assessments-detail.component.ts @@ -29,15 +29,17 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class AssessmentsDetailComponent implements OnInit { - destroy$ = inject(DestroyRef); + readonly route = inject(ActivatedRoute); - constructor( - readonly route: ActivatedRoute, - readonly assessmentsProvider: AssessmentsProvider, - readonly dataRoutingService: DataRoutingService, - readonly navController: NavController, - readonly activatedRoute: ActivatedRoute, - ) {} + readonly assessmentsProvider = inject(AssessmentsProvider); + + readonly dataRoutingService = inject(DataRoutingService); + + readonly navController = inject(NavController); + + readonly activatedRoute = inject(ActivatedRoute); + + destroy$ = inject(DestroyRef); @Input() dataPathAutoRouting = true; diff --git a/frontend/app/src/app/modules/assessments/list/assessments-simple-data-list.component.ts b/frontend/app/src/app/modules/assessments/list/assessments-simple-data-list.component.ts index d2660b2d..d1db20c2 100644 --- a/frontend/app/src/app/modules/assessments/list/assessments-simple-data-list.component.ts +++ b/frontend/app/src/app/modules/assessments/list/assessments-simple-data-list.component.ts @@ -26,6 +26,12 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class AssessmentsSimpleDataListComponent implements OnInit { + readonly dataRoutingService = inject(DataRoutingService); + + readonly router = inject(Router); + + readonly activatedRoute = inject(ActivatedRoute); + /** * All SCThings to display */ @@ -47,12 +53,6 @@ export class AssessmentsSimpleDataListComponent implements OnInit { destroy$ = inject(DestroyRef); - constructor( - readonly dataRoutingService: DataRoutingService, - readonly router: Router, - readonly activatedRoute: ActivatedRoute, - ) {} - ngOnInit() { this.dataRoutingService .itemSelectListener() diff --git a/frontend/app/src/app/modules/assessments/page/assessments-page.component.ts b/frontend/app/src/app/modules/assessments/page/assessments-page.component.ts index d642cc50..62774ff2 100644 --- a/frontend/app/src/app/modules/assessments/page/assessments-page.component.ts +++ b/frontend/app/src/app/modules/assessments/page/assessments-page.component.ts @@ -32,6 +32,18 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class AssessmentsPageComponent implements OnInit, AfterViewInit { + readonly logger = inject(NGXLogger); + + readonly assessmentsProvider = inject(AssessmentsProvider); + + readonly dataProvider = inject(DataProvider); + + readonly activatedRoute = inject(ActivatedRoute); + + readonly dataRoutingService = inject(DataRoutingService); + + readonly router = inject(Router); + assessments: Promise< Record< string, @@ -50,15 +62,6 @@ export class AssessmentsPageComponent implements OnInit, AfterViewInit { destroy$ = inject(DestroyRef); - constructor( - readonly logger: NGXLogger, - readonly assessmentsProvider: AssessmentsProvider, - readonly dataProvider: DataProvider, - readonly activatedRoute: ActivatedRoute, - readonly dataRoutingService: DataRoutingService, - readonly router: Router, - ) {} - ngAfterViewInit() { this.segmentView.value = this.sharedAxisChoreographer.currentValue; } diff --git a/frontend/app/src/app/modules/auth/auth-callback/page/auth-callback-page.component.ts b/frontend/app/src/app/modules/auth/auth-callback/page/auth-callback-page.component.ts index 3d428586..d3a76cd7 100644 --- a/frontend/app/src/app/modules/auth/auth-callback/page/auth-callback-page.component.ts +++ b/frontend/app/src/app/modules/auth/auth-callback/page/auth-callback-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {NavController} from '@ionic/angular/standalone'; import {Router} from '@angular/router'; import {AuthActions, IAuthAction} from 'ionic-appauth'; @@ -27,12 +27,15 @@ import {DefaultAuthService} from '../../default-auth.service'; standalone: false, }) export class AuthCallbackPageComponent { - constructor( - private navCtrl: NavController, - private router: Router, - private authHelper: AuthHelperService, - private auth: DefaultAuthService, - ) { + private navCtrl = inject(NavController); + + private router = inject(Router); + + private authHelper = inject(AuthHelperService); + + private auth = inject(DefaultAuthService); + + constructor() { const events: Observable = this.auth.events$; events.pipe(takeUntilDestroyed()).subscribe((action: IAuthAction) => this.postCallback(action)); diff --git a/frontend/app/src/app/modules/auth/auth-guard.service.ts b/frontend/app/src/app/modules/auth/auth-guard.service.ts index 6d82af12..a700f532 100644 --- a/frontend/app/src/app/modules/auth/auth-guard.service.ts +++ b/frontend/app/src/app/modules/auth/auth-guard.service.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {CanActivate, NavigationExtras, Router, RouterStateSnapshot} from '@angular/router'; import {ActivatedProtectedRouteSnapshot} from './protected.routes'; import {AuthHelperService} from './auth-helper.service'; @@ -22,10 +22,9 @@ import {AuthHelperService} from './auth-helper.service'; providedIn: 'root', }) export class AuthGuardService implements CanActivate { - constructor( - private authHelper: AuthHelperService, - private router: Router, - ) {} + private authHelper = inject(AuthHelperService); + + private router = inject(Router); public async canActivate(route: ActivatedProtectedRouteSnapshot, _state: RouterStateSnapshot) { if (route.queryParamMap.get('token')) { diff --git a/frontend/app/src/app/modules/auth/auth-helper.service.ts b/frontend/app/src/app/modules/auth/auth-helper.service.ts index 97099880..86dfdce6 100644 --- a/frontend/app/src/app/modules/auth/auth-helper.service.ts +++ b/frontend/app/src/app/modules/auth/auth-helper.service.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {AuthActions, IAuthAction} from 'ionic-appauth'; import {TranslateService} from '@ngx-translate/core'; import {JSONPath} from 'jsonpath-plus'; @@ -35,16 +35,21 @@ const AUTH_ORIGIN_PATH = 'stapps.auth.origin_path'; providedIn: 'root', }) export class AuthHelperService { + private translateService = inject(TranslateService); + + private configProvider = inject(ConfigProvider); + + private storageProvider = inject(StorageProvider); + + private defaultAuth = inject(DefaultAuthService); + + private browser = inject(SimpleBrowser); + + private alertController = inject(AlertController); + userConfigurationMap: SCUserConfigurationMap; - constructor( - private translateService: TranslateService, - private configProvider: ConfigProvider, - private storageProvider: StorageProvider, - private defaultAuth: DefaultAuthService, - private browser: SimpleBrowser, - private alertController: AlertController, - ) { + constructor() { this.userConfigurationMap = ( this.configProvider.getAnyValue('auth') as { diff --git a/frontend/app/src/app/modules/auth/default-auth.service.ts b/frontend/app/src/app/modules/auth/default-auth.service.ts index 701365a2..e9659d9e 100644 --- a/frontend/app/src/app/modules/auth/default-auth.service.ts +++ b/frontend/app/src/app/modules/auth/default-auth.service.ts @@ -26,7 +26,7 @@ import {AuthActionBuilder, Browser, DefaultBrowser, EndSessionHandler, UserInfoH import {ConfigProvider} from '../config/config.provider'; import {SCAuthorizationProvider} from '@openstapps/core'; import {getClientConfig, getEndpointsConfig} from './auth.provider.methods'; -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {AuthService} from './auth.service'; const TOKEN_RESPONSE_KEY = 'token_response'; @@ -35,6 +35,14 @@ const TOKEN_RESPONSE_KEY = 'token_response'; providedIn: 'root', }) export class DefaultAuthService extends AuthService { + protected browser: Browser; + + protected storage: StorageBackend; + + protected requestor: Requestor; + + private readonly configProvider = inject(ConfigProvider); + public localConfiguration: AuthorizationServiceConfiguration; protected tokenHandler: TokenRequestHandler; @@ -45,13 +53,16 @@ export class DefaultAuthService extends AuthService { protected endSessionHandler: EndSessionHandler; - constructor( - protected browser: Browser = new DefaultBrowser(), - protected storage: StorageBackend = new LocalStorageBackend(), - protected requestor: Requestor = new JQueryRequestor(), - private readonly configProvider: ConfigProvider, - ) { + constructor() { + const browser = inject(Browser) ?? new DefaultBrowser(); + const storage = inject(StorageBackend) ?? new LocalStorageBackend(); + const requestor = inject(Requestor) ?? new JQueryRequestor(); + super(browser, storage, requestor); + + this.browser = browser; + this.storage = storage; + this.requestor = requestor; } get configuration(): Promise { diff --git a/frontend/app/src/app/modules/auth/factories/http.factory.ts b/frontend/app/src/app/modules/auth/factories/http.factory.ts index ec137d73..0a7e28b3 100644 --- a/frontend/app/src/app/modules/auth/factories/http.factory.ts +++ b/frontend/app/src/app/modules/auth/factories/http.factory.ts @@ -13,11 +13,10 @@ * this program. If not, see . */ -import {HttpClient} from '@angular/common/http'; import {Platform} from '@ionic/angular/standalone'; import {CapacitorRequestor} from '../capacitor-requestor'; import {NgHttpService} from '../ng-http.service'; -export const httpFactory = (platform: Platform, httpClient: HttpClient) => { - return platform.is('capacitor') ? new CapacitorRequestor() : new NgHttpService(httpClient); +export const httpFactory = (platform: Platform) => { + return platform.is('capacitor') ? new CapacitorRequestor() : new NgHttpService(); }; diff --git a/frontend/app/src/app/modules/auth/ng-http.service.ts b/frontend/app/src/app/modules/auth/ng-http.service.ts index 2cdb3617..bbb13a4f 100644 --- a/frontend/app/src/app/modules/auth/ng-http.service.ts +++ b/frontend/app/src/app/modules/auth/ng-http.service.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {Requestor} from '@openid/appauth'; import {HttpClient, HttpHeaders} from '@angular/common/http'; import {XhrSettings} from 'ionic-appauth/lib/cordova'; @@ -23,7 +23,7 @@ import {firstValueFrom, Observable} from 'rxjs'; providedIn: 'root', }) export class NgHttpService implements Requestor { - constructor(private http: HttpClient) {} + private http = inject(HttpClient); public async xhr(settings: XhrSettings): Promise { if (!settings.method) { diff --git a/frontend/app/src/app/modules/background/schedule/schedule-sync.service.ts b/frontend/app/src/app/modules/background/schedule/schedule-sync.service.ts index e912a7ed..3df4e5db 100644 --- a/frontend/app/src/app/modules/background/schedule/schedule-sync.service.ts +++ b/frontend/app/src/app/modules/background/schedule/schedule-sync.service.ts @@ -40,16 +40,19 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; @Injectable() export class ScheduleSyncService { - destroy$ = inject(DestroyRef); + private scheduleProvider = inject(ScheduleProvider); - constructor( - private scheduleProvider: ScheduleProvider, - private storageProvider: StorageProvider, - private translator: ThingTranslateService, - private dateFormatPipe: DateFormatPipe, - private durationFormatPipe: DurationPipe, - private calendar: CalendarService, - ) {} + private storageProvider = inject(StorageProvider); + + private translator = inject(ThingTranslateService); + + private dateFormatPipe = inject(DateFormatPipe); + + private durationFormatPipe = inject(DurationPipe); + + private calendar = inject(CalendarService); + + destroy$ = inject(DestroyRef); init() { this.scheduleProvider.uuids$ diff --git a/frontend/app/src/app/modules/calendar/add-event-review-modal.component.ts b/frontend/app/src/app/modules/calendar/add-event-review-modal.component.ts index 8838a51e..85b7a063 100644 --- a/frontend/app/src/app/modules/calendar/add-event-review-modal.component.ts +++ b/frontend/app/src/app/modules/calendar/add-event-review-modal.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input, OnInit, inject} from '@angular/core'; import { getICalExport, getNativeCalendarExport, @@ -45,6 +45,12 @@ interface ICalInfo { standalone: false, }) export class AddEventReviewModalComponent implements OnInit { + readonly calendarService = inject(CalendarService); + + readonly translator = inject(ThingTranslateService); + + readonly translateService = inject(TranslateService); + moment = moment; @Input() dismissAction: () => void; @@ -57,12 +63,6 @@ export class AddEventReviewModalComponent implements OnInit { isWeb = true; - constructor( - readonly calendarService: CalendarService, - readonly translator: ThingTranslateService, - readonly translateService: TranslateService, - ) {} - ngOnInit() { Device.getInfo().then(it => { this.isWeb = it.platform === 'web'; diff --git a/frontend/app/src/app/modules/calendar/calendar.service.ts b/frontend/app/src/app/modules/calendar/calendar.service.ts index ddcd31c5..1f21b02d 100644 --- a/frontend/app/src/app/modules/calendar/calendar.service.ts +++ b/frontend/app/src/app/modules/calendar/calendar.service.ts @@ -14,7 +14,7 @@ */ import {Calendar} from '@awesome-cordova-plugins/calendar/ngx'; -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {ICalEvent} from './ical/ical'; import moment, {duration, Moment, unitOfTime} from 'moment'; import {Dialog} from '@capacitor/dialog'; @@ -31,6 +31,10 @@ const RECURRENCE_PATTERNS: Partial> @Injectable() export class CalendarService { + readonly calendar = inject(Calendar); + + private readonly configProvider = inject(ConfigProvider); + goToDate = new Subject(); goToDateClicked = this.goToDate.asObservable(); @@ -38,10 +42,7 @@ export class CalendarService { calendarName = 'StApps'; // eslint-disable-next-line @typescript-eslint/no-empty-function - constructor( - readonly calendar: Calendar, - private readonly configProvider: ConfigProvider, - ) { + constructor() { this.calendarName = (this.configProvider.getValue('name') as string) ?? 'StApps'; } diff --git a/frontend/app/src/app/modules/calendar/schedule.provider.ts b/frontend/app/src/app/modules/calendar/schedule.provider.ts index c94eef2c..8cabdeeb 100644 --- a/frontend/app/src/app/modules/calendar/schedule.provider.ts +++ b/frontend/app/src/app/modules/calendar/schedule.provider.ts @@ -68,6 +68,8 @@ export type DateSeriesRelevantData = Pick; */ @Injectable() export class ScheduleProvider implements OnDestroy { + private readonly dataProvider = inject(DataProvider); + // tslint:disable:prefer-function-over-method private static partialEventsStorageKey = 'schedule::partial_events'; @@ -76,7 +78,7 @@ export class ScheduleProvider implements OnDestroy { destroy$ = inject(DestroyRef); - constructor(private readonly dataProvider: DataProvider) { + constructor() { window.addEventListener('storage', this.storageListener); } diff --git a/frontend/app/src/app/modules/catalog/catalog.component.ts b/frontend/app/src/app/modules/catalog/catalog.component.ts index c49f92a6..e5a998ef 100644 --- a/frontend/app/src/app/modules/catalog/catalog.component.ts +++ b/frontend/app/src/app/modules/catalog/catalog.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, inject} from '@angular/core'; import {Router, ActivatedRoute} from '@angular/router'; import {SCCatalog, SCSemester} from '@openstapps/core'; import moment from 'moment'; @@ -29,6 +29,18 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class CatalogComponent implements OnInit { + private readonly route = inject(ActivatedRoute); + + private readonly catalogProvider = inject(CatalogProvider); + + private readonly dataRoutingService = inject(DataRoutingService); + + private readonly logger = inject(NGXLogger); + + protected router = inject(Router); + + location = inject(Location); + /** * SCSemester to show */ @@ -54,14 +66,7 @@ export class CatalogComponent implements OnInit { */ superCatalog: SCCatalog; - constructor( - private readonly route: ActivatedRoute, - private readonly catalogProvider: CatalogProvider, - private readonly dataRoutingService: DataRoutingService, - private readonly logger: NGXLogger, - protected router: Router, - public location: Location, - ) { + constructor() { this.dataRoutingService .itemSelectListener() .pipe(takeUntilDestroyed()) diff --git a/frontend/app/src/app/modules/catalog/catalog.provider.ts b/frontend/app/src/app/modules/catalog/catalog.provider.ts index 04a72358..8f262092 100644 --- a/frontend/app/src/app/modules/catalog/catalog.provider.ts +++ b/frontend/app/src/app/modules/catalog/catalog.provider.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import { SCCatalogWithoutReferences, SCSearchFilter, @@ -28,7 +28,7 @@ import {DataProvider} from '../data/data.provider'; providedIn: 'root', }) export class CatalogProvider { - constructor(private readonly dataProvider: DataProvider) {} + private readonly dataProvider = inject(DataProvider); /** * Get news messages diff --git a/frontend/app/src/app/modules/config/config.provider.ts b/frontend/app/src/app/modules/config/config.provider.ts index f64cea40..a309ec7d 100644 --- a/frontend/app/src/app/modules/config/config.provider.ts +++ b/frontend/app/src/app/modules/config/config.provider.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {Client} from '@openstapps/api'; import {SCAppConfiguration, SCIndexResponse} from '@openstapps/core'; import {CORE_VERSION} from '@openstapps/core'; @@ -44,6 +44,12 @@ export const STORAGE_KEY_CONFIG = 'stapps.config'; providedIn: 'root', }) export class ConfigProvider { + private readonly storageProvider = inject(StorageProvider); + + private readonly logger = inject(NGXLogger); + + private readonly internetConnectionService = inject(InternetConnectionService); + /** * Api client */ @@ -66,16 +72,10 @@ export class ConfigProvider { /** * Constructor, initialise api client - * @param storageProvider StorageProvider to load persistent configuration - * @param swHttpClient Api client - * @param logger An angular logger */ - constructor( - private readonly storageProvider: StorageProvider, - swHttpClient: StAppsWebHttpClient, - private readonly logger: NGXLogger, - private readonly internetConnectionService: InternetConnectionService, - ) { + constructor() { + const swHttpClient = inject(StAppsWebHttpClient); + console.log('config init'); this.client = new Client(swHttpClient, environment.backend_url, environment.backend_version); } diff --git a/frontend/app/src/app/modules/dashboard/dashboard.component.ts b/frontend/app/src/app/modules/dashboard/dashboard.component.ts index 078177aa..cf2479e8 100644 --- a/frontend/app/src/app/modules/dashboard/dashboard.component.ts +++ b/frontend/app/src/app/modules/dashboard/dashboard.component.ts @@ -41,6 +41,20 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { + private readonly dataRoutingService = inject(DataRoutingService); + + private scheduleProvider = inject(ScheduleProvider); + + protected router = inject(Router); + + location = inject(Location); + + private animationControl = inject(AnimationController); + + private breakpointObserver = inject(BreakpointObserver); + + private zone = inject(NgZone); + @ViewChild('toolbar', {read: ElementRef}) toolbarRef: ElementRef; @ViewChild('schedule', {read: ElementRef}) scheduleRef: ElementRef; @@ -61,15 +75,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit { destroy$ = inject(DestroyRef); - constructor( - private readonly dataRoutingService: DataRoutingService, - private scheduleProvider: ScheduleProvider, - protected router: Router, - public location: Location, - private animationControl: AnimationController, - private breakpointObserver: BreakpointObserver, - private zone: NgZone, - ) { + constructor() { this.dataRoutingService .itemSelectListener() .pipe(takeUntilDestroyed()) diff --git a/frontend/app/src/app/modules/dashboard/dashboard.provider.ts b/frontend/app/src/app/modules/dashboard/dashboard.provider.ts index 4fa80dab..334f69b3 100644 --- a/frontend/app/src/app/modules/dashboard/dashboard.provider.ts +++ b/frontend/app/src/app/modules/dashboard/dashboard.provider.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {inject, Injectable} from '@angular/core'; import { SCBooleanFilterArguments, SCMessage, @@ -28,7 +28,9 @@ import {DataProvider} from '../data/data.provider'; providedIn: 'root', }) export class DashboardProvider { - constructor(private readonly dataProvider: DataProvider) {} + private readonly dataProvider = inject(DataProvider); + + constructor() {} /** * Get news messages diff --git a/frontend/app/src/app/modules/dashboard/sections/favorites-section/favorites-section.component.ts b/frontend/app/src/app/modules/dashboard/sections/favorites-section/favorites-section.component.ts index eab8e78d..67f7d121 100644 --- a/frontend/app/src/app/modules/dashboard/sections/favorites-section/favorites-section.component.ts +++ b/frontend/app/src/app/modules/dashboard/sections/favorites-section/favorites-section.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, inject} from '@angular/core'; import {filter, map} from 'rxjs/operators'; import {FavoritesService} from '../../../favorites/favorites.service'; import {fadeAnimation} from '../../fade.animation'; @@ -30,10 +30,10 @@ import {isMensaThing} from '../../mensa-filters'; standalone: false, }) export class FavoritesSectionComponent { + private favoritesService = inject(FavoritesService); + items = this.favoritesService.favoriteThings$.pipe( map(favorites => favorites.filter(it => !isMensaThing(it))), filter(favorites => favorites.length > 0), ); - - constructor(private favoritesService: FavoritesService) {} } diff --git a/frontend/app/src/app/modules/dashboard/sections/mensa-section/mensa-section-content.component.ts b/frontend/app/src/app/modules/dashboard/sections/mensa-section/mensa-section-content.component.ts index 07af3939..06a1deb3 100644 --- a/frontend/app/src/app/modules/dashboard/sections/mensa-section/mensa-section-content.component.ts +++ b/frontend/app/src/app/modules/dashboard/sections/mensa-section/mensa-section-content.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, inject} from '@angular/core'; import {SCDish, SCPlace, SCThings} from '@openstapps/core'; import {PlaceMensaService} from '../../../data/types/place/special/mensa/place-mensa-service'; import {fadeAnimation} from '../../fade.animation'; @@ -30,6 +30,8 @@ import {isToday} from 'date-fns'; standalone: false, }) export class MensaSectionContentComponent { + private readonly mensaService = inject(PlaceMensaService); + /** * Map of dishes for each day */ @@ -42,6 +44,4 @@ export class MensaSectionContentComponent { return closestDayWithDishes ? it[closestDayWithDishes] : []; }); } - - constructor(private readonly mensaService: PlaceMensaService) {} } diff --git a/frontend/app/src/app/modules/dashboard/sections/mensa-section/mensa-section.component.ts b/frontend/app/src/app/modules/dashboard/sections/mensa-section/mensa-section.component.ts index 42f653dd..9b676727 100644 --- a/frontend/app/src/app/modules/dashboard/sections/mensa-section/mensa-section.component.ts +++ b/frontend/app/src/app/modules/dashboard/sections/mensa-section/mensa-section.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, inject} from '@angular/core'; import {map} from 'rxjs/operators'; import {FavoritesService} from '../../../favorites/favorites.service'; import {fadeAnimation} from '../../fade.animation'; @@ -30,7 +30,7 @@ import {isMensaThing} from '../../mensa-filters'; standalone: false, }) export class MensaSectionComponent { - items = this.favoritesService.favoriteThings$.pipe(map(favorites => favorites.filter(isMensaThing))); + protected favoritesService = inject(FavoritesService); - constructor(protected favoritesService: FavoritesService) {} + items = this.favoritesService.favoriteThings$.pipe(map(favorites => favorites.filter(isMensaThing))); } diff --git a/frontend/app/src/app/modules/dashboard/sections/news-section/news-section.component.ts b/frontend/app/src/app/modules/dashboard/sections/news-section/news-section.component.ts index be3a1ca8..74eaf1bd 100644 --- a/frontend/app/src/app/modules/dashboard/sections/news-section/news-section.component.ts +++ b/frontend/app/src/app/modules/dashboard/sections/news-section/news-section.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, inject} from '@angular/core'; import {NewsProvider} from '../../../news/news.provider'; import {fadeAnimation} from '../../fade.animation'; @@ -28,10 +28,10 @@ import {fadeAnimation} from '../../fade.animation'; standalone: false, }) export class NewsSectionComponent { + readonly newsProvider = inject(NewsProvider); + news = this.newsProvider .getCurrentFilters() // eslint-disable-next-line unicorn/prefer-top-level-await,unicorn/consistent-function-scoping .then(filters => this.newsProvider.getList(5, 0, filters)); - - constructor(readonly newsProvider: NewsProvider) {} } diff --git a/frontend/app/src/app/modules/dashboard/sections/search-section/search-section.component.ts b/frontend/app/src/app/modules/dashboard/sections/search-section/search-section.component.ts index b9902ae9..51f88f86 100644 --- a/frontend/app/src/app/modules/dashboard/sections/search-section/search-section.component.ts +++ b/frontend/app/src/app/modules/dashboard/sections/search-section/search-section.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {AnimationController} from '@ionic/angular/standalone'; import {homePageSearchTransition} from './search-route-transition'; @@ -26,7 +26,7 @@ import {homePageSearchTransition} from './search-route-transition'; standalone: false, }) export class SearchSectionComponent { - routeTransition = homePageSearchTransition(this.animationController); + private animationController = inject(AnimationController); - constructor(private animationController: AnimationController) {} + routeTransition = homePageSearchTransition(this.animationController); } diff --git a/frontend/app/src/app/modules/data/chips/data/add-event-action-chip.component.ts b/frontend/app/src/app/modules/data/chips/data/add-event-action-chip.component.ts index c2c30818..5d400a3c 100644 --- a/frontend/app/src/app/modules/data/chips/data/add-event-action-chip.component.ts +++ b/frontend/app/src/app/modules/data/chips/data/add-event-action-chip.component.ts @@ -39,6 +39,14 @@ import {MaterialSymbol} from 'material-symbols'; standalone: false, }) export class AddEventActionChipComponent { + readonly dataProvider = inject(CoordinatedSearchProvider); + + readonly modalController = inject(ModalController); + + readonly scheduleProvider = inject(ScheduleProvider); + + readonly routerOutlet = inject(IonRouterOutlet); + /** * Associated date series */ @@ -94,13 +102,6 @@ export class AddEventActionChipComponent { destroy$ = inject(DestroyRef); - constructor( - readonly dataProvider: CoordinatedSearchProvider, - readonly modalController: ModalController, - readonly scheduleProvider: ScheduleProvider, - readonly routerOutlet: IonRouterOutlet, - ) {} - /** * Apply state */ diff --git a/frontend/app/src/app/modules/data/chips/edit-event-selection.component.ts b/frontend/app/src/app/modules/data/chips/edit-event-selection.component.ts index f3a2a68b..78614f77 100644 --- a/frontend/app/src/app/modules/data/chips/edit-event-selection.component.ts +++ b/frontend/app/src/app/modules/data/chips/edit-event-selection.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, inject} from '@angular/core'; import {ModalController} from '@ionic/angular/standalone'; import {SCDateSeries} from '@openstapps/core'; import { @@ -41,6 +41,14 @@ import {SelectionValue, TreeNode} from './tree-node'; standalone: false, }) export class EditEventSelectionComponent implements OnInit { + readonly ref = inject(ChangeDetectorRef); + + readonly scheduleProvider = inject(ScheduleProvider); + + readonly calendar = inject(CalendarService); + + readonly modalController = inject(ModalController); + /** * The item the action belongs to */ @@ -59,13 +67,6 @@ export class EditEventSelectionComponent implements OnInit { @Output() modified = new EventEmitter(); - constructor( - readonly ref: ChangeDetectorRef, - readonly scheduleProvider: ScheduleProvider, - readonly calendar: CalendarService, - readonly modalController: ModalController, - ) {} - ngOnInit() { this.partialDateSeries = this.scheduleProvider.partialEvents$.value; this.reset(); diff --git a/frontend/app/src/app/modules/data/coordinated-search.provider.ts b/frontend/app/src/app/modules/data/coordinated-search.provider.ts index 7c4016ea..83f3d5c7 100644 --- a/frontend/app/src/app/modules/data/coordinated-search.provider.ts +++ b/frontend/app/src/app/modules/data/coordinated-search.provider.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {SCSearchRequest, SCSearchResponse} from '@openstapps/core'; -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {DataProvider} from './data.provider'; /** @@ -50,7 +50,7 @@ interface OngoingQuery { providedIn: 'root', }) export class CoordinatedSearchProvider { - constructor(readonly dataProvider: DataProvider) {} + readonly dataProvider = inject(DataProvider); /** * Queue of ongoing queries diff --git a/frontend/app/src/app/modules/data/data.provider.ts b/frontend/app/src/app/modules/data/data.provider.ts index 69ce4b1a..f10d94b6 100644 --- a/frontend/app/src/app/modules/data/data.provider.ts +++ b/frontend/app/src/app/modules/data/data.provider.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {Client} from '@openstapps/api'; import { SCFacet, @@ -141,12 +141,10 @@ export class DataProvider { return facet; } - /** - * TODO - * @param stAppsWebHttpClient TODO - * @param storageProvider TODO - */ - constructor(stAppsWebHttpClient: StAppsWebHttpClient, storageProvider: StorageProvider) { + constructor() { + const stAppsWebHttpClient = inject(StAppsWebHttpClient); + const storageProvider = inject(StorageProvider); + this.client = new Client(stAppsWebHttpClient, this.backendUrl, this.appVersion); this.storageProvider = storageProvider; } diff --git a/frontend/app/src/app/modules/data/debug-data-collector.service.ts b/frontend/app/src/app/modules/data/debug-data-collector.service.ts index 6cbfd533..631aab5d 100644 --- a/frontend/app/src/app/modules/data/debug-data-collector.service.ts +++ b/frontend/app/src/app/modules/data/debug-data-collector.service.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {SCFeedbackRequestMetaData} from '@openstapps/core'; import {Platform} from '@ionic/angular/standalone'; import {DataProvider} from './data.provider'; @@ -23,6 +23,14 @@ import {SettingsProvider} from '../settings/settings.provider'; providedIn: 'root', }) export class DebugDataCollectorService { + private platform = inject(Platform); + + private dataProvider = inject(DataProvider); + + private router = inject(Router); + + private settingsProvider = inject(SettingsProvider); + /** * Previously visited route */ @@ -33,12 +41,9 @@ export class DebugDataCollectorService { */ currentRoute: string; - constructor( - private platform: Platform, - private dataProvider: DataProvider, - private router: Router, - private settingsProvider: SettingsProvider, - ) { + constructor() { + const router = this.router; + this.currentRoute = this.router.url; router.events.subscribe(event => { if (event instanceof NavigationEnd) { diff --git a/frontend/app/src/app/modules/data/detail/data-detail-content.component.ts b/frontend/app/src/app/modules/data/detail/data-detail-content.component.ts index 9dcedc11..af292be6 100644 --- a/frontend/app/src/app/modules/data/detail/data-detail-content.component.ts +++ b/frontend/app/src/app/modules/data/detail/data-detail-content.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input, TemplateRef} from '@angular/core'; +import {Component, Input, TemplateRef, inject} from '@angular/core'; import {SCThings} from '@openstapps/core'; import {DataListContext} from '../list/data-list.component'; import {ModalController} from '@ionic/angular/standalone'; @@ -27,6 +27,8 @@ import {ModalController} from '@ionic/angular/standalone'; standalone: false, }) export class DataDetailContentComponent { + readonly modalController = inject(ModalController); + /** * TODO */ @@ -37,6 +39,4 @@ export class DataDetailContentComponent { @Input() openAsModal = false; @Input() showModalHeader = false; - - constructor(readonly modalController: ModalController) {} } diff --git a/frontend/app/src/app/modules/data/detail/data-detail.component.ts b/frontend/app/src/app/modules/data/detail/data-detail.component.ts index 3f17d92e..5a4e272c 100644 --- a/frontend/app/src/app/modules/data/detail/data-detail.component.ts +++ b/frontend/app/src/app/modules/data/detail/data-detail.component.ts @@ -12,7 +12,16 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, ContentChild, EventEmitter, Input, OnInit, Output, TemplateRef} from '@angular/core'; +import { + Component, + ContentChild, + EventEmitter, + Input, + OnInit, + Output, + TemplateRef, + inject, +} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {ModalController} from '@ionic/angular/standalone'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; @@ -39,6 +48,14 @@ export interface ExternalDataLoadEvent { standalone: false, }) export class DataDetailComponent implements OnInit { + protected readonly route = inject(ActivatedRoute); + + private readonly dataProvider = inject(DataProvider); + + private readonly favoritesService = inject(FavoritesService); + + readonly modalController = inject(ModalController); + /** * The associated item * @@ -87,14 +104,10 @@ export class DataDetailComponent implements OnInit { return (thing as SCSaveableThing).data !== undefined; } - constructor( - protected readonly route: ActivatedRoute, - router: Router, - private readonly dataProvider: DataProvider, - private readonly favoritesService: FavoritesService, - readonly modalController: ModalController, - translateService: TranslateService, - ) { + constructor() { + const router = inject(Router); + const translateService = inject(TranslateService); + this.inputItem = router.currentNavigation()?.extras.state?.item; if (!this.inputItem?.origin) { // We received a ThingWithoutReferences. diff --git a/frontend/app/src/app/modules/data/detail/data-path.component.ts b/frontend/app/src/app/modules/data/detail/data-path.component.ts index 3fa0b416..9373cb05 100644 --- a/frontend/app/src/app/modules/data/detail/data-path.component.ts +++ b/frontend/app/src/app/modules/data/detail/data-path.component.ts @@ -29,6 +29,14 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class DataPathComponent implements OnInit { + readonly dataRoutingService = inject(DataRoutingService); + + readonly navController = inject(NavController); + + readonly routeStack = inject(RoutingStackService); + + readonly dataProvider = inject(DataProvider); + path: Promise; $width: Observable; @@ -66,13 +74,6 @@ export class DataPathComponent implements OnInit { destroy$ = inject(DestroyRef); - constructor( - readonly dataRoutingService: DataRoutingService, - readonly navController: NavController, - readonly routeStack: RoutingStackService, - readonly dataProvider: DataProvider, - ) {} - ngOnInit() { this.$width = fromEvent(window, 'resize').pipe( map(() => window.innerWidth), diff --git a/frontend/app/src/app/modules/data/elements/external-link.component.ts b/frontend/app/src/app/modules/data/elements/external-link.component.ts index 582a83df..d28a4871 100644 --- a/frontend/app/src/app/modules/data/elements/external-link.component.ts +++ b/frontend/app/src/app/modules/data/elements/external-link.component.ts @@ -13,9 +13,10 @@ * this program. If not, see . */ -import {Component, Input} from '@angular/core'; +import {Component, Input, inject} from '@angular/core'; import {Browser} from '@capacitor/browser'; import {Capacitor} from '@capacitor/core'; +import {SimpleBrowser} from '../../../util/browser.factory'; @Component({ selector: 'stapps-external-link', @@ -24,6 +25,8 @@ import {Capacitor} from '@capacitor/core'; standalone: false, }) export class ExternalLinkComponent { + private browser = inject(SimpleBrowser); + @Input() link: string; @Input() text: string; diff --git a/frontend/app/src/app/modules/data/elements/favorite-button.component.ts b/frontend/app/src/app/modules/data/elements/favorite-button.component.ts index f338eee4..6bc2ae32 100644 --- a/frontend/app/src/app/modules/data/elements/favorite-button.component.ts +++ b/frontend/app/src/app/modules/data/elements/favorite-button.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, inject} from '@angular/core'; import {SCIndexableThings} from '@openstapps/core'; import {FavoritesService} from '../../favorites/favorites.service'; import {Observable} from 'rxjs'; @@ -29,6 +29,8 @@ import {map, take} from 'rxjs/operators'; standalone: false, }) export class FavoriteButtonComponent { + private favoritesService = inject(FavoritesService); + /** * Item getter */ @@ -58,8 +60,6 @@ export class FavoriteButtonComponent { */ isFavorite$: Observable; - constructor(private favoritesService: FavoritesService) {} - /** * Add or remove the thing from favorites (depending on its current status) * @param event A click event diff --git a/frontend/app/src/app/modules/data/elements/offers-in-list.component.ts b/frontend/app/src/app/modules/data/elements/offers-in-list.component.ts index 2d7876a2..2ce86f10 100644 --- a/frontend/app/src/app/modules/data/elements/offers-in-list.component.ts +++ b/frontend/app/src/app/modules/data/elements/offers-in-list.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input} from '@angular/core'; +import {Component, Input, inject} from '@angular/core'; import { SCAcademicPriceGroup, SCThingThatCanBeOfferedAvailability, @@ -27,6 +27,8 @@ import {SettingsProvider} from '../../settings/settings.provider'; standalone: false, }) export class OffersInListComponent { + readonly settingsProvider = inject(SettingsProvider); + @Input() set offers(it: Array>) { this._offers = it; this.price = it[0].prices?.default; @@ -44,6 +46,4 @@ export class OffersInListComponent { availability: SCThingThatCanBeOfferedAvailability; _offers: Array>; - - constructor(readonly settingsProvider: SettingsProvider) {} } diff --git a/frontend/app/src/app/modules/data/elements/rating.component.ts b/frontend/app/src/app/modules/data/elements/rating.component.ts index a8f527ee..f092f3c5 100644 --- a/frontend/app/src/app/modules/data/elements/rating.component.ts +++ b/frontend/app/src/app/modules/data/elements/rating.component.ts @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectionStrategy, Component, ElementRef, HostListener, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, ElementRef, HostListener, Input, inject} from '@angular/core'; import {SCDish, SCRatingRequest} from '@openstapps/core'; import {RatingProvider} from '../rating.provider'; import {ratingAnimation} from './rating.animation'; @@ -29,6 +29,10 @@ import {catchError, map} from 'rxjs/operators'; standalone: false, }) export class StappsRatingComponent { + readonly elementRef = inject(ElementRef); + + readonly ratingProvider = inject(RatingProvider); + performRating = new BehaviorSubject(false); userRating = new BehaviorSubject(undefined); @@ -52,11 +56,6 @@ export class StappsRatingComponent { this.dish.next(value); } - constructor( - readonly elementRef: ElementRef, - readonly ratingProvider: RatingProvider, - ) {} - @HostListener('document:mousedown', ['$event']) clickOutside(event: MouseEvent) { if (this.userRating.value) return; diff --git a/frontend/app/src/app/modules/data/elements/share-button.component.ts b/frontend/app/src/app/modules/data/elements/share-button.component.ts index 16484ac1..093859b5 100644 --- a/frontend/app/src/app/modules/data/elements/share-button.component.ts +++ b/frontend/app/src/app/modules/data/elements/share-button.component.ts @@ -1,4 +1,4 @@ -import {Component, Input} from '@angular/core'; +import {Component, Input, inject} from '@angular/core'; import {ToastController} from '@ionic/angular/standalone'; import {environment} from '../../../../environments/environment'; @@ -9,14 +9,14 @@ import {environment} from '../../../../environments/environment'; standalone: false, }) export class ShareButtonComponent { + readonly toastController = inject(ToastController); + canShare = false; @Input({required: true}) title: string; @Input() url: string; - constructor(readonly toastController: ToastController) {} - share(): boolean { const url = this.url ?? new URL(window.location.pathname, `https://${environment.app_host}`); diff --git a/frontend/app/src/app/modules/data/list/data-list-item-host.directive.ts b/frontend/app/src/app/modules/data/list/data-list-item-host.directive.ts index df247a78..3078076a 100644 --- a/frontend/app/src/app/modules/data/list/data-list-item-host.directive.ts +++ b/frontend/app/src/app/modules/data/list/data-list-item-host.directive.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ComponentRef, Directive, Input, Type, ViewContainerRef} from '@angular/core'; +import {ComponentRef, Directive, Input, Type, ViewContainerRef, inject} from '@angular/core'; import {SCThings, SCThingType} from '@openstapps/core'; import {CatalogListItemComponent} from '../types/catalog/catalog-list-item.component'; import {DateSeriesListItemComponent} from '../types/date-series/date-series-list-item.component'; @@ -56,12 +56,12 @@ const DataListItemIndex: Partial>> = { standalone: false, }) export class DataListItemHostDirective { + readonly viewContainerRef = inject(ViewContainerRef); + private type?: Type; private component?: ComponentRef; - constructor(readonly viewContainerRef: ViewContainerRef) {} - @Input() set dataListItemHost(value: SCThings | undefined) { if (!value) { this.viewContainerRef.clear(); diff --git a/frontend/app/src/app/modules/data/list/data-list-item.component.ts b/frontend/app/src/app/modules/data/list/data-list-item.component.ts index 965d023a..3c3ba9d2 100644 --- a/frontend/app/src/app/modules/data/list/data-list-item.component.ts +++ b/frontend/app/src/app/modules/data/list/data-list-item.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, ContentChild, HostBinding, Input, TemplateRef} from '@angular/core'; +import {Component, ContentChild, HostBinding, Input, TemplateRef, inject} from '@angular/core'; import {SCThings} from '@openstapps/core'; import {DataRoutingService} from '../data-routing.service'; import {DataListContext} from './data-list.component'; @@ -27,6 +27,8 @@ import {DataListContext} from './data-list.component'; standalone: false, }) export class DataListItemComponent { + private readonly dataRoutingService = inject(DataRoutingService); + /** * Whether the list item should show a thumbnail */ @@ -55,8 +57,6 @@ export class DataListItemComponent { return this.appearance === 'square'; } - constructor(private readonly dataRoutingService: DataRoutingService) {} - /** * Emit event that an item was selected */ diff --git a/frontend/app/src/app/modules/data/list/food-data-list.component.ts b/frontend/app/src/app/modules/data/list/food-data-list.component.ts index b753ff6c..546d686b 100644 --- a/frontend/app/src/app/modules/data/list/food-data-list.component.ts +++ b/frontend/app/src/app/modules/data/list/food-data-list.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {PositionService} from '../../map/position.service'; import {Geolocation} from '@capacitor/geolocation'; import {BehaviorSubject, catchError} from 'rxjs'; @@ -68,7 +68,10 @@ export class FoodDataListComponent { type: 'boolean', }; - constructor(positionService: PositionService, contextMenuService: ContextMenuService) { + constructor() { + const positionService = inject(PositionService); + const contextMenuService = inject(ContextMenuService); + positionService .watchCurrentLocation({enableHighAccuracy: false, maximumAge: 1000}) .pipe( diff --git a/frontend/app/src/app/modules/data/list/search-page.component.ts b/frontend/app/src/app/modules/data/list/search-page.component.ts index ef46588a..589bbdde 100644 --- a/frontend/app/src/app/modules/data/list/search-page.component.ts +++ b/frontend/app/src/app/modules/data/list/search-page.component.ts @@ -31,7 +31,6 @@ import {SettingsProvider} from '../../settings/settings.provider'; import {DataRoutingService} from '../data-routing.service'; import {DataProvider} from '../data.provider'; import {PositionService} from '../../map/position.service'; -import {ConfigProvider} from '../../config/config.provider'; import {searchPageSwitchAnimation} from './search-page-switch-animation'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; import {ContextMenuModalComponent} from '../../menu/context/context-menu-modal.component'; @@ -48,6 +47,28 @@ import {enterAnimation, leaveAnimation} from '../../menu/context/context-menu-mo standalone: false, }) export class SearchPageComponent implements OnInit { + protected readonly alertController = inject(AlertController); + + protected dataProvider = inject(DataProvider); + + protected readonly contextMenuService = inject(ContextMenuService); + + protected readonly settingsProvider = inject(SettingsProvider); + + protected readonly logger = inject(NGXLogger); + + protected dataRoutingService = inject(DataRoutingService); + + protected router = inject(Router); + + private readonly route = inject(ActivatedRoute); + + protected positionService = inject(PositionService); + + protected animationController = inject(AnimationController); + + protected modalController = inject(ModalController); + @Input() title = 'search.title'; @Input() placeholder = 'search.search_bar.placeholder'; @@ -144,31 +165,10 @@ export class SearchPageComponent implements OnInit { /** * Injects the providers and creates subscriptions - * @param alertController AlertController - * @param dataProvider DataProvider - * @param contextMenuService ContextMenuService - * @param settingsProvider SettingsProvider - * @param logger An angular logger - * @param dataRoutingService DataRoutingService - * @param router Router - * @param route ActivatedRoute - * @param positionService PositionService - * @param configProvider ConfigProvider */ - constructor( - protected readonly alertController: AlertController, - protected dataProvider: DataProvider, - protected readonly contextMenuService: ContextMenuService, - protected readonly settingsProvider: SettingsProvider, - protected readonly logger: NGXLogger, - protected dataRoutingService: DataRoutingService, - protected router: Router, - private readonly route: ActivatedRoute, - protected positionService: PositionService, - private readonly configProvider: ConfigProvider, - protected animationController: AnimationController, - protected modalController: ModalController, - ) { + constructor() { + const animationController = this.animationController; + this.routeAnimation = searchPageSwitchAnimation(animationController); } diff --git a/frontend/app/src/app/modules/data/list/simple-data-list.component.ts b/frontend/app/src/app/modules/data/list/simple-data-list.component.ts index 2ffac32a..32e1b62d 100644 --- a/frontend/app/src/app/modules/data/list/simple-data-list.component.ts +++ b/frontend/app/src/app/modules/data/list/simple-data-list.component.ts @@ -29,6 +29,10 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class SimpleDataListComponent implements OnInit { + protected router = inject(Router); + + private readonly dataRoutingService = inject(DataRoutingService); + @Input() items?: Promise; /** @@ -54,11 +58,6 @@ export class SimpleDataListComponent implements OnInit { destroy$ = inject(DestroyRef); - constructor( - protected router: Router, - private readonly dataRoutingService: DataRoutingService, - ) {} - ngOnInit(): void { if (!this.autoRouting) return; this.dataRoutingService diff --git a/frontend/app/src/app/modules/data/rating.provider.ts b/frontend/app/src/app/modules/data/rating.provider.ts index 3841acc6..6dab1627 100644 --- a/frontend/app/src/app/modules/data/rating.provider.ts +++ b/frontend/app/src/app/modules/data/rating.provider.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import { SCAcademicPriceGroup, SCDish, @@ -39,6 +39,10 @@ interface RatingStorage { providedIn: 'root', }) export class RatingProvider { + private readonly storageProvider = inject(StorageProvider); + + private readonly settingsProvider = inject(SettingsProvider); + private readonly client: Client; private readonly backendUrl = environment.backend_url; @@ -49,11 +53,9 @@ export class RatingProvider { private readonly storageKey = 'rating.rated_uuids'; - constructor( - stAppsWebHttpClient: StAppsWebHttpClient, - private readonly storageProvider: StorageProvider, - private readonly settingsProvider: SettingsProvider, - ) { + constructor() { + const stAppsWebHttpClient = inject(StAppsWebHttpClient); + this.client = new Client(stAppsWebHttpClient, this.backendUrl, this.appVersion); } diff --git a/frontend/app/src/app/modules/data/stapps-web-http-client.provider.ts b/frontend/app/src/app/modules/data/stapps-web-http-client.provider.ts index 341229d3..f212e88a 100644 --- a/frontend/app/src/app/modules/data/stapps-web-http-client.provider.ts +++ b/frontend/app/src/app/modules/data/stapps-web-http-client.provider.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {HttpClient, HttpResponse} from '@angular/common/http'; -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {HttpClientInterface, HttpClientRequest} from '@openstapps/api'; import {map, retry} from 'rxjs/operators'; import {lastValueFrom, Observable} from 'rxjs'; @@ -32,13 +32,9 @@ type HttpRequestParameters> = Paramet */ @Injectable() export class StAppsWebHttpClient implements HttpClientInterface { - /** - * - */ - constructor( - private readonly http: HttpClient, - private readonly connectionService: InternetConnectionService, - ) {} + private readonly http = inject(HttpClient); + + private readonly connectionService = inject(InternetConnectionService); /** * Make a request diff --git a/frontend/app/src/app/modules/data/types/catalog/catalog-detail-content.component.ts b/frontend/app/src/app/modules/data/types/catalog/catalog-detail-content.component.ts index d02e67a3..41cb60ff 100644 --- a/frontend/app/src/app/modules/data/types/catalog/catalog-detail-content.component.ts +++ b/frontend/app/src/app/modules/data/types/catalog/catalog-detail-content.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input, OnInit, inject} from '@angular/core'; import {SCCatalog, SCThings} from '@openstapps/core'; import {DataProvider} from '../../data.provider'; @@ -23,6 +23,8 @@ import {DataProvider} from '../../data.provider'; standalone: false, }) export class CatalogDetailContentComponent implements OnInit { + private dataProvider = inject(DataProvider); + /** * SCCatalog to display */ @@ -30,8 +32,6 @@ export class CatalogDetailContentComponent implements OnInit { items: Promise; - constructor(private dataProvider: DataProvider) {} - async ngOnInit() { this.items = this.dataProvider .search({ diff --git a/frontend/app/src/app/modules/data/types/date-series/date-series-detail-content.component.ts b/frontend/app/src/app/modules/data/types/date-series/date-series-detail-content.component.ts index 24f1b37e..12bd63c7 100644 --- a/frontend/app/src/app/modules/data/types/date-series/date-series-detail-content.component.ts +++ b/frontend/app/src/app/modules/data/types/date-series/date-series-detail-content.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input, OnInit, inject} from '@angular/core'; import {SCDateSeries} from '@openstapps/core'; import {ScheduleProvider, toDateSeriesRelevantData} from '../../../calendar/schedule.provider'; import {Observable} from 'rxjs'; @@ -28,15 +28,16 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class DateSeriesDetailContentComponent implements OnInit { + readonly scheduleProvider = inject(ScheduleProvider); + @Input() item: SCDateSeries; isInCalendar: Observable; - constructor( - readonly scheduleProvider: ScheduleProvider, - dataRoutingService: DataRoutingService, - router: Router, - ) { + constructor() { + const dataRoutingService = inject(DataRoutingService); + const router = inject(Router); + dataRoutingService .itemSelectListener() .pipe(takeUntilDestroyed()) diff --git a/frontend/app/src/app/modules/data/types/message/message-detail-content.component.ts b/frontend/app/src/app/modules/data/types/message/message-detail-content.component.ts index 3abfa058..bf458321 100644 --- a/frontend/app/src/app/modules/data/types/message/message-detail-content.component.ts +++ b/frontend/app/src/app/modules/data/types/message/message-detail-content.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input} from '@angular/core'; +import {Component, Input, inject} from '@angular/core'; import {SCMessage} from '@openstapps/core'; import {SimpleBrowser} from '../../../../util/browser.factory'; @@ -26,7 +26,7 @@ import {SimpleBrowser} from '../../../../util/browser.factory'; standalone: false, }) export class MessageDetailContentComponent { - constructor(private browser: SimpleBrowser) {} + private browser = inject(SimpleBrowser); /** * TODO diff --git a/frontend/app/src/app/modules/data/types/person/person-detail-content.component.ts b/frontend/app/src/app/modules/data/types/person/person-detail-content.component.ts index 0a31890d..b88f72bb 100644 --- a/frontend/app/src/app/modules/data/types/person/person-detail-content.component.ts +++ b/frontend/app/src/app/modules/data/types/person/person-detail-content.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input} from '@angular/core'; +import {Component, Input, inject} from '@angular/core'; import { SCContactPoint, SCContactPointWithoutReferences, @@ -28,6 +28,8 @@ import {DataProvider} from '../../data.provider'; standalone: false, }) export class PersonDetailContentComponent { + private readonly dataProvider = inject(DataProvider); + private _item: SCPerson; contactPoints: Array; @@ -46,8 +48,6 @@ export class PersonDetailContentComponent { } } - constructor(private readonly dataProvider: DataProvider) {} - async getContactPoints(workLocations: SCContactPointWithoutReferences[]): Promise { const query: {[uid in SCUuid]: SCSearchQuery} = {}; workLocations.map(workLocation => { diff --git a/frontend/app/src/app/modules/data/types/place/place-detail-content.component.ts b/frontend/app/src/app/modules/data/types/place/place-detail-content.component.ts index bbf948d3..f16817bb 100644 --- a/frontend/app/src/app/modules/data/types/place/place-detail-content.component.ts +++ b/frontend/app/src/app/modules/data/types/place/place-detail-content.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input, OnInit, inject} from '@angular/core'; import {SCBuilding, SCFloor, SCPointOfInterest, SCRoom, SCThings, SCPlace} from '@openstapps/core'; import {DataProvider} from '../../data.provider'; import {hasValidLocation, isSCFloor} from './place-types'; @@ -55,7 +55,10 @@ export class PlaceDetailContentComponent implements OnInit { ); } - constructor(dataRoutingService: DataRoutingService, router: Router) { + constructor() { + const dataRoutingService = inject(DataRoutingService); + const router = inject(Router); + dataRoutingService .itemSelectListener() .pipe(takeUntilDestroyed()) diff --git a/frontend/app/src/app/modules/data/types/place/place-list-item.component.ts b/frontend/app/src/app/modules/data/types/place/place-list-item.component.ts index bda7919c..77e8645e 100644 --- a/frontend/app/src/app/modules/data/types/place/place-list-item.component.ts +++ b/frontend/app/src/app/modules/data/types/place/place-list-item.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, inject} from '@angular/core'; import {PositionService} from '../../../map/position.service'; import {filter, Observable} from 'rxjs'; import {hasValidLocation, isSCFloor, PlaceTypes, PlaceTypesWithDistance} from './place-types'; @@ -31,6 +31,8 @@ import {trigger, transition, style, animate} from '@angular/animations'; standalone: false, }) export class PlaceListItemComponent { + private positionService = inject(PositionService); + _item: PlaceTypesWithDistance; /** @@ -56,6 +58,4 @@ export class PlaceListItemComponent { * Distance in meters */ distance?: Observable; - - constructor(private positionService: PositionService) {} } diff --git a/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts b/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts index 12fbab7a..6edfff97 100644 --- a/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts +++ b/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-detail.component.ts @@ -32,6 +32,14 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class PlaceMensaDetailComponent implements AfterViewInit { + private readonly mensaService = inject(PlaceMensaService); + + protected router = inject(Router); + + readonly routerOutlet = inject(IonRouterOutlet); + + private readonly dataRoutingService = inject(DataRoutingService); + /** * Map of dishes for each day */ @@ -55,13 +63,6 @@ export class PlaceMensaDetailComponent implements AfterViewInit { destroy$ = inject(DestroyRef); - constructor( - private readonly mensaService: PlaceMensaService, - protected router: Router, - readonly routerOutlet: IonRouterOutlet, - private readonly dataRoutingService: DataRoutingService, - ) {} - ngAfterViewInit() { if (!this.openAsModal) { this.dataRoutingService diff --git a/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-service.ts b/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-service.ts index 363a852c..47f96bc8 100644 --- a/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-service.ts +++ b/frontend/app/src/app/modules/data/types/place/special/mensa/place-mensa-service.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {SCDish, SCISO8601Date, SCPlace, SCSearchQuery, SCThingType} from '@openstapps/core'; import {DataProvider} from '../../../../data.provider'; import {mapValues} from '@openstapps/collection-utils'; @@ -23,10 +23,9 @@ import {addDays, startOfHour} from 'date-fns'; providedIn: 'root', }) export class PlaceMensaService { - constructor( - private dataProvider: DataProvider, - readonly settingsProvider: SettingsProvider, - ) {} + private dataProvider = inject(DataProvider); + + readonly settingsProvider = inject(SettingsProvider); /** * Fetches all dishes for this building diff --git a/frontend/app/src/app/modules/favorites/favorites-page.component.ts b/frontend/app/src/app/modules/favorites/favorites-page.component.ts index 15270ae0..9a7140f5 100644 --- a/frontend/app/src/app/modules/favorites/favorites-page.component.ts +++ b/frontend/app/src/app/modules/favorites/favorites-page.component.ts @@ -12,20 +12,12 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, OnInit} from '@angular/core'; -import {AlertController, AnimationController, ModalController} from '@ionic/angular/standalone'; -import {ActivatedRoute, Router} from '@angular/router'; -import {NGXLogger} from 'ngx-logger'; +import {Component, OnInit, inject} from '@angular/core'; import {debounceTime, distinctUntilChanged, startWith, take} from 'rxjs/operators'; import {combineLatest} from 'rxjs'; import {FavoritesService} from './favorites.service'; -import {DataRoutingService} from '../data/data-routing.service'; import {ContextMenuService} from '../menu/context/context-menu.service'; import {SearchPageComponent} from '../data/list/search-page.component'; -import {DataProvider} from '../data/data.provider'; -import {SettingsProvider} from '../settings/settings.provider'; -import {PositionService} from '../map/position.service'; -import {ConfigProvider} from '../config/config.provider'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; /** @@ -38,39 +30,14 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class FavoritesPageComponent extends SearchPageComponent implements OnInit { + private favoritesService = inject(FavoritesService); + title = 'favorites.page.TITLE'; showNavigation = false; - constructor( - alertController: AlertController, - dataProvider: DataProvider, - contextMenuService: ContextMenuService, - settingsProvider: SettingsProvider, - logger: NGXLogger, - dataRoutingService: DataRoutingService, - router: Router, - route: ActivatedRoute, - positionService: PositionService, - private favoritesService: FavoritesService, - configProvider: ConfigProvider, - animationController: AnimationController, - modalController: ModalController, - ) { - super( - alertController, - dataProvider, - contextMenuService, - settingsProvider, - logger, - dataRoutingService, - router, - route, - positionService, - configProvider, - animationController, - modalController, - ); + constructor() { + super(); } ngOnInit() { diff --git a/frontend/app/src/app/modules/favorites/favorites.service.ts b/frontend/app/src/app/modules/favorites/favorites.service.ts index 9c8cf121..e3c0eb00 100644 --- a/frontend/app/src/app/modules/favorites/favorites.service.ts +++ b/frontend/app/src/app/modules/favorites/favorites.service.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import { SCFacet, SCFavorite, @@ -41,6 +41,12 @@ import {debounceTime, map} from 'rxjs/operators'; providedIn: 'root', }) export class FavoritesService { + private storageProvider = inject(StorageProvider); + + private readonly translate = inject(TranslateService); + + private readonly thingTranslate = inject(ThingTranslateService); + /** * Translation pipe */ @@ -119,12 +125,8 @@ export class FavoritesService { */ private _storagePrefix = 'stapps.favorites'; - constructor( - private storageProvider: StorageProvider, - private readonly translate: TranslateService, - private readonly thingTranslate: ThingTranslateService, - ) { - this.thingTranslatePipe = new ThingTranslatePipe(this.translate, this.thingTranslate); + constructor() { + this.thingTranslatePipe = new ThingTranslatePipe(); void this.emitAll(); } diff --git a/frontend/app/src/app/modules/feedback/feedback-page.component.ts b/frontend/app/src/app/modules/feedback/feedback-page.component.ts index f0eb218e..5c28fa1c 100644 --- a/frontend/app/src/app/modules/feedback/feedback-page.component.ts +++ b/frontend/app/src/app/modules/feedback/feedback-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component} from '@angular/core'; +import {Component, inject} from '@angular/core'; import { SCFeedbackRequest, SCFeedbackRequestMetaData, @@ -32,19 +32,21 @@ import {TranslateService} from '@ngx-translate/core'; standalone: false, }) export class FeedbackPageComponent { + private readonly dataProvider = inject(DataProvider); + + private readonly debugDataCollector = inject(DebugDataCollectorService); + + private readonly toastController = inject(ToastController); + + private readonly alertController = inject(AlertController); + + private readonly translateService = inject(TranslateService); + /** * Minimum allowed size of the feedback message */ MINIMUM_MESSAGE_SIZE = 15; - constructor( - private readonly dataProvider: DataProvider, - private readonly debugDataCollector: DebugDataCollectorService, - private readonly toastController: ToastController, - private readonly alertController: AlertController, - private readonly translateService: TranslateService, - ) {} - /** * Sender of the feedback message */ diff --git a/frontend/app/src/app/modules/map/cluster-leaves.pipe.ts b/frontend/app/src/app/modules/map/cluster-leaves.pipe.ts index 4f960438..8de1857d 100644 --- a/frontend/app/src/app/modules/map/cluster-leaves.pipe.ts +++ b/frontend/app/src/app/modules/map/cluster-leaves.pipe.ts @@ -1,4 +1,4 @@ -import {Pipe, PipeTransform} from '@angular/core'; +import {Pipe, PipeTransform, inject} from '@angular/core'; import {MapService} from '@maplibre/ngx-maplibre-gl'; import {Feature, Point} from 'geojson'; import {MapGeoJSONFeature, type GeoJSONSource} from 'maplibre-gl'; @@ -11,6 +11,8 @@ import {SCFeatureProperties} from './feature-collection.pipe'; pure: true, }) export class MglClusterLeavesPipe implements PipeTransform { + private mapService = inject(MapService); + source = new ReplaySubject(1); feature = new ReplaySubject(1); @@ -33,8 +35,6 @@ export class MglClusterLeavesPipe implements PipeTransform { ), ); - constructor(private mapService: MapService) {} - transform( source: string, feature: MapGeoJSONFeature, diff --git a/frontend/app/src/app/modules/map/controls/compass-control.component.ts b/frontend/app/src/app/modules/map/controls/compass-control.component.ts index 9b736066..c39e6b86 100644 --- a/frontend/app/src/app/modules/map/controls/compass-control.component.ts +++ b/frontend/app/src/app/modules/map/controls/compass-control.component.ts @@ -1,5 +1,5 @@ import {AsyncPipe} from '@angular/common'; -import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, inject} from '@angular/core'; import {IonFabButton} from '@ionic/angular/standalone'; import {MapService} from '@maplibre/ngx-maplibre-gl'; import {MapEventType} from 'maplibre-gl'; @@ -13,6 +13,8 @@ import {map, mergeMap, fromEventPattern, merge} from 'rxjs'; imports: [AsyncPipe, IonFabButton], }) export class CompassControlComponent { + readonly mapService = inject(MapService); + transform = this.mapService.mapCreated$.pipe( mergeMap(() => merge( @@ -26,12 +28,10 @@ export class CompassControlComponent { ), ), ), - map(event => { + map(_event => { // const pitch = event.target.transform.pitch; // const bearing = event.target.transform.bearing; // return `rotateX(${pitch}deg) rotateZ(${bearing}deg)`; }), ); - - constructor(readonly mapService: MapService) {} } diff --git a/frontend/app/src/app/modules/map/controls/geolocate-control.component.ts b/frontend/app/src/app/modules/map/controls/geolocate-control.component.ts index dd7c79a2..751b60e1 100644 --- a/frontend/app/src/app/modules/map/controls/geolocate-control.component.ts +++ b/frontend/app/src/app/modules/map/controls/geolocate-control.component.ts @@ -7,6 +7,7 @@ import { Input, OnDestroy, ViewChild, + inject, } from '@angular/core'; import {IonFabButton} from '@ionic/angular/standalone'; import {MapService} from '@maplibre/ngx-maplibre-gl'; @@ -54,6 +55,8 @@ class CustomGeolocateControl extends GeolocateControl { imports: [AsyncPipe, IonIconDirective, IonFabButton], }) export class GeolocateControlComponent implements AfterContentInit, OnDestroy { + private mapService = inject(MapService); + @Input() position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; @Input() positionOptions?: PositionOptions; @@ -70,8 +73,6 @@ export class GeolocateControlComponent implements AfterContentInit, OnDestroy { control: CustomGeolocateControl; - constructor(private mapService: MapService) {} - ngAfterContentInit() { this.control = new CustomGeolocateControl(this.content.nativeElement, this.watchState, { positionOptions: this.positionOptions, diff --git a/frontend/app/src/app/modules/map/elements/building-markers.component.ts b/frontend/app/src/app/modules/map/elements/building-markers.component.ts index 6ed0046f..4d6da320 100644 --- a/frontend/app/src/app/modules/map/elements/building-markers.component.ts +++ b/frontend/app/src/app/modules/map/elements/building-markers.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectionStrategy, Component, Input, Optional} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, inject} from '@angular/core'; import {GeoJSONSourceComponent, LayerComponent, MapService} from '@maplibre/ngx-maplibre-gl'; import {FeatureCollection, Polygon} from 'geojson'; import {SCFeatureProperties} from '../feature-collection.pipe'; @@ -28,6 +28,12 @@ function getCssVariable(color: string) { imports: [GeoJSONSourceComponent, LayerComponent, AsyncPipe], }) export class BuildingMarkersComponent { + readonly dataProvider = inject(MapDataProvider, {optional: true}); + + readonly dataRoutingService = inject(DataRoutingService); + + readonly mapService = inject(MapService); + accentColor = getCssVariable('--ion-color-primary'); haloColor = fromEvent( @@ -64,12 +70,6 @@ export class BuildingMarkersComponent { @Input({required: true}) data: FeatureCollection; - constructor( - @Optional() readonly dataProvider: MapDataProvider | null, - readonly dataRoutingService: DataRoutingService, - readonly mapService: MapService, - ) {} - async featureClick(event: MapLayerMouseEvent) { if (this.dataProvider === null) return; diff --git a/frontend/app/src/app/modules/map/elements/poi-marker.component.ts b/frontend/app/src/app/modules/map/elements/poi-marker.component.ts index 1f9c9113..f62c9af1 100644 --- a/frontend/app/src/app/modules/map/elements/poi-marker.component.ts +++ b/frontend/app/src/app/modules/map/elements/poi-marker.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectionStrategy, Component, HostBinding, Input, OnInit, Optional} from '@angular/core'; +import {ChangeDetectionStrategy, Component, HostBinding, Input, OnInit, inject} from '@angular/core'; import {MapIconDirective} from '../map-icon.directive'; import {Feature, Point} from 'geojson'; import {SCFeatureProperties} from '../feature-collection.pipe'; @@ -16,17 +16,16 @@ import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; imports: [IonIconDirective, MapIconDirective, AddWordBreakOpportunitiesPipe, IonLabel, IonButton], }) export class PoiMarkerComponent implements OnInit { + readonly dataProvider = inject(MapDataProvider, {optional: true}); + + readonly dataRoutingService = inject(DataRoutingService); + @Input({required: true}) feature: Feature; @HostBinding('disabled') disabled = this.dataProvider === null; fontSize = 0; - constructor( - @Optional() readonly dataProvider: MapDataProvider | null, - readonly dataRoutingService: DataRoutingService, - ) {} - async featureClick() { if (this.dataProvider === null) return; diff --git a/frontend/app/src/app/modules/map/geo-navigation.directive.ts b/frontend/app/src/app/modules/map/geo-navigation.directive.ts index 00d115f7..371592e7 100644 --- a/frontend/app/src/app/modules/map/geo-navigation.directive.ts +++ b/frontend/app/src/app/modules/map/geo-navigation.directive.ts @@ -1,4 +1,4 @@ -import {Directive, HostListener, Input} from '@angular/core'; +import {Directive, HostListener, Input, inject} from '@angular/core'; import {SCPlaceWithoutReferences, SCThings, SCThingWithoutReferences} from '@openstapps/core'; import {Device} from '@capacitor/device'; import {ActionSheetController, ActionSheetOptions, ToastController} from '@ionic/angular/standalone'; @@ -20,17 +20,19 @@ import {PositionService} from './position.service'; standalone: true, }) export class GeoNavigationDirective { + private actionSheetController = inject(ActionSheetController); + + private translateService = inject(TranslateService); + + private thingTranslate = inject(ThingTranslateService); + + private toastController = inject(ToastController); + + private positionService = inject(PositionService); + @Input({required: true}) geoNavigation: SCThingWithoutReferences & Pick; - constructor( - private actionSheetController: ActionSheetController, - private translateService: TranslateService, - private thingTranslate: ThingTranslateService, - private toastController: ToastController, - private positionService: PositionService, - ) {} - @HostListener('click', ['$event']) async presentActionSheet(event: Event) { event.stopPropagation(); diff --git a/frontend/app/src/app/modules/map/map-page.component.ts b/frontend/app/src/app/modules/map/map-page.component.ts index cd141cd6..dfbf88e8 100644 --- a/frontend/app/src/app/modules/map/map-page.component.ts +++ b/frontend/app/src/app/modules/map/map-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, inject} from '@angular/core'; import {LngLatBoundsLike, MapLibreEvent} from 'maplibre-gl'; import {ControlComponent, MapComponent, ScaleControlDirective} from '@maplibre/ngx-maplibre-gl'; import {TranslateModule} from '@ngx-translate/core'; @@ -71,6 +71,10 @@ import {GeolocateControlComponent} from './controls/geolocate-control.component' ], }) export class MapPageComponent { + readonly dataProvider = inject(MapDataProvider); + + readonly activatedRoute = inject(ActivatedRoute); + forcedFilter: SCSearchFilter = { type: 'boolean', arguments: { @@ -119,11 +123,6 @@ export class MapPageComponent { filter(uid => uid !== undefined), ); - constructor( - readonly dataProvider: MapDataProvider, - readonly activatedRoute: ActivatedRoute, - ) {} - mapMove(event: MapLibreEvent) { const bounds = event.target.getBounds(); this.dataProvider.currentBounds.next([ diff --git a/frontend/app/src/app/modules/map/map-size-fix.directive.ts b/frontend/app/src/app/modules/map/map-size-fix.directive.ts index 20d15b08..5ffc6ab0 100644 --- a/frontend/app/src/app/modules/map/map-size-fix.directive.ts +++ b/frontend/app/src/app/modules/map/map-size-fix.directive.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Directive, Host, HostBinding, HostListener, ViewContainerRef} from '@angular/core'; +import {AfterViewInit, Directive, HostBinding, HostListener, ViewContainerRef, inject} from '@angular/core'; import {MapComponent} from '@maplibre/ngx-maplibre-gl'; /** @@ -10,15 +10,14 @@ import {MapComponent} from '@maplibre/ngx-maplibre-gl'; standalone: true, }) export class MapSizeFixDirective implements AfterViewInit { + private map = inject(MapComponent, {host: true}); + + private viewContainerRef = inject(ViewContainerRef); + private animation: Animation; @HostBinding('class.ready') ready = false; - constructor( - @Host() private map: MapComponent, - private viewContainerRef: ViewContainerRef, - ) {} - @HostListener('mapLoad') mapLoad() { this.map.mapInstance.resize(); diff --git a/frontend/app/src/app/modules/menu/context/context-menu-modal.component.ts b/frontend/app/src/app/modules/menu/context/context-menu-modal.component.ts index 750c7695..3b1eafb9 100644 --- a/frontend/app/src/app/modules/menu/context/context-menu-modal.component.ts +++ b/frontend/app/src/app/modules/menu/context/context-menu-modal.component.ts @@ -18,7 +18,7 @@ import {ContextMenuService} from './context-menu.service'; import {FilterContext, FilterFacet, SortContext, SortContextOption} from './context-type.js'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; import {ModalController} from '@ionic/angular/standalone'; -import {Component, Input, OnInit, OnDestroy} from '@angular/core'; +import {Component, Input, OnInit, OnDestroy, inject} from '@angular/core'; import {Subject, takeUntil} from 'rxjs'; @Component({ @@ -27,6 +27,10 @@ import {Subject, takeUntil} from 'rxjs'; standalone: false, }) export class ContextMenuModalComponent implements OnInit, OnDestroy { + private translateService = inject(TranslateService); + + private readonly modalController = inject(ModalController); + @Input() contextMenuService: ContextMenuService; compactFilterOptionCount = 5; @@ -44,10 +48,7 @@ export class ContextMenuModalComponent implements OnInit, OnDestroy { // Using a subject to manage subscriptions for clean-up private readonly destroy$ = new Subject(); - constructor( - private translateService: TranslateService, - private readonly modalController: ModalController, - ) { + constructor() { this.language = this.translateService.currentLang as keyof SCTranslations; this.translator = new SCThingTranslator(this.language); diff --git a/frontend/app/src/app/modules/menu/context/context-menu.service.ts b/frontend/app/src/app/modules/menu/context/context-menu.service.ts index e124df9c..31007860 100644 --- a/frontend/app/src/app/modules/menu/context/context-menu.service.ts +++ b/frontend/app/src/app/modules/menu/context/context-menu.service.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import { SCFacet, SCSearchFilter, @@ -32,6 +32,10 @@ import {transformFacets} from './facet-filter'; */ @Injectable() export class ContextMenuService { + private readonly translate = inject(TranslateService); + + private readonly thingTranslate = inject(ThingTranslateService); + /** * Local filter context object */ @@ -82,11 +86,6 @@ export class ContextMenuService { */ sortQueryChanged$ = this.sortQuery.asObservable(); - constructor( - private readonly translate: TranslateService, - private readonly thingTranslate: ThingTranslateService, - ) {} - /** * Returns SCSearchFilter if filterContext value is set, undefined otherwise * @param filterContext FilterContext to build SCSearchFilter from diff --git a/frontend/app/src/app/modules/menu/navigation/navigation.component.ts b/frontend/app/src/app/modules/menu/navigation/navigation.component.ts index 74ccfdc1..f7d8aeb5 100644 --- a/frontend/app/src/app/modules/menu/navigation/navigation.component.ts +++ b/frontend/app/src/app/modules/menu/navigation/navigation.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, inject} from '@angular/core'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; import { SCAppConfigurationMenuCategory, @@ -38,6 +38,14 @@ import {BreakpointObserver} from '@angular/cdk/layout'; standalone: false, }) export class NavigationComponent implements OnInit { + translateService = inject(TranslateService); + + private navigationService = inject(NavigationService); + + private settingsProvider = inject(SettingsProvider); + + private responsive = inject(BreakpointObserver); + showTabbar = true; /** @@ -60,12 +68,9 @@ export class NavigationComponent implements OnInit { */ translator: SCThingTranslator; - constructor( - public translateService: TranslateService, - private navigationService: NavigationService, - private settingsProvider: SettingsProvider, - private responsive: BreakpointObserver, - ) { + constructor() { + const translateService = this.translateService; + translateService.onLangChange.subscribe((event: LangChangeEvent) => { this.language = event.lang as keyof SCTranslations; this.translator = new SCThingTranslator(this.language); diff --git a/frontend/app/src/app/modules/menu/navigation/navigation.service.ts b/frontend/app/src/app/modules/menu/navigation/navigation.service.ts index 6dbcc490..a6f17aff 100644 --- a/frontend/app/src/app/modules/menu/navigation/navigation.service.ts +++ b/frontend/app/src/app/modules/menu/navigation/navigation.service.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {SCAppConfigurationMenuCategory} from '@openstapps/core'; import {ConfigProvider} from '../../config/config.provider'; import {NGXLogger} from 'ngx-logger'; @@ -22,10 +22,9 @@ import {NGXLogger} from 'ngx-logger'; providedIn: 'root', }) export class NavigationService { - constructor( - private configProvider: ConfigProvider, - private logger: NGXLogger, - ) {} + private configProvider = inject(ConfigProvider); + + private logger = inject(NGXLogger); async getMenu() { let menu: SCAppConfigurationMenuCategory[] = []; diff --git a/frontend/app/src/app/modules/menu/navigation/offline-notice.component.ts b/frontend/app/src/app/modules/menu/navigation/offline-notice.component.ts index 90a470d2..0d6e4b3a 100644 --- a/frontend/app/src/app/modules/menu/navigation/offline-notice.component.ts +++ b/frontend/app/src/app/modules/menu/navigation/offline-notice.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, ElementRef, HostBinding, ViewChild} from '@angular/core'; +import {Component, ElementRef, HostBinding, ViewChild, inject} from '@angular/core'; import {InternetConnectionService} from '../../../util/internet-connection.service'; import {Router} from '@angular/router'; import {NGXLogger} from 'ngx-logger'; @@ -25,17 +25,19 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class OfflineNoticeComponent { + readonly offlineProvider = inject(InternetConnectionService); + + readonly router = inject(Router); + + readonly logger = inject(NGXLogger); + @HostBinding('class.is-offline') isOffline = false; @HostBinding('class.has-error') hasError = false; @ViewChild('spinIcon', {read: ElementRef}) spinIcon: ElementRef; - constructor( - readonly offlineProvider: InternetConnectionService, - readonly router: Router, - readonly logger: NGXLogger, - ) { + constructor() { this.offlineProvider.offline$.pipe(takeUntilDestroyed()).subscribe(isOffline => { this.isOffline = isOffline; }); diff --git a/frontend/app/src/app/modules/menu/navigation/root-link.directive.ts b/frontend/app/src/app/modules/menu/navigation/root-link.directive.ts index 70a0d693..3dd40856 100644 --- a/frontend/app/src/app/modules/menu/navigation/root-link.directive.ts +++ b/frontend/app/src/app/modules/menu/navigation/root-link.directive.ts @@ -23,6 +23,16 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class RootLinkDirective implements OnInit { + private element = inject(ElementRef); + + private renderer = inject(Renderer2); + + private navController = inject(NavController); + + private router = inject(Router); + + private animationController = inject(AnimationController); + @Input() rootLink: string; @Input() redirectedFrom: string; @@ -33,14 +43,6 @@ export class RootLinkDirective implements OnInit { destroy$ = inject(DestroyRef); - constructor( - private element: ElementRef, - private renderer: Renderer2, - private navController: NavController, - private router: Router, - private animationController: AnimationController, - ) {} - ngOnInit() { const animation = tabsTransition(this.animationController); this.renderer.setAttribute(this.element.nativeElement, 'button', ''); diff --git a/frontend/app/src/app/modules/menu/navigation/tabs.component.ts b/frontend/app/src/app/modules/menu/navigation/tabs.component.ts index 9040c071..6d4514c3 100644 --- a/frontend/app/src/app/modules/menu/navigation/tabs.component.ts +++ b/frontend/app/src/app/modules/menu/navigation/tabs.component.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Component} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {NavigationEnd, Router} from '@angular/router'; import { SCAppConfigurationMenuCategory, @@ -32,6 +32,14 @@ import {NGXLogger} from 'ngx-logger'; standalone: false, }) export class TabsComponent { + private readonly configProvider = inject(ConfigProvider); + + translateService = inject(TranslateService); + + private readonly logger = inject(NGXLogger); + + private readonly router = inject(Router); + /** * Possible languages to be used for translation */ @@ -52,12 +60,10 @@ export class TabsComponent { */ selectedTab: string; - constructor( - private readonly configProvider: ConfigProvider, - public translateService: TranslateService, - private readonly logger: NGXLogger, - private readonly router: Router, - ) { + constructor() { + const translateService = this.translateService; + const router = this.router; + this.language = this.translateService.currentLang as keyof SCTranslations; this.translator = new SCThingTranslator(this.language); void this.loadMenuEntries(); diff --git a/frontend/app/src/app/modules/news/news.provider.ts b/frontend/app/src/app/modules/news/news.provider.ts index dfe970e2..67c42762 100644 --- a/frontend/app/src/app/modules/news/news.provider.ts +++ b/frontend/app/src/app/modules/news/news.provider.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import { SCBooleanFilterArguments, SCMessage, @@ -37,10 +37,9 @@ import {SettingsProvider} from '../settings/settings.provider'; providedIn: 'root', }) export class NewsProvider { - constructor( - private dataProvider: DataProvider, - private settingsProvider: SettingsProvider, - ) {} + private dataProvider = inject(DataProvider); + + private settingsProvider = inject(SettingsProvider); async getCurrentSettings(): Promise { const settings: SCSetting[] = []; diff --git a/frontend/app/src/app/modules/news/page/news-page.component.ts b/frontend/app/src/app/modules/news/page/news-page.component.ts index 09a85e6b..ba5c9199 100644 --- a/frontend/app/src/app/modules/news/page/news-page.component.ts +++ b/frontend/app/src/app/modules/news/page/news-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, inject} from '@angular/core'; import {IonRefresher} from '@ionic/angular/standalone'; import {SCMessage, SCSearchFilter, SCSearchValueFilter, SCSetting} from '@openstapps/core'; import {NewsProvider} from '../news.provider'; @@ -27,6 +27,8 @@ import {NewsProvider} from '../news.provider'; standalone: false, }) export class NewsPageComponent implements OnInit { + private newsProvider = inject(NewsProvider); + /** * Thing counter to start query the next page from */ @@ -62,8 +64,6 @@ export class NewsPageComponent implements OnInit { */ filters: SCSearchFilter[]; - constructor(private newsProvider: NewsProvider) {} - /** * Fetch news from the backend */ diff --git a/frontend/app/src/app/modules/profile/id-card.component.ts b/frontend/app/src/app/modules/profile/id-card.component.ts index 074197f8..f8c7a014 100644 --- a/frontend/app/src/app/modules/profile/id-card.component.ts +++ b/frontend/app/src/app/modules/profile/id-card.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectionStrategy, Component, ElementRef, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, ElementRef, Input, inject} from '@angular/core'; import {SCIdCard} from '@openstapps/core'; import {ThingTranslateModule} from '../../translation/thing-translate.module'; import {AsyncPipe, TitleCasePipe} from '@angular/common'; @@ -25,13 +25,13 @@ import {iosDuration, iosEasing, mdDuration, mdEasing} from 'src/app/animation/ea ], }) export class IdCardComponent { - @Input({required: true}) item: SCIdCard; + private modalController = inject(ModalController); - constructor( - private modalController: ModalController, - private animationController: AnimationController, - private elementRef: ElementRef, - ) {} + private animationController = inject(AnimationController); + + private elementRef = inject(ElementRef); + + @Input({required: true}) item: SCIdCard; async presentFullscreen() { const top = await this.modalController.getTop(); diff --git a/frontend/app/src/app/modules/profile/id-cards.component.ts b/frontend/app/src/app/modules/profile/id-cards.component.ts index 6e514491..d14b0215 100644 --- a/frontend/app/src/app/modules/profile/id-cards.component.ts +++ b/frontend/app/src/app/modules/profile/id-cards.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, inject} from '@angular/core'; import {IdCardsProvider} from './id-cards.provider'; import {SCIdCard} from '@openstapps/core'; import {AsyncPipe} from '@angular/common'; @@ -32,7 +32,7 @@ import {IonIconDirective} from 'src/app/util/ion-icon/ion-icon.directive'; imports: [AsyncPipe, ThingTranslateModule, UtilModule, IdCardComponent, TranslateModule, IonIconDirective], }) export class IdCardsComponent { - idCards: Observable = this.idCardsProvider.getIdCards(); + readonly idCardsProvider = inject(IdCardsProvider); - constructor(readonly idCardsProvider: IdCardsProvider) {} + idCards: Observable = this.idCardsProvider.getIdCards(); } diff --git a/frontend/app/src/app/modules/profile/id-cards.provider.ts b/frontend/app/src/app/modules/profile/id-cards.provider.ts index 16d5dae3..1abd0ea6 100644 --- a/frontend/app/src/app/modules/profile/id-cards.provider.ts +++ b/frontend/app/src/app/modules/profile/id-cards.provider.ts @@ -1,4 +1,4 @@ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {SCIdCard, SCThingOriginType, SCThingType, SCUserConfiguration} from '@openstapps/core'; import {from, of, Observable} from 'rxjs'; import {AuthHelperService} from '../auth/auth-helper.service'; @@ -9,12 +9,13 @@ import {EncryptedStorageProvider} from '../storage/encrypted-storage.provider'; @Injectable({providedIn: 'root'}) export class IdCardsProvider { - constructor( - private authHelper: AuthHelperService, - private config: ConfigProvider, - private httpClient: HttpClient, - private encryptedStorageProvider: EncryptedStorageProvider, - ) {} + private authHelper = inject(AuthHelperService); + + private config = inject(ConfigProvider); + + private httpClient = inject(HttpClient); + + private encryptedStorageProvider = inject(EncryptedStorageProvider); getIdCards(): Observable { const feature = this.config.config.app.features.extern?.['idCards']; diff --git a/frontend/app/src/app/modules/profile/id-cards.spec.ts b/frontend/app/src/app/modules/profile/id-cards.spec.ts index a42d2b11..2d752c4a 100644 --- a/frontend/app/src/app/modules/profile/id-cards.spec.ts +++ b/frontend/app/src/app/modules/profile/id-cards.spec.ts @@ -35,7 +35,7 @@ describe('IdCards', () => { }); it('should emit undefined if not logged in', async () => { - const provider = new IdCardsProvider(authHelper, configProvider, httpClient, encryptedStorageProvider); + const provider = new IdCardsProvider(); expect(await firstValueFrom(provider.getIdCards())).toEqual([]); expect(authHelper.getProvider).toHaveBeenCalledTimes(1); }); @@ -44,7 +44,7 @@ describe('IdCards', () => { fakeAuth.isLoggedIn$.next(true); httpClient.get = jasmine.createSpy().and.returnValue(of(['abc'])); fakeAuth.getValidToken = jasmine.createSpy().and.resolveTo({accessToken: 'fake-token'}); - const provider = new IdCardsProvider(authHelper, configProvider, httpClient, encryptedStorageProvider); + const provider = new IdCardsProvider(); expect(await firstValueFrom(provider.getIdCards())).toEqual(['abc' as never]); expect(authHelper.getProvider).toHaveBeenCalledTimes(1); // eslint-disable-next-line unicorn/no-null @@ -57,7 +57,7 @@ describe('IdCards', () => { }); it('should react to logins', async () => { - const provider = new IdCardsProvider(authHelper, configProvider, httpClient, encryptedStorageProvider); + const provider = new IdCardsProvider(); const observable = provider.getIdCards(); expect(await firstValueFrom(observable)).toEqual([]); httpClient.get = jasmine.createSpy().and.returnValue(of(['abc'])); diff --git a/frontend/app/src/app/modules/profile/page/my-courses.component.ts b/frontend/app/src/app/modules/profile/page/my-courses.component.ts index 04ce9a80..510c8d3b 100644 --- a/frontend/app/src/app/modules/profile/page/my-courses.component.ts +++ b/frontend/app/src/app/modules/profile/page/my-courses.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Input, inject} from '@angular/core'; import {mergeMap, ReplaySubject} from 'rxjs'; import {map} from 'rxjs/operators'; import {SCDateSeries, SCISO8601Date} from '@openstapps/core'; @@ -49,6 +49,8 @@ function groupDays(dateSeries: SCDateSeries[], visibleDays: number): MyCoursesGr standalone: false, }) export class MyCoursesComponent { + private scheduleProvider = inject(ScheduleProvider); + /** * The number of days from today to display */ @@ -66,6 +68,4 @@ export class MyCoursesComponent { ), ), ); - - constructor(private scheduleProvider: ScheduleProvider) {} } diff --git a/frontend/app/src/app/modules/profile/page/profile-page.component.ts b/frontend/app/src/app/modules/profile/page/profile-page.component.ts index c69594db..cee601d3 100644 --- a/frontend/app/src/app/modules/profile/page/profile-page.component.ts +++ b/frontend/app/src/app/modules/profile/page/profile-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {AuthHelperService} from '../../auth/auth-helper.service'; import {ActivatedRoute} from '@angular/router'; import {ScheduleProvider} from '../../calendar/schedule.provider'; @@ -25,13 +25,13 @@ import {profilePageSections} from '../../../../config/profile-page-sections'; standalone: false, }) export class ProfilePageComponent { - sections = profilePageSections; + readonly authHelper = inject(AuthHelperService); - constructor( - readonly authHelper: AuthHelperService, - readonly activatedRoute: ActivatedRoute, - readonly scheduleProvider: ScheduleProvider, - ) {} + readonly activatedRoute = inject(ActivatedRoute); + + readonly scheduleProvider = inject(ScheduleProvider); + + sections = profilePageSections; async signIn() { const originPath = this.activatedRoute.snapshot.queryParamMap.get('origin_path'); diff --git a/frontend/app/src/app/modules/schedule/page/calendar-view.component.ts b/frontend/app/src/app/modules/schedule/page/calendar-view.component.ts index fd9cdc6e..356171ab 100644 --- a/frontend/app/src/app/modules/schedule/page/calendar-view.component.ts +++ b/frontend/app/src/app/modules/schedule/page/calendar-view.component.ts @@ -13,13 +13,10 @@ * this program. If not, see . */ import {AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core'; -import {ActivatedRoute} from '@angular/router'; import moment from 'moment'; import {materialFade, materialManualFade, materialSharedAxisX} from '../../../animation/material-motion'; import {ScheduleResponsiveBreakpoint} from './schema/schema'; -import {ScheduleProvider} from '../../calendar/schedule.provider'; import {CalendarComponent} from './components/calendar.component'; -import {CalendarService} from '../../calendar/calendar.service'; import {InfiniteSwiperComponent} from './grid/infinite-swiper.component'; import {IonContent} from '@ionic/angular/standalone'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; @@ -56,12 +53,8 @@ export class CalendarViewComponent extends CalendarComponent implements OnInit, */ moment = moment; - constructor( - activatedRoute: ActivatedRoute, - calendarService: CalendarService, - scheduleProvider: ScheduleProvider, - ) { - super(activatedRoute, calendarService, scheduleProvider); + constructor() { + super(); // This could be done directly on the properties too instead of // here in the constructor, but because of TSLint member ordering, // some properties wouldn't be initialized, and if you disable diff --git a/frontend/app/src/app/modules/schedule/page/components/calendar.component.ts b/frontend/app/src/app/modules/schedule/page/components/calendar.component.ts index 3450b596..81d36a26 100644 --- a/frontend/app/src/app/modules/schedule/page/components/calendar.component.ts +++ b/frontend/app/src/app/modules/schedule/page/components/calendar.component.ts @@ -37,6 +37,12 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class CalendarComponent implements OnInit { + protected readonly activatedRoute = inject(ActivatedRoute); + + protected readonly calendarService = inject(CalendarService); + + protected readonly scheduleProvider = inject(ScheduleProvider); + /** * The day that the schedule started out on */ @@ -103,12 +109,6 @@ export class CalendarComponent implements OnInit { destroy$ = inject(DestroyRef); - constructor( - protected readonly activatedRoute: ActivatedRoute, - protected readonly calendarService: CalendarService, - protected readonly scheduleProvider: ScheduleProvider, - ) {} - ngOnInit() { let dayString: string | number | null = this.activatedRoute.snapshot.paramMap.get('date'); if (dayString == undefined || dayString === 'now') { diff --git a/frontend/app/src/app/modules/schedule/page/grid/schedule-card.component.ts b/frontend/app/src/app/modules/schedule/page/grid/schedule-card.component.ts index dcd6efb7..57955986 100644 --- a/frontend/app/src/app/modules/schedule/page/grid/schedule-card.component.ts +++ b/frontend/app/src/app/modules/schedule/page/grid/schedule-card.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input, OnInit, inject} from '@angular/core'; import moment from 'moment'; import {ScheduleProvider} from '../../../calendar/schedule.provider'; import {ScheduleEvent} from '../schema/schema'; @@ -27,6 +27,8 @@ import {ScheduleEvent} from '../schema/schema'; standalone: false, }) export class ScheduleCardComponent implements OnInit { + private readonly scheduleProvider = inject(ScheduleProvider); + cardColor = { isExercise: false, isLecture: false, @@ -73,8 +75,6 @@ export class ScheduleCardComponent implements OnInit { */ title: string; - constructor(private readonly scheduleProvider: ScheduleProvider) {} - /** * Initializer */ diff --git a/frontend/app/src/app/modules/schedule/page/grid/schedule-day.component.ts b/frontend/app/src/app/modules/schedule/page/grid/schedule-day.component.ts index d012013c..c9de7e90 100644 --- a/frontend/app/src/app/modules/schedule/page/grid/schedule-day.component.ts +++ b/frontend/app/src/app/modules/schedule/page/grid/schedule-day.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, HostListener, Input, OnInit} from '@angular/core'; +import {Component, HostListener, Input, OnInit, inject} from '@angular/core'; import moment from 'moment'; import {Range, ScheduleEvent, ScheduleResponsiveBreakpoint} from '../schema/schema'; import {ScheduleProvider} from '../../../calendar/schedule.provider'; @@ -28,6 +28,8 @@ import {groupRangeOverlaps} from './range-overlap'; standalone: false, }) export class ScheduleDayComponent implements OnInit { + protected readonly scheduleProvider = inject(ScheduleProvider); + @Input() day: moment.Moment; @Input() hoursRange: Range; @@ -59,8 +61,6 @@ export class ScheduleDayComponent implements OnInit { dateFormat = 'dd'; - constructor(protected readonly scheduleProvider: ScheduleProvider) {} - ngOnInit() { this.determineDateFormat(); } diff --git a/frontend/app/src/app/modules/schedule/page/schedule-page.component.ts b/frontend/app/src/app/modules/schedule/page/schedule-page.component.ts index e4cba8bd..23e1b159 100644 --- a/frontend/app/src/app/modules/schedule/page/schedule-page.component.ts +++ b/frontend/app/src/app/modules/schedule/page/schedule-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {AfterViewInit, Component, HostListener, Input, OnInit, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, HostListener, Input, OnInit, ViewChild, inject} from '@angular/core'; import {Location} from '@angular/common'; import {ActivatedRoute, Router} from '@angular/router'; import {AnimationController, IonRouterOutlet} from '@ionic/angular/standalone'; @@ -57,6 +57,18 @@ const responsiveConfig: ScheduleResponsiveBreakpoint[] = [ standalone: false, }) export class SchedulePageComponent implements OnInit, AfterViewInit { + private readonly activatedRoute = inject(ActivatedRoute); + + private calendarService = inject(CalendarService); + + readonly routerOutlet = inject(IonRouterOutlet); + + private router = inject(Router); + + private animationController = inject(AnimationController); + + private location = inject(Location); + /** * Current width of the window */ @@ -108,15 +120,6 @@ export class SchedulePageComponent implements OnInit, AfterViewInit { return responsiveConfig.find(value => width < value.until) ?? responsiveConfig.at(-1)!; } - constructor( - private readonly activatedRoute: ActivatedRoute, - private calendarService: CalendarService, - readonly routerOutlet: IonRouterOutlet, - private router: Router, - private animationController: AnimationController, - private location: Location, - ) {} - ngOnInit() { this.onInit(); } diff --git a/frontend/app/src/app/modules/schedule/page/schedule-single-events.component.ts b/frontend/app/src/app/modules/schedule/page/schedule-single-events.component.ts index 56436690..1211f65b 100644 --- a/frontend/app/src/app/modules/schedule/page/schedule-single-events.component.ts +++ b/frontend/app/src/app/modules/schedule/page/schedule-single-events.component.ts @@ -47,6 +47,8 @@ export interface ScheduleSingleEvent { standalone: false, }) export class ScheduleSingleEventsComponent implements OnInit { + protected readonly scheduleProvider = inject(ScheduleProvider); + /** * The events to display */ @@ -100,8 +102,6 @@ export class ScheduleSingleEventsComponent implements OnInit { .map(([_, value]) => value); } - constructor(protected readonly scheduleProvider: ScheduleProvider) {} - /** * Fetch date series items */ diff --git a/frontend/app/src/app/modules/schedule/page/schedule-view.component.ts b/frontend/app/src/app/modules/schedule/page/schedule-view.component.ts index 40910714..cde69446 100644 --- a/frontend/app/src/app/modules/schedule/page/schedule-view.component.ts +++ b/frontend/app/src/app/modules/schedule/page/schedule-view.component.ts @@ -13,13 +13,10 @@ * this program. If not, see . */ import {AfterViewInit, Component, Input, OnInit, ViewChild} from '@angular/core'; -import {ActivatedRoute} from '@angular/router'; import moment, {Moment} from 'moment'; import {materialFade, materialManualFade, materialSharedAxisX} from '../../../animation/material-motion'; -import {ScheduleProvider} from '../../calendar/schedule.provider'; import {SCISO8601Date, SCUuid} from '@openstapps/core'; import {ScheduleEvent, ScheduleResponsiveBreakpoint} from './schema/schema'; -import {CalendarService} from '../../calendar/calendar.service'; import {CalendarComponent} from './components/calendar.component'; import {IonContent, IonDatetime} from '@ionic/angular/standalone'; import {SwiperComponent} from 'swiper/angular'; @@ -84,12 +81,8 @@ export class ScheduleViewComponent extends CalendarComponent implements OnInit, (_, i) => moment().startOf('week').add(i, 'days'), ); - constructor( - activatedRoute: ActivatedRoute, - calendarService: CalendarService, - scheduleProvider: ScheduleProvider, - ) { - super(activatedRoute, calendarService, scheduleProvider); + constructor() { + super(); const hoursAmount = this.hoursRange.to - this.hoursRange.from + 1; this.hours = [...Array.from({length: hoursAmount}).keys()]; } diff --git a/frontend/app/src/app/modules/settings/in-app-review/in-app-review.provider.ts b/frontend/app/src/app/modules/settings/in-app-review/in-app-review.provider.ts index f50fc1b4..00a87642 100644 --- a/frontend/app/src/app/modules/settings/in-app-review/in-app-review.provider.ts +++ b/frontend/app/src/app/modules/settings/in-app-review/in-app-review.provider.ts @@ -1,4 +1,4 @@ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {InAppReview} from '@capacitor-community/in-app-review'; import {StorageProvider} from '../../storage/storage.provider'; @@ -15,12 +15,14 @@ export type IN_APP_REVIEW_KEYS = typeof IN_APP_REVIEW_SESSIONS_KEY | typeof IN_A */ @Injectable() export class InAppReviewProvider { + private readonly storageProvider = inject(StorageProvider); + requestReview: () => Promise; /** - * @param storageProvider TODO + * */ - constructor(private readonly storageProvider: StorageProvider) { + constructor() { this.requestReview = InAppReview.requestReview; } diff --git a/frontend/app/src/app/modules/settings/item/settings-item.component.ts b/frontend/app/src/app/modules/settings/item/settings-item.component.ts index 54e72d43..45d51e28 100644 --- a/frontend/app/src/app/modules/settings/item/settings-item.component.ts +++ b/frontend/app/src/app/modules/settings/item/settings-item.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input} from '@angular/core'; +import {Component, Input, inject} from '@angular/core'; import {AlertController} from '@ionic/angular/standalone'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; import {SCLanguageCode, SCSetting, SCSettingValue, SCSettingValues} from '@openstapps/core'; @@ -28,6 +28,12 @@ import {SettingsProvider} from '../settings.provider'; standalone: false, }) export class SettingsItemComponent { + private readonly alertCtrl = inject(AlertController); + + private readonly translateService = inject(TranslateService); + + private readonly settingsProvider = inject(SettingsProvider); + /** * If set the setting will be shown as compact view */ @@ -45,15 +51,10 @@ export class SettingsItemComponent { /** * - * @param alertCtrl AlertController - * @param translateService TranslateService - * @param settingsProvider SettingProvider */ - constructor( - private readonly alertCtrl: AlertController, - private readonly translateService: TranslateService, - private readonly settingsProvider: SettingsProvider, - ) { + constructor() { + const translateService = this.translateService; + translateService.onLangChange.subscribe((_event: LangChangeEvent) => { this.isVisible = false; // TODO: Issue #53 check workaround for selected 'select option' not updating translation diff --git a/frontend/app/src/app/modules/settings/page/calendar-sync-settings.component.ts b/frontend/app/src/app/modules/settings/page/calendar-sync-settings.component.ts index 0448e972..8da7f5be 100644 --- a/frontend/app/src/app/modules/settings/page/calendar-sync-settings.component.ts +++ b/frontend/app/src/app/modules/settings/page/calendar-sync-settings.component.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Component, OnInit} from '@angular/core'; +import {Component, OnInit, inject} from '@angular/core'; import {AddEventReviewModalComponent} from '../../calendar/add-event-review-modal.component'; import {ModalController} from '@ionic/angular/standalone'; import {ScheduleProvider} from '../../calendar/schedule.provider'; @@ -43,22 +43,26 @@ import { standalone: false, }) export class CalendarSyncSettingsComponent implements OnInit { + readonly modalController = inject(ModalController); + + readonly scheduleProvider = inject(ScheduleProvider); + + readonly translator = inject(TranslateService); + + readonly thingTranslator = inject(ThingTranslateService); + + readonly storageProvider = inject(StorageProvider); + + readonly scheduleSyncService = inject(ScheduleSyncService); + + readonly calendarService = inject(CalendarService); + isWeb = true; syncEnabled = false; notificationsEnabled = false; - constructor( - readonly modalController: ModalController, - readonly scheduleProvider: ScheduleProvider, - readonly translator: TranslateService, - readonly thingTranslator: ThingTranslateService, - readonly storageProvider: StorageProvider, - readonly scheduleSyncService: ScheduleSyncService, - readonly calendarService: CalendarService, - ) {} - ngOnInit() { Device.getInfo().then(it => { this.isWeb = it.platform === 'web'; diff --git a/frontend/app/src/app/modules/settings/page/settings-page.component.ts b/frontend/app/src/app/modules/settings/page/settings-page.component.ts index 64e6bd00..182e7a5d 100644 --- a/frontend/app/src/app/modules/settings/page/settings-page.component.ts +++ b/frontend/app/src/app/modules/settings/page/settings-page.component.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {ChangeDetectorRef, Component, OnInit} from '@angular/core'; +import {ChangeDetectorRef, Component, OnInit, inject} from '@angular/core'; import {AlertController, ToastController} from '@ionic/angular/standalone'; import {TranslateService} from '@ngx-translate/core'; import {SCSettingMeta} from '@openstapps/core'; @@ -28,6 +28,16 @@ import {SettingsCache, SettingsProvider} from '../settings.provider'; standalone: false, }) export class SettingsPageComponent implements OnInit { + private readonly alertController = inject(AlertController); + + private readonly settingsProvider = inject(SettingsProvider); + + private readonly toastController = inject(ToastController); + + private readonly translateService = inject(TranslateService); + + private readonly changeDetectorRef = inject(ChangeDetectorRef); + /** * Order of the categories */ @@ -50,19 +60,8 @@ export class SettingsPageComponent implements OnInit { /** * - * @param alertController AlertController - * @param settingsProvider SettingsProvider - * @param toastController ToastController - * @param translateService TranslateService - * @param changeDetectorRef ChangeDetectorRef */ - constructor( - private readonly alertController: AlertController, - private readonly settingsProvider: SettingsProvider, - private readonly toastController: ToastController, - private readonly translateService: TranslateService, - private readonly changeDetectorRef: ChangeDetectorRef, - ) { + constructor() { this.settingsCache = {}; } diff --git a/frontend/app/src/app/modules/settings/setting-translate.pipe.ts b/frontend/app/src/app/modules/settings/setting-translate.pipe.ts index f7f5a730..547a1cc2 100644 --- a/frontend/app/src/app/modules/settings/setting-translate.pipe.ts +++ b/frontend/app/src/app/modules/settings/setting-translate.pipe.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Pipe, PipeTransform} from '@angular/core'; +import {Pipe, PipeTransform, inject} from '@angular/core'; import {TranslateService} from '@ngx-translate/core'; import {SCSetting} from '@openstapps/core'; import {ThingTranslatePipe} from '../../translation/thing-translate.pipe'; @@ -28,13 +28,12 @@ import {ThingTranslateService} from '../../translation/thing-translate.service'; standalone: false, }) export class SettingTranslatePipe implements PipeTransform { - constructor( - private readonly translate: TranslateService, - private readonly thingTranslate: ThingTranslateService, - ) {} + private readonly translate = inject(TranslateService); + + private readonly thingTranslate = inject(ThingTranslateService); transform(setting: SCSetting): string | undefined { - const thingTranslatePipe = new ThingTranslatePipe(this.translate, this.thingTranslate); + const thingTranslatePipe = new ThingTranslatePipe(); const translatedSettingValues = thingTranslatePipe.transform('values', setting); return translatedSettingValues diff --git a/frontend/app/src/app/modules/settings/settings.provider.ts b/frontend/app/src/app/modules/settings/settings.provider.ts index 67c952c8..23f29f46 100644 --- a/frontend/app/src/app/modules/settings/settings.provider.ts +++ b/frontend/app/src/app/modules/settings/settings.provider.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {SCSetting, SCSettingValue, SCSettingValues} from '@openstapps/core'; import deepMerge from 'deepmerge'; import {Subject} from 'rxjs'; @@ -91,6 +91,10 @@ export interface SettingsAction { */ @Injectable() export class SettingsProvider { + private readonly storage = inject(StorageProvider); + + private readonly configProvider = inject(ConfigProvider); + /** * Source of settings actions */ @@ -192,15 +196,7 @@ export class SettingsProvider { return isValueValid; } - /** - * - * @param storage TODO - * @param configProvider TODO - */ - constructor( - private readonly storage: StorageProvider, - private readonly configProvider: ConfigProvider, - ) { + constructor() { this.categoriesOrder = []; this.settingsCache = {}; } diff --git a/frontend/app/src/app/modules/storage/encrypted-storage.provider.ts b/frontend/app/src/app/modules/storage/encrypted-storage.provider.ts index 7a88e592..5ee6e27a 100644 --- a/frontend/app/src/app/modules/storage/encrypted-storage.provider.ts +++ b/frontend/app/src/app/modules/storage/encrypted-storage.provider.ts @@ -1,11 +1,11 @@ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {StorageProvider} from './storage.provider'; import {Capacitor} from '@capacitor/core'; import {SecureStoragePlugin} from 'capacitor-secure-storage-plugin'; @Injectable({providedIn: 'root'}) export class EncryptedStorageProvider { - constructor(private storageProvider: StorageProvider) {} + private storageProvider = inject(StorageProvider); /** * Retrieve a large value from an encrypted storage diff --git a/frontend/app/src/app/modules/storage/storage.provider.ts b/frontend/app/src/app/modules/storage/storage.provider.ts index c5a19a37..23d835ae 100644 --- a/frontend/app/src/app/modules/storage/storage.provider.ts +++ b/frontend/app/src/app/modules/storage/storage.provider.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {Storage} from '@ionic/storage-angular'; /** @@ -20,10 +20,7 @@ import {Storage} from '@ionic/storage-angular'; */ @Injectable() export class StorageProvider { - /** - * @param storage TODO - */ - constructor(private readonly storage: Storage) {} + private readonly storage = inject(Storage); /** * Deletes storage entries using keys used to save them diff --git a/frontend/app/src/app/translation/common-string-pipes.ts b/frontend/app/src/app/translation/common-string-pipes.ts index 9af908ee..8ac8011b 100644 --- a/frontend/app/src/app/translation/common-string-pipes.ts +++ b/frontend/app/src/app/translation/common-string-pipes.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core'; +import {Injectable, OnDestroy, Pipe, PipeTransform, inject} from '@angular/core'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; import moment from 'moment'; import {Subscription} from 'rxjs'; @@ -121,6 +121,8 @@ export class StringSplitPipe implements PipeTransform { standalone: false, }) export class DurationLocalizedPipe implements PipeTransform, OnDestroy { + private readonly translate = inject(TranslateService); + locale: string; onLangChange?: Subscription; @@ -137,7 +139,9 @@ export class DurationLocalizedPipe implements PipeTransform, OnDestroy { ru: 'kаждые', }; - constructor(private readonly translate: TranslateService) { + constructor() { + const translate = this.translate; + this.locale = translate.currentLang; } @@ -196,13 +200,17 @@ export class DurationLocalizedPipe implements PipeTransform, OnDestroy { standalone: false, }) export class MetersLocalizedPipe implements PipeTransform, OnDestroy { + private readonly translate = inject(TranslateService); + locale: string; onLangChange?: Subscription; value = ''; - constructor(private readonly translate: TranslateService) { + constructor() { + const translate = this.translate; + this.locale = translate.currentLang; } @@ -292,13 +300,17 @@ export class IsNumericPipe implements PipeTransform { standalone: false, }) export class NumberLocalizedPipe implements PipeTransform, OnDestroy { + private readonly translate = inject(TranslateService); + locale: string; onLangChange?: Subscription; value: string; - constructor(private readonly translate: TranslateService) { + constructor() { + const translate = this.translate; + this.locale = translate.currentLang; } @@ -358,13 +370,17 @@ export class NumberLocalizedPipe implements PipeTransform, OnDestroy { standalone: false, }) export class DateLocalizedFormatPipe implements PipeTransform, OnDestroy { + private readonly translate = inject(TranslateService); + locale: string; onLangChange?: Subscription; value: string; - constructor(private readonly translate: TranslateService) { + constructor() { + const translate = this.translate; + this.locale = translate.currentLang; } diff --git a/frontend/app/src/app/translation/property-name-translate.pipe.ts b/frontend/app/src/app/translation/property-name-translate.pipe.ts index 80ac50f5..f7a991a5 100644 --- a/frontend/app/src/app/translation/property-name-translate.pipe.ts +++ b/frontend/app/src/app/translation/property-name-translate.pipe.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core'; +import {Injectable, OnDestroy, Pipe, PipeTransform, inject} from '@angular/core'; import {Subscription} from 'rxjs'; import {TranslateService} from '@ngx-translate/core'; import {ThingTranslateService} from './thing-translate.service'; @@ -26,6 +26,10 @@ import {logger} from '../_helpers/ts-logger'; standalone: false, }) export class PropertyNameTranslatePipe implements PipeTransform, OnDestroy { + private readonly translate = inject(TranslateService); + + private readonly thingTranslate = inject(ThingTranslateService); + value: unknown; lastKey?: string; @@ -34,11 +38,6 @@ export class PropertyNameTranslatePipe implements PipeTransform, OnDestroy { onLangChange: Subscription; - constructor( - private readonly translate: TranslateService, - private readonly thingTranslate: ThingTranslateService, - ) {} - updateValue(key: string, type: string): void { this.value = this.thingTranslate.getPropertyName(type as SCThingType, key); } diff --git a/frontend/app/src/app/translation/thing-translate.pipe.ts b/frontend/app/src/app/translation/thing-translate.pipe.ts index 44a1ceab..3298499b 100644 --- a/frontend/app/src/app/translation/thing-translate.pipe.ts +++ b/frontend/app/src/app/translation/thing-translate.pipe.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable, OnDestroy, Pipe, PipeTransform} from '@angular/core'; +import {Injectable, OnDestroy, Pipe, PipeTransform, inject} from '@angular/core'; import {TranslateService} from '@ngx-translate/core'; import {isThing, SCThings, SCThingWithoutReferences} from '@openstapps/core'; import {Subscription} from 'rxjs'; @@ -26,6 +26,10 @@ import {logger} from '../_helpers/ts-logger'; standalone: false, }) export class ThingTranslatePipe implements PipeTransform, OnDestroy { + private readonly translate = inject(TranslateService); + + private readonly thingTranslate = inject(ThingTranslateService); + value: unknown; lastKey?: string; @@ -34,12 +38,6 @@ export class ThingTranslatePipe implements PipeTransform, OnDestroy { onLangChange: Subscription; - constructor( - private readonly translate: TranslateService, - // private readonly _ref: ChangeDetectorRef, - private readonly thingTranslate: ThingTranslateService, - ) {} - updateValue(key: string, thing: SCThingWithoutReferences): void { this.value = this.thingTranslate.get(thing as SCThings, key); } diff --git a/frontend/app/src/app/translation/thing-translate.service.ts b/frontend/app/src/app/translation/thing-translate.service.ts index cf1122c9..10fcaf45 100644 --- a/frontend/app/src/app/translation/thing-translate.service.ts +++ b/frontend/app/src/app/translation/thing-translate.service.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {LangChangeEvent, TranslateService} from '@ngx-translate/core'; import { SCLanguage, @@ -37,19 +37,26 @@ import {getDateFnsLocale} from './dfns-locale'; providedIn: 'root', }) export class ThingTranslateService { - translator: SCThingTranslator; + /** + * translateService Instance of Angular TranslateService + */ + private readonly translateService = inject(TranslateService); /** - * - * @param translateService Instance of Angular TranslateService - * @param parser An instance of the parser currently used - * @param dfnsConfiguration the date fns configuration + * parser An instance of the parser currently used */ - constructor( - private readonly translateService: TranslateService, - public parser: ThingTranslateParser, - private dfnsConfiguration: DateFnsConfigurationService, - ) { + parser = inject(ThingTranslateParser); + + /** + * dfnsConfiguration the date fns configuration + */ + private dfnsConfiguration = inject(DateFnsConfigurationService); + + translator: SCThingTranslator; + + constructor() { + const translateService = this.translateService; + this.translator = new SCThingTranslator( (translateService.currentLang ?? translateService.defaultLang) as SCLanguageCode, ); diff --git a/frontend/app/src/app/translation/translate-simple.pipe.ts b/frontend/app/src/app/translation/translate-simple.pipe.ts index b44433e4..5086203a 100644 --- a/frontend/app/src/app/translation/translate-simple.pipe.ts +++ b/frontend/app/src/app/translation/translate-simple.pipe.ts @@ -25,6 +25,8 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; standalone: false, }) export class TranslateSimplePipe implements PipeTransform { + private readonly translate = inject(TranslateService); + value: unknown; query: unknown; @@ -35,8 +37,6 @@ export class TranslateSimplePipe implements PipeTransform { destroy$ = inject(DestroyRef); - constructor(private readonly translate: TranslateService) {} - // eslint-disable-next-line @typescript-eslint/ban-types private updateValue() { try { diff --git a/frontend/app/src/app/util/edit-modal.component.ts b/frontend/app/src/app/util/edit-modal.component.ts index ac95ea75..facae661 100644 --- a/frontend/app/src/app/util/edit-modal.component.ts +++ b/frontend/app/src/app/util/edit-modal.component.ts @@ -13,7 +13,16 @@ * this program. If not, see . */ -import {Component, ContentChild, EventEmitter, Input, Output, TemplateRef, ViewChild} from '@angular/core'; +import { + Component, + ContentChild, + EventEmitter, + Input, + Output, + TemplateRef, + ViewChild, + inject, +} from '@angular/core'; import { ActionSheetController, AlertController, @@ -31,6 +40,18 @@ import {TranslatePipe} from '@ngx-translate/core'; standalone: false, }) export class EditModalComponent { + readonly modalController = inject(ModalController); + + readonly routerOutlet = inject(IonRouterOutlet); + + readonly alertController = inject(AlertController); + + readonly actionSheetController = inject(ActionSheetController); + + readonly translatePipe = inject(TranslatePipe); + + readonly config = inject(Config); + @ContentChild(TemplateRef) content: TemplateRef; @ViewChild('modal') modal: IonModal; @@ -39,15 +60,6 @@ export class EditModalComponent { @Output() save = new EventEmitter(); - constructor( - readonly modalController: ModalController, - readonly routerOutlet: IonRouterOutlet, - readonly alertController: AlertController, - readonly actionSheetController: ActionSheetController, - readonly translatePipe: TranslatePipe, - readonly config: Config, - ) {} - present() { this.modal.present(); this.pendingChanges = false; diff --git a/frontend/app/src/app/util/element-size-change.directive.ts b/frontend/app/src/app/util/element-size-change.directive.ts index 27ab77e9..404eb5f7 100644 --- a/frontend/app/src/app/util/element-size-change.directive.ts +++ b/frontend/app/src/app/util/element-size-change.directive.ts @@ -13,13 +13,15 @@ * this program. If not, see . */ -import {Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core'; +import {Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, inject} from '@angular/core'; @Directive({ selector: '[elementSizeChange]', standalone: false, }) export class ElementSizeChangeDirective implements OnInit, OnDestroy { + private elementRef = inject(ElementRef); + @Output() elementSizeChange = new EventEmitter(); @@ -29,8 +31,6 @@ export class ElementSizeChangeDirective implements OnInit, OnDestroy { private resizeObserver: ResizeObserver; - constructor(private elementRef: ElementRef) {} - ngOnInit() { this.resizeObserver = new ResizeObserver(elements => { const stamp = Date.now(); diff --git a/frontend/app/src/app/util/full-screen-image.directive.ts b/frontend/app/src/app/util/full-screen-image.directive.ts index b4b67e26..98d59496 100644 --- a/frontend/app/src/app/util/full-screen-image.directive.ts +++ b/frontend/app/src/app/util/full-screen-image.directive.ts @@ -1,11 +1,13 @@ -import {Directive, ElementRef, HostListener} from '@angular/core'; +import {Directive, ElementRef, HostListener, inject} from '@angular/core'; @Directive({ selector: 'img[fullScreenImage]', standalone: true, }) export class FullScreenImageDirective { - constructor(private host: ElementRef) {} + private host = inject(ElementRef); + + constructor() {} @HostListener('click') async onClick() { diff --git a/frontend/app/src/app/util/internet-connection.service.ts b/frontend/app/src/app/util/internet-connection.service.ts index 63345224..d8d15ef2 100644 --- a/frontend/app/src/app/util/internet-connection.service.ts +++ b/frontend/app/src/app/util/internet-connection.service.ts @@ -24,7 +24,7 @@ import { Subject, takeUntil, } from 'rxjs'; -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {filter, map, startWith, take, tap} from 'rxjs/operators'; import {NGXLogger} from 'ngx-logger'; import {Router} from '@angular/router'; @@ -33,6 +33,10 @@ import {Router} from '@angular/router'; providedIn: 'root', }) export class InternetConnectionService { + private readonly logger = inject(NGXLogger); + + private readonly router = inject(Router); + private readonly manualRetry$ = new Subject(); private readonly abortRetry$ = new Subject(); @@ -101,11 +105,6 @@ export class InternetConnectionService { private readonly errors = new Set(); - constructor( - private readonly logger: NGXLogger, - private readonly router: Router, - ) {} - /** * Retry all failed http requests */ diff --git a/frontend/app/src/app/util/ion-content-parallax.directive.ts b/frontend/app/src/app/util/ion-content-parallax.directive.ts index b4e8c39f..f16f9509 100644 --- a/frontend/app/src/app/util/ion-content-parallax.directive.ts +++ b/frontend/app/src/app/util/ion-content-parallax.directive.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Directive, ElementRef, HostBinding, Input, OnDestroy, OnInit} from '@angular/core'; +import {Directive, ElementRef, HostBinding, Input, OnDestroy, OnInit, inject} from '@angular/core'; import {waitForElement} from './ion-icon/shadow-attacher'; type IonicColor = @@ -76,6 +76,8 @@ type IonicColor = standalone: false, }) export class IonContentParallaxDirective implements OnInit, OnDestroy { + private element = inject(ElementRef); + @HostBinding('style.--parallax-content-size.px') @Input() parallaxSize = 230; @Input() set parallaxColor(value: IonicColor) { @@ -86,8 +88,6 @@ export class IonContentParallaxDirective implements OnInit, OnDestroy { private mutationObserver: MutationObserver; - constructor(private element: ElementRef) {} - async ngOnInit() { this.mutationObserver = new MutationObserver(this.replace.bind(this)); const element = this.element.nativeElement; diff --git a/frontend/app/src/app/util/ion-icon/ion-icon.directive.ts b/frontend/app/src/app/util/ion-icon/ion-icon.directive.ts index f47dd774..0f36e40b 100644 --- a/frontend/app/src/app/util/ion-icon/ion-icon.directive.ts +++ b/frontend/app/src/app/util/ion-icon/ion-icon.directive.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {Directive, ElementRef, Input} from '@angular/core'; +import {Directive, ElementRef, Input, inject} from '@angular/core'; import {IonIconCustomElement} from './ion-icon-custom-component'; @Directive({ @@ -21,6 +21,8 @@ import {IonIconCustomElement} from './ion-icon-custom-component'; standalone: true, }) export class IonIconDirective { + private elementRef = inject>(ElementRef); + @Input({required: true}) set name(value: IonIconCustomElement['name']) { this.elementRef.nativeElement.name = value; } @@ -44,6 +46,4 @@ export class IonIconDirective { @Input() set grade(value: IonIconCustomElement['grade']) { this.elementRef.nativeElement.grade = value; } - - constructor(private elementRef: ElementRef) {} } diff --git a/frontend/app/src/app/util/lazy.pipe.ts b/frontend/app/src/app/util/lazy.pipe.ts index 2852e141..354be726 100644 --- a/frontend/app/src/app/util/lazy.pipe.ts +++ b/frontend/app/src/app/util/lazy.pipe.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ import {Observable} from 'rxjs'; -import {Pipe, PipeTransform} from '@angular/core'; +import {Pipe, PipeTransform, inject} from '@angular/core'; import {SCSaveableThing, SCThings, SCUuid} from '@openstapps/core'; import {DataProvider, DataScope} from '../modules/data/data.provider'; import {get} from '@openstapps/collection-utils'; @@ -24,7 +24,7 @@ import {get} from '@openstapps/collection-utils'; standalone: false, }) export class LazyPipe implements PipeTransform { - constructor(private readonly dataProvider: DataProvider) {} + private readonly dataProvider = inject(DataProvider); transform( uid: SCUuid, diff --git a/frontend/app/src/app/util/routing-stack.service.ts b/frontend/app/src/app/util/routing-stack.service.ts index 952d9bd7..6fa4821f 100644 --- a/frontend/app/src/app/util/routing-stack.service.ts +++ b/frontend/app/src/app/util/routing-stack.service.ts @@ -12,7 +12,7 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {NavigationEnd, Router} from '@angular/router'; import {SCSaveableThing, SCThings} from '@openstapps/core'; @@ -20,6 +20,8 @@ import {SCSaveableThing, SCThings} from '@openstapps/core'; providedIn: 'root', }) export class RoutingStackService { + private router = inject(Router); + currentRoute: string; currentDataDetail?: Promise; @@ -28,7 +30,7 @@ export class RoutingStackService { lastDataDetail?: Promise; - constructor(private router: Router) { + constructor() { this.router.events.subscribe(event => { if (event instanceof NavigationEnd) { this.lastRoute = this.currentRoute; diff --git a/frontend/app/src/app/util/searchbar-autofocus.directive.ts b/frontend/app/src/app/util/searchbar-autofocus.directive.ts index 9ccbfe87..ad2a1f4c 100644 --- a/frontend/app/src/app/util/searchbar-autofocus.directive.ts +++ b/frontend/app/src/app/util/searchbar-autofocus.directive.ts @@ -13,7 +13,7 @@ * this program. If not, see . */ -import {AfterViewInit, Directive, ElementRef, Input} from '@angular/core'; +import {AfterViewInit, Directive, ElementRef, Input, inject} from '@angular/core'; import {IonSearchbar} from '@ionic/angular/standalone'; @Directive({ @@ -21,9 +21,9 @@ import {IonSearchbar} from '@ionic/angular/standalone'; standalone: false, }) export class SearchbarAutofocusDirective implements AfterViewInit { - @Input() autofocus = true; + private element = inject(ElementRef); - constructor(private element: ElementRef) {} + @Input() autofocus = true; ngAfterViewInit() { if (!this.autofocus) return; diff --git a/frontend/app/src/app/util/section.component.ts b/frontend/app/src/app/util/section.component.ts index 29bf3469..d80b3915 100644 --- a/frontend/app/src/app/util/section.component.ts +++ b/frontend/app/src/app/util/section.component.ts @@ -12,7 +12,14 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {AfterContentInit, ChangeDetectionStrategy, Component, Input, ViewContainerRef} from '@angular/core'; +import { + AfterContentInit, + ChangeDetectionStrategy, + Component, + Input, + ViewContainerRef, + inject, +} from '@angular/core'; import {SCThings} from '@openstapps/core'; import {fromMutationObserver} from './rxjs/mutation-observer'; import {combineLatestWith, mergeMap, OperatorFunction, ReplaySubject, takeLast} from 'rxjs'; @@ -45,6 +52,8 @@ function isSlideVisible( standalone: false, }) export class SectionComponent implements AfterContentInit { + readonly viewContainerRef = inject(ViewContainerRef); + @Input() title = ''; @Input() item?: SCThings; @@ -109,8 +118,6 @@ export class SectionComponent implements AfterContentInit { map(([multipleSlides, firstVisible, lastVisible]) => multipleSlides && !(firstVisible && lastVisible)), ); - constructor(readonly viewContainerRef: ViewContainerRef) {} - ngAfterContentInit() { this.nativeElement.next(this.viewContainerRef.element.nativeElement); this.nativeElement.complete();