The crop tool now exposes a landscape/portrait toggle next to the device-name label, and the canvas crop frame snaps to the chosen aspect when toggled. Choosing an orientation that does not match the target frame's current orientation surfaces a yellow informational chip — purely informational, no action required, clears as soon as the user toggles back to the matching orientation (or changes the frame in Settings). The chosen orientation rides along on the upload/reprocess request as a new cropOrientation form field and is persisted on the Image entity, so the library view and rotation logic can later surface the same mismatch state for already-uploaded photos. Existing photos without a stored orientation get null and are unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ const makeImage = (overrides: Partial<Image> = {}): Image => ({
|
||||
approvedDeviceIds: [],
|
||||
cropParams: null,
|
||||
stickerState: null,
|
||||
cropOrientation: null,
|
||||
...overrides,
|
||||
})
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('upload store', () => {
|
||||
expect(store.selectedDeviceIds).toEqual([])
|
||||
})
|
||||
|
||||
it('setCrop stores croppedBlob and cropParams', () => {
|
||||
it('setCrop stores croppedBlob, cropParams, and cropOrientation', () => {
|
||||
const store = useUploadStore()
|
||||
const file = new File(['data'], 'photo.jpg')
|
||||
store.init(file)
|
||||
@@ -67,12 +67,13 @@ describe('upload store', () => {
|
||||
const blob = new Blob(['crop'], { type: 'image/jpeg' })
|
||||
const params = { natX: 0, natY: 0, natW: 200, natH: 200 }
|
||||
|
||||
store.setCrop(blob, params)
|
||||
store.setCrop(blob, params, 'portrait')
|
||||
|
||||
// Pinia wraps refs in a reactive proxy, use toStrictEqual for value equality
|
||||
expect(store.croppedBlob).toStrictEqual(blob)
|
||||
expect(store.croppedUrl).toBe('blob:mock-url')
|
||||
expect(store.cropParams).toEqual(params)
|
||||
expect(store.cropOrientation).toBe('portrait')
|
||||
})
|
||||
|
||||
it('addSticker appends to stickers', () => {
|
||||
@@ -137,6 +138,7 @@ describe('upload store', () => {
|
||||
expect(store.croppedBlob).toBeNull()
|
||||
expect(store.croppedUrl).toBeNull()
|
||||
expect(store.cropParams).toBeNull()
|
||||
expect(store.cropOrientation).toBeNull()
|
||||
expect(store.stickers).toHaveLength(0)
|
||||
expect(store.contextDeviceId).toBeNull()
|
||||
expect(store.selectedDeviceIds).toEqual([])
|
||||
|
||||
@@ -65,6 +65,7 @@ const makeImage = (overrides: Partial<Image> = {}): Image => ({
|
||||
approvedDeviceIds: [],
|
||||
cropParams: null,
|
||||
stickerState: null,
|
||||
cropOrientation: null,
|
||||
...overrides,
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user