Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement FileRelatedActionsHelper #641

Merged
merged 10 commits into from
Dec 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions monosketch-svelte/src/lib/mono/file/mono-file.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2024, tuanchauict
*/

import { Point, PointF } from "$libs/graphics-geo/point";
import { Extra, MonoFile } from "$mono/file/mono-file";
import { SerializableLineConnector } from "$mono/shape/serialization/connector";
import { SerializableGroup, SerializableRectangle } from "$mono/shape/serialization/shapes";
import { describe, expect, test } from "vitest";

describe("MonoFile serialization", () => {
const root = SerializableGroup.create({
id: "root",
isIdTemporary: false,
versionCode: 1,
shapes: [
SerializableRectangle.EMPTY,
SerializableRectangle.EMPTY,
]
});
const connectors: SerializableLineConnector[] = [
SerializableLineConnector.create({
lineId: "lineId",
anchor: 0,
targetId: "targetId",
ratio: PointF.create({ left: 0.5, top: 0.6 }),
offset: Point.of(10, 20),
}),
SerializableLineConnector.create({
lineId: "lineId1",
anchor: 1,
targetId: "targetId",
ratio: PointF.create({ left: 0.5, top: 0.6 }),
offset: Point.of(10, 20),
}),
];
const extra = Extra.create("Test", Point.of(30, 50));
const modifiedTimestampMillis = 1000;

test("should serialize MonoFile correctly", () => {
const monoFile = MonoFile.create(root, connectors, extra, modifiedTimestampMillis);
// @ts-expect-error toJson is attached by Jsonizable
const json = monoFile.toJson();
expect(json).toEqual({
// @ts-expect-error toJson is attached by Jsonizable
root: root.toJson(),
// @ts-expect-error toJson is attached by Jsonizable
extra: extra.toJson(),
version: 2,
modified_timestamp_millis: modifiedTimestampMillis,
// @ts-expect-error toJson is attached by Json
connectors: connectors.map(connector => connector.toJson()),
});
});

test("should deserialize MonoFile correctly", () => {
const json = {
// @ts-expect-error toJson is attached by Jsonizable
root: root.toJson(),
// @ts-expect-error toJson is attached by Jsonizable
extra: extra.toJson(),
version: 2,
modified_timestamp_millis: modifiedTimestampMillis,
// @ts-expect-error toJson is attached by Json
connectors: connectors.map(connector => connector.toJson()),
};
// @ts-expect-error fromJson is attached by Jsonizable
const monoFile = MonoFile.fromJson(json);
expect(monoFile).toEqual(MonoFile.create(root, connectors, extra, modifiedTimestampMillis));
});
});
83 changes: 83 additions & 0 deletions monosketch-svelte/src/lib/mono/file/mono-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2024, tuanchauict
*/

import { Point } from "$libs/graphics-geo/point";
import {
type SerializableLineConnector,
SerializableLineConnectorArraySerializer,
} from "$mono/shape/serialization/connector";
import { Jsonizable, Serializer, SerialName } from "$mono/shape/serialization/serializable";
import { SerializableGroup } from "$mono/shape/serialization/shapes";

/**
* Version of the mono file
*
* # Version 0
* No mono file format. It was just a serialization of the root group
*
* # Version 1
* The first version of MonoFile.
* - root: root group content
* - extra:
* - name
* - offset
* - version: 1
* - modified_timestamp_millis: timestamp in millisecond (local time)
*
* # Version 2
* Include `connectors`
* - connectors: list of serialization of line connectors
*/
const MONO_FILE_VERSION = 2;

/**
* A data class for serializing shape to Json and load shape from Json.
*/
@Jsonizable
export class MonoFile {
@SerialName("root")
root: SerializableGroup = SerializableGroup.EMPTY;
@SerialName("extra")
extra: Extra = Extra.create("", Point.ZERO);
@SerialName("version")
version: number = 0;
@SerialName("modified_timestamp_millis")
modifiedTimestampMillis: number = 0;
@SerialName("connectors")
@Serializer(SerializableLineConnectorArraySerializer)
connectors: SerializableLineConnector[] = [];

static create(
root: SerializableGroup,
connectors: SerializableLineConnector[],
extra: Extra,
modifiedTimestampMillis: number = Date.now(),
): MonoFile {
const file = new MonoFile();
file.root = root;
file.connectors = connectors;
file.extra = extra;
file.version = MONO_FILE_VERSION;
file.modifiedTimestampMillis = modifiedTimestampMillis;
return file;
}
}

@Jsonizable
export class Extra {
@SerialName("name")
name: string = "";
@SerialName("offset")
offset: Point = Point.ZERO;

private constructor() {
}

static create(name: string, offset: Point): Extra {
const extra = new Extra();
extra.name = name;
extra.offset = offset;
return extra;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2024, tuanchauict
*/

import { describe, expect, test } from "vitest";
import { ShapeSerializationUtil } from './shape-serialization-util';
import { SerializableGroup, SerializableRectangle } from '$mono/shape/serialization/shapes';
import { SerializableLineConnector } from '$mono/shape/serialization/connector';
import { Point, PointF } from '$libs/graphics-geo/point';
import { MonoFile, Extra } from './mono-file';

describe('ShapeSerializationUtil', () => {
const root = SerializableGroup.create({
id: "root",
isIdTemporary: false,
versionCode: 2,
shapes: [
SerializableRectangle.EMPTY,
SerializableRectangle.EMPTY,
]
});
const connectors: SerializableLineConnector[] = [
SerializableLineConnector.create({
lineId: "lineId",
anchor: 1,
targetId: "targetId",
ratio: PointF.create({ left: 0.5, top: 0.6 }),
offset: Point.of(10, 20),
}),
SerializableLineConnector.create({
lineId: "lineId1",
anchor: 0,
targetId: "targetId",
ratio: PointF.create({ left: 0.5, top: 0.6 }),
offset: Point.of(10, 20),
}),
];
const extra = Extra.create("Test", Point.of(30, 50));
const modifiedTimestampMillis = 1000;

test('should serialize and deserialize a shape correctly', () => {
const json = ShapeSerializationUtil.toShapeJson(root);
console.log(json);
const deserializedShape = ShapeSerializationUtil.fromShapeJson(json);
expect(deserializedShape).toEqual(root);
});

test('should serialize and deserialize connectors correctly', () => {
const json = ShapeSerializationUtil.toConnectorsJson(connectors);
console.log(json);
const deserializedConnectors = ShapeSerializationUtil.fromConnectorsJson(json);
expect(deserializedConnectors).toEqual(connectors);
});

test('should serialize and deserialize a MonoFile correctly', () => {
const monoFile = MonoFile.create(root, connectors, extra, modifiedTimestampMillis);
const json = ShapeSerializationUtil.toMonoFileJson(monoFile);
console.log(json);
const deserializedMonoFile = ShapeSerializationUtil.fromMonoFileJson(json);
expect(deserializedMonoFile).toEqual(monoFile);
});
});
67 changes: 67 additions & 0 deletions monosketch-svelte/src/lib/mono/file/shape-serialization-util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2024, tuanchauict
*/

import { SerializableGroup, AbstractSerializableShape, deserializeShape } from '$mono/shape/serialization/shapes';
import {
SerializableLineConnector,
SerializableLineConnectorArraySerializer,
} from '$mono/shape/serialization/connector';
import { Point } from '$libs/graphics-geo/point';
import { MonoFile, Extra } from './mono-file';

export class ShapeSerializationUtil {
static toShapeJson(serializableShape: AbstractSerializableShape): string {
// @ts-expect-error toJson is attached by Jsonizable
return JSON.stringify(serializableShape.toJson());
}

static fromShapeJson(jsonString: string): AbstractSerializableShape | null {
try {
const json = JSON.parse(jsonString);
return deserializeShape(json);
} catch (e) {
console.error("Error while restoring shapes");
console.error(e);
return null;
}
}

static toConnectorsJson(connectors: SerializableLineConnector[]): string {
return JSON.stringify(SerializableLineConnectorArraySerializer.serialize(connectors));
}
/* eslint-disable @typescript-eslint/no-explicit-any */
static fromConnectorsJson(jsonString: string): SerializableLineConnector[] {
try {
const json = JSON.parse(jsonString) as any[];
return SerializableLineConnectorArraySerializer.deserialize(json);
} catch (e) {
console.error("Error while restoring connectors");
console.error(e);
return [];
}
}
/* eslint-enable @typescript-eslint/no-explicit-any */

static toMonoFileJson(monoFile: MonoFile): string {
// @ts-expect-error toJson is attached by Jsonizable
const json = monoFile.toJson();
return JSON.stringify(json);
}

static fromMonoFileJson(jsonString: string): MonoFile | null {
try {
const json = JSON.parse(jsonString);
// @ts-expect-error fromJson is attached by Jsonizable
return MonoFile.fromJson(json);
} catch (e) {

Check warning on line 57 in monosketch-svelte/src/lib/mono/file/shape-serialization-util.ts

View workflow job for this annotation

GitHub Actions / lint

'e' is defined but never used. Allowed unused args must match /^_/u
// Fallback to version 0
const shape = this.fromShapeJson(jsonString) as SerializableGroup | null;
if (shape) {
return MonoFile.create(shape, [], Extra.create("", Point.ZERO));
} else {
return null;
}
}
}
}
6 changes: 6 additions & 0 deletions monosketch-svelte/src/lib/mono/monobitmap/board/board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ export class MonoBoard {

return painterBoard.toString();
};

toStringInBound = (bound: Rect): string => {
const painterBoard = new PainterBoard(bound);
Array.from(this.painterBoards.values()).forEach((pb) => painterBoard.fill(pb));
return painterBoard.toString();
};
}

type BoardAddress = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,13 @@ export function Jsonizable(constructor: Function) {
// 1st: Check if the field has a serializer
// 2nd: Check if the field has a toJson method
// 3rd: Use the value directly
const field = instance[key];
if (serializers[key]) {
json[serializedKey] = serializers[key].serialize(instance[key]);
} else if (instance[key].toJson) {
json[serializedKey] = instance[key].toJson();
json[serializedKey] = serializers[key].serialize(field);
} else if (field && field.toJson) {
json[serializedKey] = field.toJson();
} else {
json[serializedKey] = instance[key];
json[serializedKey] = field;
}
}
return json;
Expand Down
Loading
Loading