/* * Copyright (C) 2022 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ import {Component, OnInit} from '@angular/core'; import {AddEventReviewModalComponent} from '../../calendar/add-event-review-modal.component'; import {ModalController} from '@ionic/angular'; import {ScheduleProvider} from '../../calendar/schedule.provider'; import {Directory, Encoding, Filesystem} from '@capacitor/filesystem'; import {Share} from '@capacitor/share'; import {Device} from '@capacitor/device'; import {Dialog} from '@capacitor/dialog'; import {SCUuid} from '@openstapps/core'; import {TranslateService} from '@ngx-translate/core'; import {StorageProvider} from '../../storage/storage.provider'; import {ScheduleSyncService} from '../../background/schedule/schedule-sync.service'; import {CalendarService} from '../../calendar/calendar.service'; import {getNativeCalendarExport} from '../../calendar/ical/ical'; import {ThingTranslateService} from '../../../translation/thing-translate.service'; import { CALENDAR_NOTIFICATIONS_ENABLED_KEY, CALENDAR_SYNC_ENABLED_KEY, CALENDAR_SYNC_KEYS, calendarSettingStorageKey, getCalendarSetting, } from './calendar-sync-settings-keys'; @Component({ selector: 'calendar-sync-settings', templateUrl: 'calendar-sync-settings.html', styleUrls: ['calendar-sync-settings.scss'], }) export class CalendarSyncSettingsComponent implements OnInit { 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'; }); this.getSetting(CALENDAR_SYNC_ENABLED_KEY).then( it => (this.syncEnabled = it), ); this.getSetting(CALENDAR_NOTIFICATIONS_ENABLED_KEY).then( it => (this.notificationsEnabled = it), ); } async getSetting( key: CALENDAR_SYNC_KEYS, defaultValue = false, ): Promise { return getCalendarSetting(this.storageProvider, key, defaultValue); } async syncCalendar(sync: boolean) { this.syncEnabled = sync; if (sync) { const uuids = this.scheduleProvider.partialEvents$.value.map( it => it.uid, ); const dateSeries = (await this.scheduleProvider.getDateSeries(uuids)) .dates; await this.calendarService.syncEvents( getNativeCalendarExport(dateSeries, this.thingTranslator.translator), ); } else { await this.calendarService.purge(); } } async setSetting(settings: Partial>) { await Promise.all( Object.entries(settings).map(([key, setting]) => this.storageProvider.put(calendarSettingStorageKey(key), setting), ), ); return this.scheduleSyncService.enable(); } async export() { const uuids = this.scheduleProvider.partialEvents$.value.map(it => it.uid); const dateSeries = (await this.scheduleProvider.getDateSeries(uuids)).dates; const modal = await this.modalController.create({ component: AddEventReviewModalComponent, canDismiss: true, cssClass: 'add-modal', componentProps: { dismissAction: () => { modal.dismiss(); }, dateSeries: dateSeries, }, }); await modal.present(); await modal.onWillDismiss(); } async restore(event: Event) { // @ts-expect-error files do actually exist const file = event.target?.files[0] as File; const uuids = JSON.parse(await file.text()) as SCUuid[] | unknown; if (!Array.isArray(uuids) || uuids.some(it => typeof it !== 'string')) { return Dialog.alert({ title: this.translator.instant( 'settings.calendar.export.dialogs.restore.rejectFile.title', ), message: this.translator.instant( 'settings.calendar.export.dialogs.restore.rejectFile.message', ), }); } const dateSeries = await this.scheduleProvider.restore(uuids); return dateSeries ? Dialog.confirm({ title: this.translator.instant( 'settings.calendar.export.dialogs.restore.success.title', ), message: this.translator.instant( 'settings.calendar.export.dialogs.restore.success.message', ), }) : Dialog.alert({ title: this.translator.instant( 'settings.calendar.export.dialogs.restore.error.title', ), message: this.translator.instant( 'settings.calendar.export.dialogs.restore.error.message', ), }); } translateWithDefault(key: string, defaultValue: string) { const out = this.translator.instant(key); return out === key ? defaultValue : out; } async backup() { const uuids = JSON.stringify( this.scheduleProvider.partialEvents$.value.map(it => it.uid), ); const fileName = `${this.translator.instant( 'settings.calendar.export.fileName', )}.json`; const info = await Device.getInfo(); if (info.platform === 'web') { const blob = new Blob([uuids], {type: 'application/json'}); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = fileName; a.click(); window.URL.revokeObjectURL(url); } else { const result = await Filesystem.writeFile({ path: fileName, data: uuids, encoding: Encoding.UTF8, directory: Directory.Cache, }); await Share.share({ title: this.translator.instant( 'settings.calendar.export.dialogs.backup.save.title', ), text: this.translator.instant( 'settings.calendar.export.dialogs.backup.save.message', ), url: result.uri, dialogTitle: this.translator.instant( 'settings.calendar.export.dialogs.backup.save.title', ), }); } } }