@sequent-org/moodboard 1.2.60 → 1.2.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -17,46 +17,33 @@ export class DataManager {
|
|
|
17
17
|
// Очищаем доску перед загрузкой
|
|
18
18
|
this.clearBoard();
|
|
19
19
|
|
|
20
|
-
//
|
|
20
|
+
// Применяем settings централизованно (если есть апплаер), иначе — старым способом
|
|
21
21
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
if (this.coreMoodboard?.settingsApplier && data.settings) {
|
|
23
|
+
this.coreMoodboard.settingsApplier.apply(data.settings);
|
|
24
|
+
} else {
|
|
25
|
+
// fallback оставлен для совместимости (если где-то аплеер не создан)
|
|
26
|
+
const grid = (data.settings && data.settings.grid) || data.grid || (data.board && data.board.grid);
|
|
27
|
+
if (grid && grid.type) {
|
|
28
|
+
const payload = { type: grid.type };
|
|
29
|
+
const opts = grid.options || null;
|
|
30
|
+
if (opts && typeof opts === 'object') payload.options = opts;
|
|
31
|
+
this.coreMoodboard.eventBus.emit(this.coreMoodboard.Events?.UI?.GridChange || 'ui:grid:change', payload);
|
|
32
|
+
}
|
|
33
|
+
const settings = data.settings || {};
|
|
34
|
+
const bg = settings.backgroundColor;
|
|
35
|
+
if (bg && this.coreMoodboard?.pixi?.app?.renderer) {
|
|
36
|
+
const s = typeof bg === 'string' ? (bg.startsWith('#') ? bg.slice(1) : bg) : null;
|
|
37
|
+
const bgInt = typeof bg === 'number' ? bg : (s ? parseInt(s, 16) : null);
|
|
38
|
+
if (bgInt != null) this.coreMoodboard.pixi.app.renderer.backgroundColor = bgInt;
|
|
39
|
+
}
|
|
40
|
+
const z = settings.zoom && (settings.zoom.current || settings.zoom.default);
|
|
41
|
+
const world = this.coreMoodboard?.pixi?.worldLayer || this.coreMoodboard?.pixi?.app?.stage;
|
|
42
|
+
if (world && Number.isFinite(z) && z > 0) {
|
|
43
|
+
world.scale.set(z);
|
|
44
|
+
const percent = Math.round(z * 100);
|
|
45
|
+
try { this.coreMoodboard.eventBus.emit('ui:zoom:percent', { percentage: percent }); } catch (_) {}
|
|
28
46
|
}
|
|
29
|
-
this.coreMoodboard.eventBus.emit(this.coreMoodboard.Events?.UI?.GridChange || 'ui:grid:change', payload);
|
|
30
|
-
}
|
|
31
|
-
} catch (_) {}
|
|
32
|
-
|
|
33
|
-
// Восстановим фон и зум из settings, если есть
|
|
34
|
-
try {
|
|
35
|
-
const settings = data.settings || {};
|
|
36
|
-
// Фон
|
|
37
|
-
const bg = settings.backgroundColor;
|
|
38
|
-
if (bg && this.coreMoodboard?.pixi?.app?.renderer) {
|
|
39
|
-
const parseHex = (v) => {
|
|
40
|
-
if (typeof v === 'number') return v;
|
|
41
|
-
if (typeof v === 'string') {
|
|
42
|
-
const s = v.startsWith('#') ? v.slice(1) : v;
|
|
43
|
-
const n = parseInt(s, 16);
|
|
44
|
-
if (Number.isFinite(n)) return n;
|
|
45
|
-
}
|
|
46
|
-
return null;
|
|
47
|
-
};
|
|
48
|
-
const bgInt = parseHex(bg);
|
|
49
|
-
if (bgInt != null) this.coreMoodboard.pixi.app.renderer.backgroundColor = bgInt;
|
|
50
|
-
}
|
|
51
|
-
// Зум
|
|
52
|
-
const z = settings.zoom && (settings.zoom.current || settings.zoom.default);
|
|
53
|
-
const world = this.coreMoodboard?.pixi?.worldLayer || this.coreMoodboard?.pixi?.app?.stage;
|
|
54
|
-
if (world && Number.isFinite(z) && z > 0) {
|
|
55
|
-
world.scale.set(z);
|
|
56
|
-
const percent = Math.round(z * 100);
|
|
57
|
-
try {
|
|
58
|
-
this.coreMoodboard.eventBus.emit('ui:zoom:percent', { percentage: percent });
|
|
59
|
-
} catch (_) {}
|
|
60
47
|
}
|
|
61
48
|
} catch (_) {}
|
|
62
49
|
|
|
@@ -18,6 +18,7 @@ import { NotePropertiesPanel } from '../ui/NotePropertiesPanel.js';
|
|
|
18
18
|
import { FilePropertiesPanel } from '../ui/FilePropertiesPanel.js';
|
|
19
19
|
import { AlignmentGuides } from '../tools/AlignmentGuides.js';
|
|
20
20
|
import { ImageUploadService } from '../services/ImageUploadService.js';
|
|
21
|
+
import { SettingsApplier } from '../services/SettingsApplier.js';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Готовый MoodBoard с UI - главный класс пакета
|
|
@@ -84,6 +85,15 @@ export class MoodBoard {
|
|
|
84
85
|
// Инициализируем CoreMoodBoard
|
|
85
86
|
await this.initCoreMoodBoard();
|
|
86
87
|
|
|
88
|
+
// Настройки (единая точка применения)
|
|
89
|
+
this.settingsApplier = new SettingsApplier(
|
|
90
|
+
this.coreMoodboard.eventBus,
|
|
91
|
+
this.coreMoodboard.pixi,
|
|
92
|
+
this.coreMoodboard.boardService || null
|
|
93
|
+
);
|
|
94
|
+
// Делаем доступным для других подсистем
|
|
95
|
+
this.coreMoodboard.settingsApplier = this.settingsApplier;
|
|
96
|
+
|
|
87
97
|
// Создаем менеджеры
|
|
88
98
|
this.dataManager = new DataManager(this.coreMoodboard);
|
|
89
99
|
this.actionHandler = new ActionHandler(this.dataManager, this.workspaceManager);
|
|
@@ -131,6 +141,10 @@ export class MoodBoard {
|
|
|
131
141
|
|
|
132
142
|
// Предоставляем доступ к сервису через core
|
|
133
143
|
this.coreMoodboard.imageUploadService = this.imageUploadService;
|
|
144
|
+
// Передаем ссылку на topbar в апплаер настроек для синхронизации UI
|
|
145
|
+
if (this.settingsApplier && this.topbar) {
|
|
146
|
+
this.settingsApplier.setUI({ topbar: this.topbar });
|
|
147
|
+
}
|
|
134
148
|
|
|
135
149
|
// Настраиваем коллбеки событий
|
|
136
150
|
this.setupEventCallbacks();
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Events } from '../core/events/Events.js';
|
|
2
|
+
|
|
3
|
+
export class SettingsApplier {
|
|
4
|
+
constructor(eventBus, pixi, boardService = null, uiRefs = {}) {
|
|
5
|
+
this.eventBus = eventBus;
|
|
6
|
+
this.pixi = pixi;
|
|
7
|
+
this.boardService = boardService;
|
|
8
|
+
this.ui = uiRefs || {};
|
|
9
|
+
this.settings = {};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
setUI(uiRefs = {}) {
|
|
13
|
+
this.ui = { ...this.ui, ...uiRefs };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
set(partial) {
|
|
17
|
+
this.settings = { ...this.settings, ...(partial || {}) };
|
|
18
|
+
this.apply(this.settings);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get() {
|
|
22
|
+
return { ...this.settings };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
apply(settings = {}) {
|
|
26
|
+
this.settings = { ...this.settings, ...settings };
|
|
27
|
+
const s = this.settings;
|
|
28
|
+
|
|
29
|
+
// 1) Фон
|
|
30
|
+
if (s.backgroundColor && this.pixi?.app?.renderer) {
|
|
31
|
+
const bgInt = this._toIntColor(s.backgroundColor);
|
|
32
|
+
if (bgInt != null) this.pixi.app.renderer.backgroundColor = bgInt;
|
|
33
|
+
// Синхронизация UI цвета (если доступен topbar)
|
|
34
|
+
if (this.ui.topbar) {
|
|
35
|
+
try {
|
|
36
|
+
const boardHex = this._toHex(bgInt);
|
|
37
|
+
this.ui.topbar.setCurrentBoardHex(boardHex);
|
|
38
|
+
} catch (_) {}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 2) Сетка
|
|
43
|
+
if (s.grid && s.grid.type) {
|
|
44
|
+
try {
|
|
45
|
+
const payload = { type: s.grid.type };
|
|
46
|
+
// Пробрасываем дополнительные опции, если есть
|
|
47
|
+
const options = s.grid.options || {
|
|
48
|
+
size: s.grid.size,
|
|
49
|
+
color: this._maybeInt(s.grid.color),
|
|
50
|
+
enabled: s.grid.visible !== false
|
|
51
|
+
};
|
|
52
|
+
if (options) payload.options = options;
|
|
53
|
+
this.eventBus.emit(Events.UI.GridChange, payload);
|
|
54
|
+
if (this.ui.topbar && s.grid.type) {
|
|
55
|
+
this.ui.topbar.setActive(s.grid.type);
|
|
56
|
+
}
|
|
57
|
+
} catch (_) {}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 3) Зум
|
|
61
|
+
if (s.zoom && (typeof s.zoom.current === 'number')) {
|
|
62
|
+
const world = this.pixi?.worldLayer || this.pixi?.app?.stage;
|
|
63
|
+
if (world) {
|
|
64
|
+
const z = Math.max(0.1, Math.min(5, s.zoom.current));
|
|
65
|
+
world.scale.set(z);
|
|
66
|
+
try { this.eventBus.emit(Events.UI.ZoomPercent, { percentage: Math.round(z * 100) }); } catch (_) {}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
_toIntColor(hexOrInt) {
|
|
72
|
+
if (typeof hexOrInt === 'number') return hexOrInt;
|
|
73
|
+
if (typeof hexOrInt === 'string') {
|
|
74
|
+
const s = hexOrInt.startsWith('#') ? hexOrInt.slice(1) : hexOrInt;
|
|
75
|
+
const n = parseInt(s, 16);
|
|
76
|
+
return Number.isFinite(n) ? n : null;
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
_maybeInt(v) {
|
|
82
|
+
if (v == null) return v;
|
|
83
|
+
if (typeof v === 'number') return v;
|
|
84
|
+
if (typeof v === 'string') {
|
|
85
|
+
const s = v.startsWith('#') ? v.slice(1) : v;
|
|
86
|
+
const n = parseInt(s, 16);
|
|
87
|
+
return Number.isFinite(n) ? n : v;
|
|
88
|
+
}
|
|
89
|
+
return v;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
_toHex(intColor) {
|
|
93
|
+
try { return `#${(intColor >>> 0).toString(16).padStart(6, '0')}`.toLowerCase(); } catch (_) { return '#f5f5f5'; }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|