[fix] Don't synchronize isReadOnly (#1396)
We were storing the state of whether or not a document is read-only in the store. It does not need to be stored there, and it was creating consistency problems for us, so let's not store it in there. fixes https://github.com/tldraw/brivate/issues/1864 ### Change Type <!-- 💡 Indicate the type of change your pull request is. --> <!-- 🤷♀️ If you're not sure, don't select anything --> <!-- ✂️ Feel free to delete unselected options --> <!-- To select one, put an x in the box: [x] --> - [ ] `patch` — Bug Fix - [ ] `minor` — New Feature - [x] `major` — Breaking Change - [ ] `dependencies` — Dependency Update (publishes a `patch` release, for devDependencies use `internal`) - [ ] `documentation` — Changes to the documentation only (will not publish a new version) - [ ] `tests` — Changes to any testing-related code only (will not publish a new version) - [ ] `internal` — Any other changes that don't affect the published package (will not publish a new version) ### Test Plan 1. Create a multiplayer room 2. Create a read-only link for the room 3. Paste the link into a new browser tab (not incognito, needs to have the same session state) 4. Check the room is read-only in the new tab 5. Check the room is still writable in the previous tab. ### Release Notes - Removes the isReadOnly value from the `user_document_settings` record type.
This commit is contained in:
parent
01487be6fa
commit
a3896fc492
9 changed files with 75 additions and 27 deletions
|
@ -32,6 +32,11 @@ export function generateSharedScripts(bublic: '<rootDir>' | '<rootDir>/bublic')
|
|||
test: {
|
||||
baseCommand: 'yarn run -T jest',
|
||||
runsAfter: { 'refresh-assets': {} },
|
||||
cache: {
|
||||
inputs: {
|
||||
exclude: ['*.tsbuildinfo'],
|
||||
},
|
||||
},
|
||||
},
|
||||
'test-coverage': {
|
||||
baseCommand: 'yarn run -T jest --coverage',
|
||||
|
@ -42,7 +47,7 @@ export function generateSharedScripts(bublic: '<rootDir>' | '<rootDir>/bublic')
|
|||
runsAfter: { 'build-types': {} },
|
||||
cache: {
|
||||
inputs: {
|
||||
exclude: ['**/*.tsbuildinfo'],
|
||||
exclude: ['*.tsbuildinfo'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -456,7 +456,7 @@ export class App extends EventEmitter<TLEventMap> {
|
|||
// (undocumented)
|
||||
setPenMode(isPenMode: boolean): this;
|
||||
setProp(key: TLShapeProp, value: any, ephemeral?: boolean, squashing?: boolean): this;
|
||||
// (undocumented)
|
||||
// @internal (undocumented)
|
||||
setReadOnly(isReadOnly: boolean): this;
|
||||
setScribble(scribble?: null | TLScribble): this;
|
||||
setSelectedIds(ids: TLShapeId[], squashing?: boolean): this;
|
||||
|
|
|
@ -1564,20 +1564,21 @@ export class App extends EventEmitter<TLEventMap> {
|
|||
return this
|
||||
}
|
||||
|
||||
get isReadOnly() {
|
||||
return this.userDocumentSettings.isReadOnly
|
||||
}
|
||||
private _isReadOnly = atom<boolean>('isReadOnly', false as any)
|
||||
|
||||
/** @internal */
|
||||
setReadOnly(isReadOnly: boolean): this {
|
||||
if (isReadOnly !== this.isReadOnly) {
|
||||
this.updateUserDocumentSettings({ isReadOnly }, true)
|
||||
if (isReadOnly) {
|
||||
this.setSelectedTool('hand')
|
||||
}
|
||||
this._isReadOnly.set(isReadOnly)
|
||||
if (isReadOnly) {
|
||||
this.setSelectedTool('hand')
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
get isReadOnly() {
|
||||
return this._isReadOnly.value
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
private _isPenMode = atom<boolean>('isPenMode', false as any)
|
||||
|
||||
|
|
|
@ -408,7 +408,8 @@ describe('When in readonly mode', () => {
|
|||
props: { opacity: '1', w: 100, h: 100, url: '', doesResize: false },
|
||||
},
|
||||
])
|
||||
app.updateUserDocumentSettings({ isReadOnly: true })
|
||||
app.setReadOnly(true)
|
||||
app.setSelectedTool('select')
|
||||
})
|
||||
|
||||
it('Begins editing embed when double clicked', () => {
|
||||
|
|
|
@ -274,7 +274,7 @@ describe('creating groups', () => {
|
|||
// │ A │ │ B │ │ C │
|
||||
// └───┘ └───┘ └───┘
|
||||
app.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
|
||||
app.updateUserDocumentSettings({ isReadOnly: true })
|
||||
app.setReadOnly(true)
|
||||
app.selectAll()
|
||||
expect(app.selectedIds.length).toBe(3)
|
||||
app.groupShapes()
|
||||
|
@ -485,8 +485,8 @@ describe('ungrouping shapes', () => {
|
|||
expect(app.selectedIds.length).toBe(3)
|
||||
app.groupShapes()
|
||||
expect(app.selectedIds.length).toBe(1)
|
||||
app.setReadOnly(true)
|
||||
|
||||
app.updateUserDocumentSettings({ isReadOnly: true })
|
||||
app.ungroupShapes()
|
||||
expect(app.selectedIds.length).toBe(1)
|
||||
expect(onlySelectedShape().type).toBe(TLGroupUtil.type)
|
||||
|
|
|
@ -1290,8 +1290,6 @@ export interface TLUserDocument extends BaseRecord<'user_document'> {
|
|||
// (undocumented)
|
||||
isPenMode: boolean;
|
||||
// (undocumented)
|
||||
isReadOnly: boolean;
|
||||
// (undocumented)
|
||||
isSnapMode: boolean;
|
||||
// (undocumented)
|
||||
lastUpdatedPageId: ID<TLPage> | null;
|
||||
|
|
|
@ -6,7 +6,7 @@ import { videoAssetMigrations } from './assets/TLVideoAsset'
|
|||
import { instanceTypeMigrations } from './records/TLInstance'
|
||||
import { instancePageStateMigrations } from './records/TLInstancePageState'
|
||||
import { rootShapeTypeMigrations, TLShape } from './records/TLShape'
|
||||
import { userDocumentTypeMigrations } from './records/TLUserDocument'
|
||||
import { userDocumentTypeMigrations, userDocumentVersions } from './records/TLUserDocument'
|
||||
import { userPresenceTypeMigrations } from './records/TLUserPresence'
|
||||
import { storeMigrations } from './schema'
|
||||
import { arrowShapeMigrations } from './shapes/TLArrowShape'
|
||||
|
@ -665,6 +665,45 @@ describe('Adding check-box to geo shape', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('Removing isReadOnly from user_document', () => {
|
||||
const { up, down } = userDocumentTypeMigrations.migrators[userDocumentVersions.RemoveIsReadOnly]
|
||||
const prev = {
|
||||
id: 'user_document:123',
|
||||
typeName: 'user_document',
|
||||
userId: 'user:123',
|
||||
isReadOnly: false,
|
||||
isPenMode: false,
|
||||
isGridMode: false,
|
||||
isDarkMode: false,
|
||||
isMobileMode: false,
|
||||
isSnapMode: false,
|
||||
lastUpdatedPageId: null,
|
||||
lastUsedTabId: null,
|
||||
}
|
||||
|
||||
const next = {
|
||||
id: 'user_document:123',
|
||||
typeName: 'user_document',
|
||||
userId: 'user:123',
|
||||
isPenMode: false,
|
||||
isGridMode: false,
|
||||
isDarkMode: false,
|
||||
isMobileMode: false,
|
||||
isSnapMode: false,
|
||||
lastUpdatedPageId: null,
|
||||
lastUsedTabId: null,
|
||||
}
|
||||
|
||||
test('up removes the isReadOnly property', () => {
|
||||
expect(up(prev)).toEqual(next)
|
||||
})
|
||||
test('down adds the isReadOnly property', () => {
|
||||
expect(down(next)).toEqual(prev)
|
||||
})
|
||||
})
|
||||
|
||||
/* --- PUT YOU
|
||||
|
||||
/* --- PUT YOUR MIGRATIONS TESTS ABOVE HERE --- */
|
||||
|
||||
for (const migrator of allMigrators) {
|
||||
|
|
|
@ -14,7 +14,6 @@ import { TLUserId } from './TLUser'
|
|||
*/
|
||||
export interface TLUserDocument extends BaseRecord<'user_document'> {
|
||||
userId: TLUserId
|
||||
isReadOnly: boolean
|
||||
isPenMode: boolean
|
||||
isGridMode: boolean
|
||||
isDarkMode: boolean
|
||||
|
@ -35,7 +34,6 @@ export const userDocumentTypeValidator: T.Validator<TLUserDocument> = T.model(
|
|||
typeName: T.literal('user_document'),
|
||||
id: idValidator<TLUserDocumentId>('user_document'),
|
||||
userId: userIdValidator,
|
||||
isReadOnly: T.boolean,
|
||||
isPenMode: T.boolean,
|
||||
isGridMode: T.boolean,
|
||||
isDarkMode: T.boolean,
|
||||
|
@ -49,20 +47,21 @@ export const userDocumentTypeValidator: T.Validator<TLUserDocument> = T.model(
|
|||
// --- MIGRATIONS ---
|
||||
// STEP 1: Add a new version number here, give it a meaningful name.
|
||||
// It should be 1 higher than the current version
|
||||
const Versions = {
|
||||
export const userDocumentVersions = {
|
||||
Initial: 0,
|
||||
AddSnapMode: 1,
|
||||
AddMissingIsMobileMode: 2,
|
||||
RemoveIsReadOnly: 3,
|
||||
} as const
|
||||
|
||||
/** @public */
|
||||
export const userDocumentTypeMigrations = defineMigrations({
|
||||
firstVersion: Versions.Initial,
|
||||
firstVersion: userDocumentVersions.Initial,
|
||||
// STEP 2: Update the current version to point to your latest version
|
||||
currentVersion: Versions.AddMissingIsMobileMode,
|
||||
currentVersion: userDocumentVersions.RemoveIsReadOnly,
|
||||
// STEP 3: Add an up+down migration for the new version here
|
||||
migrators: {
|
||||
[Versions.AddSnapMode]: {
|
||||
[userDocumentVersions.AddSnapMode]: {
|
||||
up: (userDocument: TLUserDocument) => {
|
||||
return { ...userDocument, isSnapMode: false }
|
||||
},
|
||||
|
@ -70,7 +69,7 @@ export const userDocumentTypeMigrations = defineMigrations({
|
|||
return userDocument
|
||||
},
|
||||
},
|
||||
[Versions.AddMissingIsMobileMode]: {
|
||||
[userDocumentVersions.AddMissingIsMobileMode]: {
|
||||
up: (userDocument: TLUserDocument) => {
|
||||
return { ...userDocument, isMobileMode: userDocument.isMobileMode ?? false }
|
||||
},
|
||||
|
@ -78,6 +77,14 @@ export const userDocumentTypeMigrations = defineMigrations({
|
|||
return userDocument
|
||||
},
|
||||
},
|
||||
[userDocumentVersions.RemoveIsReadOnly]: {
|
||||
up: ({ isReadOnly: _, ...userDocument }: TLUserDocument & { isReadOnly: boolean }) => {
|
||||
return userDocument
|
||||
},
|
||||
down: (userDocument: TLUserDocument) => {
|
||||
return { ...userDocument, isReadOnly: false }
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
/* STEP 4: Add your changes to the record type */
|
||||
|
@ -91,7 +98,6 @@ export const TLUserDocument = createRecordType<TLUserDocument>('user_document',
|
|||
}).withDefaultProperties(
|
||||
(): Omit<TLUserDocument, 'id' | 'typeName' | 'userId'> => ({
|
||||
/* STEP 6: Add any new default values for properties here */
|
||||
isReadOnly: false,
|
||||
isPenMode: false,
|
||||
isGridMode: false,
|
||||
isDarkMode: false,
|
||||
|
|
|
@ -181,9 +181,7 @@ function DebugMenuContent({
|
|||
<DropdownMenu.Item
|
||||
onClick={() => {
|
||||
// We need to do this manually because `updateUserDocumentSettings` does not allow toggling `isReadOnly`)
|
||||
app.store.put([
|
||||
{ ...app.userDocumentSettings, isReadOnly: !app.userDocumentSettings.isReadOnly },
|
||||
])
|
||||
app.setReadOnly(!app.isReadOnly)
|
||||
}}
|
||||
>
|
||||
<span>Toggle read-only</span>
|
||||
|
|
Loading…
Reference in a new issue