fix: dev green after the Studio, place picture and tour merges

The ids of long catalogues (fonts, shapes, patterns) read as a checked string
in the book tools' schemas, so restore_book_page and the page edit stay under
their ceilings. The lightbox takes its reading direction from the language.
Baselines follow the removed avatar upload and the lower counts, the doubled
NEWER constants and three unused imports go, the locale indexes are sorted,
and the place gallery, picture, sheet, inspector weight and paddle tests
follow the merged behaviour.
This commit is contained in:
Maurice
2026-10-23 21:58:43 +02:00
parent 7b50b12fe6
commit c6b3f609b7
48 changed files with 108 additions and 71 deletions
+8 -8
View File
@@ -1,18 +1,18 @@
{
"src": {
"@typescript-eslint/no-non-null-assertion": 404,
"@typescript-eslint/no-misused-promises": 854,
"@typescript-eslint/no-non-null-assertion": 403,
"@typescript-eslint/no-misused-promises": 850,
"no-console": 88,
"complexity": 226,
"@typescript-eslint/no-explicit-any": 146,
"trek/no-swallowed-catch": 131,
"trek/no-swallowed-catch": 130,
"max-params": 33,
"trek/store-without-selector": 67,
"react-hooks/refs": 557,
"react-hooks/set-state-in-effect": 195,
"react-hooks/refs": 556,
"react-hooks/set-state-in-effect": 194,
"@typescript-eslint/no-floating-promises": 165,
"react-hooks/exhaustive-deps": 116,
"@typescript-eslint/no-unused-vars": 126,
"@typescript-eslint/no-unused-vars": 125,
"react-hooks/immutability": 28,
"max-lines-per-function": 132,
"react-hooks/static-components": 78,
@@ -20,7 +20,7 @@
"no-useless-assignment": 7,
"no-empty": 19,
"trek/no-window-globals": 41,
"react-refresh/only-export-components": 46,
"react-refresh/only-export-components": 45,
"unused-disable-directive": 6,
"max-depth": 21,
"react-hooks/void-use-memo": 1,
@@ -34,7 +34,7 @@
"react-hooks/exhaustive-deps": 46
},
"tests": {
"@typescript-eslint/no-explicit-any": 491,
"@typescript-eslint/no-explicit-any": 490,
"@typescript-eslint/no-non-null-assertion": 1932,
"@typescript-eslint/no-misused-promises": 22,
"@typescript-eslint/no-unused-vars": 51,
-1
View File
@@ -116,7 +116,6 @@
"src/components/Vacay/useVacayCalendarLogic.ts",
"src/components/Vacay/useVacaySettings.ts",
"src/components/Vacay/useVacayUserPicker.ts",
"src/components/shared/PlaceAvatarUpload.tsx",
"src/hooks/useAirtrailConnection.ts",
"src/hooks/useDawarichConnection.ts",
"src/hooks/useDawarichSuggestions.ts",
-1
View File
@@ -73,7 +73,6 @@
"components/shared/DetailShell.tsx": 1,
"components/shared/ElevationProfile.tsx": 2,
"components/shared/NavigationMenu.tsx": 2,
"components/shared/PlaceAvatarUpload.tsx": 3,
"components/shared/PublicLanguagePicker.tsx": 1,
"components/shared/SlidingTabs.tsx": 3,
"components/shared/StarRating.tsx": 3,
+1 -2
View File
@@ -51,7 +51,7 @@
"src/components/Planner/DayPlanSidebarNoteModal.test.tsx": 1,
"src/components/Planner/PlaceFormModal.test.tsx": 3,
"src/components/Planner/PlaceFormModal.tsx": 1,
"src/components/Planner/PlaceInspector.tsx": 17,
"src/components/Planner/PlaceInspector.tsx": 16,
"src/components/Planner/PlacesBulkCategoryModal.test.tsx": 1,
"src/components/Planner/PlacesSidebar.tsx": 1,
"src/components/Planner/PlacesSidebarMobileDayPicker.tsx": 8,
@@ -97,7 +97,6 @@
"src/components/shared/CustomSelect.test.tsx": 1,
"src/components/shared/PlaceAvatar.test.tsx": 2,
"src/components/shared/PlaceAvatar.tsx": 1,
"src/components/shared/PlaceAvatarUpload.test.tsx": 1,
"src/hooks/useDawarichSuggestions.test.ts": 1,
"src/mobile/screens/admin/MAdminAddonManager.tsx": 2,
"src/mobile/screens/admin/MAdminPluginsPanel.tsx": 6,
-1
View File
@@ -132,7 +132,6 @@
"components/shared/Modal.tsx": 3,
"components/shared/NavigationMenu.tsx": 1,
"components/shared/NoteColorPicker.tsx": 2,
"components/shared/PlaceAvatarUpload.tsx": 3,
"components/shared/PublicLanguagePicker.tsx": 3,
"components/shared/Skeleton.tsx": 2,
"components/shared/Spinner.tsx": 2,
@@ -17,6 +17,7 @@ vi.mock('../../api/websocket', () => ({
import { render, screen, fireEvent } from '../../../tests/helpers/render';
import { resetAllStores } from '../../../tests/helpers/store';
import { useSettingsStore } from '../../store/settingsStore';
import PhotoLightbox from './PhotoLightbox';
const samplePhotos = [
@@ -277,7 +278,8 @@ describe('PhotoLightbox', () => {
describe('right to left', () => {
beforeEach(() => {
document.documentElement.dir = 'rtl';
// The direction follows the language, as in the app, where the provider also sets <html dir>.
useSettingsStore.setState((state) => ({ settings: { ...state.settings, language: 'ar' } }));
});
afterEach(() => {
document.documentElement.dir = '';
@@ -3,7 +3,7 @@ import { ChevronLeft, ChevronRight, X, ZoomIn, ZoomOut } from 'lucide-react'
import VideoPlayer from './VideoPlayerLazy'
import { usePhotoZoom } from './usePhotoZoom'
import { Tooltip } from '../shared/Tooltip'
import { useTranslation } from '../../i18n'
import { isRtlLanguage, useTranslation } from '../../i18n'
interface LightboxPhoto {
id: string
@@ -36,9 +36,10 @@ export default function PhotoLightbox({ photos, startIndex = 0, onClose, label }
const [idx, setIdx] = useState(startIndex)
const touchStart = useRef<{ x: number; y: number } | null>(null)
const dialogRef = useRef<HTMLDivElement>(null)
const { t } = useTranslation()
const { t, language } = useTranslation()
// Right to left, the next photo lies to the left: the arrow keys and swipes follow the reading direction.
const rtl = typeof document !== 'undefined' && document.documentElement.dir === 'rtl'
// Taken from the language, not read off <html dir>, so it stays put across re-renders.
const rtl = isRtlLanguage(language)
// Focus moves into the dialog when it opens and back to what opened it when it closes.
useEffect(() => {
@@ -613,16 +613,19 @@ describe('PlaceDetailsColumn — picture layout', () => {
withPhotos(3)
const { onPickImage } = renderColumn()
// Nothing is picked yet, and the line under the grid says so.
await screen.findByText('places.image.none')
expect(screen.queryByText('Author 0')).not.toBeInTheDocument()
// Nothing is picked and there is no own picture to remove, so 'No picture'
// stays away and the first photo is credited.
await screen.findByText('Author 0')
expect(screen.queryByText('places.image.none')).not.toBeInTheDocument()
const tiles = screen.getAllByRole('button', { name: /places.details.pickImage/ })
fireEvent.mouseEnter(tiles[2])
expect(screen.getByText('Author 2')).toBeInTheDocument()
expect(screen.queryByText('Author 0')).not.toBeInTheDocument()
expect(onPickImage).not.toHaveBeenCalled()
fireEvent.mouseLeave(tiles[2])
expect(screen.queryByText('Author 2')).not.toBeInTheDocument()
expect(screen.getByText('Author 0')).toBeInTheDocument()
})
it('FE-PDC-037: credits the picture in play, licence included', async () => {
@@ -43,7 +43,6 @@ import {
} from '../shared/DialogShell'
import { EditorField, GRID_2, INPUT, LABEL, PANEL, PillSelect, TEXTAREA } from '../shared/dialogParts'
import { SoftPill, tintOf } from './planParts'
import { WHITE_BUTTON } from './placeDialogParts'
import { TimeSection } from './PlaceFormTimeSection'
// The submit payload mirrors the form, but lat/lng are parsed to numbers and
@@ -11,7 +11,11 @@ import PlacePhotoGallery from './PlacePhotoGallery';
import { __clearEnrichmentCacheForTests } from './placeEnrichment';
const placeEnrichment = vi.fn();
vi.mock('../../api/client', () => ({ mapsApi: { placeEnrichment: (...a: unknown[]) => placeEnrichment(...a) } }));
// Partial: the store registry behind resetAllStores needs the real default client.
vi.mock('../../api/client', async (importOriginal) => ({
...(await importOriginal<typeof import('../../api/client')>()),
mapsApi: { placeEnrichment: (...a: unknown[]) => placeEnrichment(...a) },
}));
vi.mock('../Journey/VideoPlayerLazy', () => ({ default: () => null }));
const PLACE = buildPlace({ id: 3, name: 'Tower', lat: 48.85, lng: 2.29, image_url: '/uploads/places/tower.jpg' });
@@ -13,7 +13,11 @@ import { __clearEnrichmentCacheForTests, readCachedEnrichment, storeEnrichment }
import { usePlaceGallery } from './usePlaceGallery';
const placeEnrichment = vi.fn();
vi.mock('../../api/client', () => ({ mapsApi: { placeEnrichment: (...a: unknown[]) => placeEnrichment(...a) } }));
// Partial: the store registry behind resetAllStores needs the real default client.
vi.mock('../../api/client', async (importOriginal) => ({
...(await importOriginal<typeof import('../../api/client')>()),
mapsApi: { placeEnrichment: (...a: unknown[]) => placeEnrichment(...a) },
}));
// One toast for every render, the way the real hook memoises it.
const toast = vi.hoisted(() => ({ success: vi.fn(), error: vi.fn(), warning: vi.fn(), info: vi.fn() }));
vi.mock('../shared/Toast', () => ({ useToast: () => toast }));
@@ -6,7 +6,7 @@ import { PeerCursors } from './PeerCursors'
import type { PeerCursor } from './useBookPresence'
import { bookElementId as elementId } from '@trek/shared'
import { fontStack, nearestWeight } from './bookFonts'
import { useSpreadInteraction, type HandleId } from './useSpreadInteraction'
import { useSpreadInteraction } from './useSpreadInteraction'
import { useStudioKeys } from './useStudioKeys'
import { selectClass, selectionShape } from './studioGestures'
import { MarqueeRect, ResizeHandles, SelectionBox } from './StudioSelectionChrome'
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import {
Camera, Check, ChevronDown, ImagePlus, ChevronUp, Compass, Copy, FileDown, Files, ImageIcon, Layers, LayoutTemplate,
Camera, ChevronDown, ImagePlus, ChevronUp, Compass, Copy, FileDown, Files, ImageIcon, Layers, LayoutTemplate,
Plus, Search, Shapes, Sticker, Trash2, Upload, X,
} from 'lucide-react'
import type { BookElement, BookPageSetup, JourneyStats } from '@trek/shared'
@@ -7,6 +7,7 @@ import type { MTripShellApi, TripPlanner } from '../../../../src/mobile/screens/
import { useAddonStore } from '../../../../src/store/addonStore'
import { useSaveToCollectionStore } from '../../../../src/store/saveToCollectionStore'
import { useTripStore } from '../../../../src/store/tripStore'
import { __clearEnrichmentCacheForTests } from '../../../../src/components/Planner/placeEnrichment'
import { openFile } from '../../../../src/utils/fileDownload'
import type { Assignment, Category, Day, Place, TripFile, TripMember } from '../../../../src/types'
import { resetAllStores, seedStore } from '../../../helpers/store'
@@ -143,6 +144,10 @@ describe('MPlaceSheet', () => {
resetAllStores()
seedStore(useAddonStore, { addons: [{ id: 'collections', name: 'Collections', type: 'feature', icon: '', enabled: true }] })
vi.spyOn(window, 'open').mockImplementation(() => null)
// The enrichment cache outlives a test: an earlier case's photos for the same place would open the gallery.
sessionStorage.clear()
__clearEnrichmentCacheForTests()
galleryToast.info.mockClear()
})
afterEach(() => {
+6 -1
View File
@@ -7,6 +7,7 @@ import {
import { fireEvent, render } from '../../helpers/render'
import { StudioInspector } from '../../../src/components/Studio/StudioInspector'
import { useStudioStore } from '../../../src/store/studioStore'
import { BOOK_FONTS } from '../../../src/components/Studio/bookFonts'
import type { JourneySource } from '../../../src/components/Studio/StudioSidebar'
/**
@@ -213,10 +214,14 @@ describe('a text element', () => {
expect(el()).toMatchObject({ text: 'Bergen harbour', overridden: true })
})
/* The weight is a slider over the weights the family ships, not a row of chips. */
it('sets the weight', () => {
load([text()])
const { container } = draw()
pick(container, '600')
const slider = container.querySelector('input[type="range"][aria-label="journey.studio.weight"]') as HTMLInputElement
const at = BOOK_FONTS.sans.weights.indexOf(600)
expect(at).toBeGreaterThan(-1)
fireEvent.change(slider, { target: { value: String(at) } })
expect(el()).toMatchObject({ weight: 600 })
})
@@ -129,9 +129,6 @@ async function journeyWithBook() {
return { owner, editor, viewer, journey, inner, everyone: [owner.id, editor.id, viewer.id].sort((a, b) => a - b) };
}
/** A revision one past what this build reads. */
const NEWER = BOOK_SCHEMA_REV + 1;
describe('Studio book over MCP and REST', () => {
it('JBE2E-001: an MCP write is what GET reads next, and a viewer is refused in the words a tool answers', async () => {
const { editor, viewer, journey, inner } = await journeyWithBook();
@@ -35,9 +35,6 @@ import { BOOK_SCHEMA_REV, normalizeBookDocument } from '@trek/shared';
import { describe, it, expect, vi, beforeAll, beforeEach, afterAll } from 'vitest';
/** A format revision newer than this build reads. */
const NEWER = BOOK_SCHEMA_REV + 1;
vi.mock('../../../src/db/database', async () => {
const { createSnapshotTestDb } = await import('../../helpers/db-mock');
const db = createSnapshotTestDb();
+5 -2
View File
@@ -427,10 +427,13 @@ describe('TourPlanMcp: create_paddle_tour', () => {
expect(paddleRoute).toHaveBeenCalledWith(
expect.objectContaining({
boat: 'canoe',
// The router is asked with the bare coordinates: the names of the points stay with the tour.
legs: [
{ from: PADDLE_POINTS[0], to: PADDLE_POINTS[1] },
{ from: PADDLE_POINTS[1], to: PADDLE_POINTS[2] },
{ from: { lat: 48.1, lng: 11.6 }, to: { lat: 48.11, lng: 11.6 } },
{ from: { lat: 48.11, lng: 11.6 }, to: { lat: 48.12, lng: 11.6 } },
],
lake_style: 'direct',
lock_policy: 'auto',
}),
);
expect(created.route).toEqual({ planned: true });
+2 -1
View File
@@ -6,6 +6,7 @@ import {
BOOK_METRICS,
BOOK_SHAPES,
bookBadgeElementSchema,
bookCatalogueIdSchema,
bookCountriesElementSchema,
bookListElementSchema,
bookMapElementSchema,
@@ -47,7 +48,7 @@ export const bookFontIdSchema = z
.enum(BOOK_FONTS_IDS)
.describe(`Typeface by role; weights a family lacks snap to its nearest. ${bookFontIndex()}`);
/** The typeface of a travel element, where the full line above would repeat ten times. */
export const bookTypesetFontSchema = z.enum(BOOK_FONTS_IDS).describe('Typeface id, as for text.');
export const bookTypesetFontSchema = bookCatalogueIdSchema(BOOK_FONTS_IDS).describe('Typeface id, as for text.');
/** How heavy type is set, 100 thin to 900 black. */
export const bookWeightSchema = bookTextElementSchema.shape.weight
.unwrap()
+10 -4
View File
@@ -58,8 +58,14 @@ type ObjectFactory = typeof z.object | typeof z.strictObject;
* The union, built once for the document (plain objects, which drop a field
* they do not know, as the rest of the document does) and once for the
* operations (strict, as every operation is), so the two cannot drift.
*
* The document takes the pattern as a string held to BOOK_PATTERNS on parse:
* a page carries paint on its background and on every shape, twice over in the
* restore tool's schema (elements and parked), and the ids spelled out each
* time are what a model handing a page back never needs. The operations,
* where a model picks a pattern, keep the enum.
*/
function paintSchemas(obj: ObjectFactory) {
function paintSchemas(obj: ObjectFactory, pattern: z.ZodType<BookPattern, string>) {
const stop = obj({ at: z.number().min(0).max(1), color: hex, alpha: alpha.optional() });
const stops = z.array(stop).min(2).max(MAX_PAINT_STOPS);
const paint = z.discriminatedUnion('type', [
@@ -74,7 +80,7 @@ function paintSchemas(obj: ObjectFactory) {
}),
obj({
type: z.literal('pattern'),
pattern: z.enum(BOOK_PATTERNS),
pattern,
fg: hex,
bg: hex.nullable(),
scale: z.number().min(PATTERN_SCALE.min).max(PATTERN_SCALE.max),
@@ -84,7 +90,7 @@ function paintSchemas(obj: ObjectFactory) {
return { stop, paint };
}
const docSchemas = paintSchemas(z.object);
const docSchemas = paintSchemas(z.object, z.string().pipe(z.enum(BOOK_PATTERNS)));
export const bookPaintStopSchema = docSchemas.stop;
export const bookPaintSchema = docSchemas.paint;
@@ -97,7 +103,7 @@ export type BookPatternPaint = Extract<BookPaint, { type: 'pattern' }>;
* Paint as the page operations take it. Described once, here, because the
* tool schema is all a model reads of it and it appears in three places.
*/
export const bookPaintInSchema = paintSchemas(z.strictObject).paint.describe(
export const bookPaintInSchema = paintSchemas(z.strictObject, z.enum(BOOK_PATTERNS)).paint.describe(
'solid (alpha 0..1), linear (angle: 0 towards the top, 90 towards the right) or radial (cx, cy 0..1 of the box, r of half its diagonal) with 2 to 6 stops at 0..1, or a pattern: fg on bg (null shows through), scale 1 is an 8 mm cell.',
);
+19 -5
View File
@@ -160,6 +160,20 @@ export const BOOK_SHAPES = [
] as const;
export type BookShapeId = (typeof BOOK_SHAPES)[number];
/**
* A field that takes one id out of a long catalogue: a typeface, a shape.
*
* A tool's JSON schema shows it as a plain string, and the parse holds it to
* the catalogue, refusing an id it lacks with the ids it has. Spelled out as an
* enum it would be repeated wherever the field appears, on every element kind
* of a page, because the tool schemas carry no `$ref` to share it, and that
* repetition is what held the book tools over their size ceiling
* (MCP-SCHEMA-003 and 004 on the server). Where a model has to choose an id,
* the described enums of book-op-enums.ts still list them.
*/
export const bookCatalogueIdSchema = <const T extends readonly [string, ...string[]]>(ids: T) =>
z.string().pipe(z.enum(ids));
/**
* The families a book may be set in, and the weights type is set at. The
* catalogue is book-fonts.data.ts: which face each id names, its weights, its
@@ -230,7 +244,7 @@ export const bookPhotoElementSchema = z.object({
* makes a frame usable: you place a wide star across a spread and it is wide.
* A shape you cannot resize freely is an ornament, not a frame.
*/
mask: z.enum(BOOK_SHAPES).nullable().default(null),
mask: bookCatalogueIdSchema(BOOK_SHAPES).nullable().default(null),
/**
* Decoration *around* the picture — a Polaroid's thick chin, a print's white
* border, the shadow of a photo lying on a page.
@@ -245,7 +259,7 @@ export const bookTextElementSchema = z.object({
...elementBase,
kind: z.literal('text'),
text: z.string().max(MAX_TEXT_LENGTH).default(''),
font: z.enum(BOOK_FONTS_IDS).default('sans'),
font: bookCatalogueIdSchema(BOOK_FONTS_IDS).default('sans'),
/** Points. */
size: z.number().min(4).max(200).default(11),
weight: bookWeightSchema.default(400),
@@ -307,7 +321,7 @@ export const bookTextElementSchema = z.object({
export const bookShapeElementSchema = z.object({
...elementBase,
kind: z.literal('shape'),
shape: z.enum(BOOK_SHAPES).default('rect'),
shape: bookCatalogueIdSchema(BOOK_SHAPES).default('rect'),
fill: hex.nullable().default('#111827'),
/**
* Fade the fill out towards one edge. A cover almost always needs this: a
@@ -358,7 +372,7 @@ export const bookShapeElementSchema = z.object({
/** What the travel elements share with text: they are typeset, not drawn. */
const typeset = {
font: z.enum(BOOK_FONTS_IDS).default('sans'),
font: bookCatalogueIdSchema(BOOK_FONTS_IDS).default('sans'),
color: hex.default('#1a1a1a'),
/**
* The one colour that carries emphasis — the figure in a stat, the route on
@@ -930,7 +944,7 @@ export const bookPageNumbersSchema = z.object({
*/
autoColor: z.boolean().default(true),
color: hex.default('#8a8578'),
font: z.enum(BOOK_FONTS_IDS).default('sans'),
font: bookCatalogueIdSchema(BOOK_FONTS_IDS).default('sans'),
});
export type BookPageNumbers = z.infer<typeof bookPageNumbersSchema>;
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';
+1 -1
View File
@@ -59,9 +59,9 @@ import share from './share';
import shared from './shared';
import storage from './storage';
import studioFonts from './studioFonts';
import studioLayers from './studioLayers';
import studioPaint from './studioPaint';
import studioStickers from './studioStickers';
import studioLayers from './studioLayers';
import system_notice from './system_notice';
import todo from './todo';
import tourCollection from './tourCollection';