1// Copyright (C) 2024 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {z} from 'zod'; 16import {Time} from '../base/time'; 17 18// This should be bumped only in case of breaking changes that cannot be 19// addressed using zod's z.optional(), z.default() or z.coerce.xxx(). 20// Ideally these cases should be extremely rare. 21export const SERIALIZED_STATE_VERSION = 1; 22 23// At deserialization time this takes a string as input and converts it into a 24// BigInt. The serialization side of this is handled by JsonSerialize(), which 25// converts BigInt into strings when invoking JSON.stringify. 26const zTime = z 27 .string() 28 .regex(/[-]?\d+/) 29 .transform((s) => Time.fromRaw(BigInt(s))); 30 31const SELECTION_SCHEMA = z.discriminatedUnion('kind', [ 32 z.object({ 33 kind: z.literal('TRACK_EVENT'), 34 // This is actually the track URI but let's not rename for backwards compat 35 trackKey: z.string(), 36 eventId: z.string(), 37 detailsPanel: z.unknown(), 38 }), 39 z.object({ 40 kind: z.literal('AREA'), 41 start: zTime, 42 end: zTime, 43 trackUris: z.array(z.string()), 44 }), 45]); 46 47export type SerializedSelection = z.infer<typeof SELECTION_SCHEMA>; 48 49const NOTE_SCHEMA = z 50 .object({ 51 id: z.string(), 52 start: zTime, 53 color: z.string(), 54 text: z.string(), 55 }) 56 .and( 57 z.discriminatedUnion('noteType', [ 58 z.object({noteType: z.literal('DEFAULT')}), 59 z.object({noteType: z.literal('SPAN'), end: zTime}), 60 ]), 61 ); 62 63export type SerializedNote = z.infer<typeof NOTE_SCHEMA>; 64 65const PLUGIN_SCHEMA = z.object({ 66 id: z.string(), 67 state: z.any(), 68}); 69 70export type SerializedPluginState = z.infer<typeof PLUGIN_SCHEMA>; 71 72export const APP_STATE_SCHEMA = z.object({ 73 version: z.number(), 74 pinnedTracks: z.array(z.string()).default([]), 75 viewport: z 76 .object({ 77 start: zTime, 78 end: zTime, 79 }) 80 .optional(), 81 selection: z.array(SELECTION_SCHEMA).default([]), 82 notes: z.array(NOTE_SCHEMA).default([]), 83 plugins: z.array(PLUGIN_SCHEMA).default([]), 84}); 85 86export type SerializedAppState = z.infer<typeof APP_STATE_SCHEMA>; 87