mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-21 09:03:02 +00:00
feat: calendar plugin
This commit is contained in:
committed by
Rainer Killinger
parent
080e6fa3e8
commit
a57c3029df
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2021 StApps
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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 {map} from 'lodash-es';
|
||||
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,
|
||||
CALENDAR_SYNC_SETTINGS_KEY,
|
||||
} 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) {
|
||||
return (await this.storageProvider.get(
|
||||
`${CALENDAR_SYNC_SETTINGS_KEY}.${key}`,
|
||||
)) as boolean;
|
||||
}
|
||||
|
||||
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<Record<CALENDAR_SYNC_KEYS, boolean>>) {
|
||||
await Promise.all(
|
||||
map(settings, (setting, key) =>
|
||||
this.storageProvider.put(
|
||||
`${CALENDAR_SYNC_SETTINGS_KEY}.${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,
|
||||
swipeToClose: 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',
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user