scriptable-testlab
Version:
A lightweight, efficient tool designed to manage and update scripts for Scriptable.
206 lines (163 loc) • 4.78 kB
text/typescript
import {AbsNotification} from 'scriptable-abstract';
import {NotificationMockState, NotificationSound} from '../../types';
const DEFAULT_STATE: NotificationMockState = {
identifier: `notification_${Date.now()}_${Math.random()}`,
title: '',
subtitle: '',
body: '',
threadIdentifier: '',
preferredContentHeight: 0,
badge: 0,
userInfo: {},
sound: 'default',
openURL: '',
deliveryDate: new Date(0),
nextTriggerDate: new Date(0),
scriptName: '',
actions: {title: '', url: ''},
};
/**
* Mock implementation of Scriptable's Notification.
* Provides functionality for managing notifications.
* @implements Notification
*/
export class MockNotification extends AbsNotification<NotificationMockState> {
private static schedules: MockNotification[] = [];
private static lastDelivered: MockNotification | null = null;
constructor() {
super(DEFAULT_STATE);
}
get asNotification(): Notification {
return this as unknown as Notification;
}
// Basic properties
get identifier(): string {
return this.state.identifier;
}
get title(): string {
return this.state.title;
}
set title(value: string) {
this.setState({title: value});
}
get body(): string {
return this.state.body;
}
set body(value: string) {
this.setState({body: value});
}
get subtitle(): string {
return this.state.subtitle;
}
set subtitle(value: string) {
this.setState({subtitle: value});
}
get threadIdentifier(): string {
return this.state.threadIdentifier;
}
set threadIdentifier(value: string) {
this.setState({threadIdentifier: value});
}
get preferredContentHeight(): number {
return this.state.preferredContentHeight;
}
set preferredContentHeight(value: number) {
this.setState({preferredContentHeight: value});
}
get badge(): number {
return this.state.badge;
}
set badge(value: number) {
this.setState({badge: value});
}
get userInfo(): Record<string, unknown> {
return {...this.state.userInfo};
}
set userInfo(value: Record<string, unknown>) {
this.setState({userInfo: {...value}});
}
get sound(): NotificationSound {
return this.state.sound;
}
set sound(value: NotificationSound) {
this.setState({sound: value});
}
get openURL(): string {
return this.state.openURL;
}
set openURL(value: string) {
this.setState({openURL: value});
}
get deliveryDate(): Date {
return new Date(this.state.deliveryDate);
}
get nextTriggerDate(): Date {
return new Date(this.state.nextTriggerDate);
}
get scriptName(): string {
return this.state.scriptName;
}
set scriptName(value: string) {
this.setState({scriptName: value});
}
get actions(): Notification.Actions {
return {...this.state.actions};
}
// Core functionality
setTriggerDate(date: Date): void {
this.setState({
deliveryDate: new Date(date),
nextTriggerDate: new Date(date),
});
}
setDailyTrigger(hour: number, minute: number, _repeats = false): void {
const now = new Date();
const next = new Date(now);
next.setHours(hour, minute, 0, 0);
if (next <= now) next.setDate(next.getDate() + 1);
this.setTriggerDate(next);
}
setWeeklyTrigger(weekday: number, hour: number, minute: number, _repeats = false): void {
const now = new Date();
const next = new Date(now);
next.setHours(hour, minute, 0, 0);
while (next.getDay() !== weekday || next <= now) {
next.setDate(next.getDate() + 1);
}
this.setTriggerDate(next);
}
addAction(title: string, url: string): void {
this.setState({actions: {title, url}});
}
async remove(): Promise<void> {
const index = MockNotification.schedules.indexOf(this);
if (index > -1) MockNotification.schedules.splice(index, 1);
}
async schedule(): Promise<void> {
MockNotification.schedules.push(this);
}
// Static methods
static async allPending(): Promise<Notification[]> {
return this.schedules.map(notification => notification.asNotification);
}
static async removePending(): Promise<void> {
this.schedules = [];
}
static async removePendingNotification(identifier: string): Promise<void> {
this.schedules = this.schedules.filter(n => n.identifier !== identifier);
}
static getLastDelivered(): Notification | null {
return this.lastDelivered?.asNotification ?? null;
}
static reset(): void {
this.schedules = [];
this.lastDelivered = null;
}
async scheduleNotification(date: Date, _repeats = false): Promise<void> {
await this.scheduleNotificationAt(date);
}
async scheduleNotificationAt(date: Date, _repeats = false): Promise<void> {
this.setTriggerDate(date);
await this.schedule();
}
}