Skip to content

Commit

Permalink
Merge pull request #1548 from klembot/develop
Browse files Browse the repository at this point in the history
2.9.2
  • Loading branch information
klembot authored Jul 28, 2024
2 parents 0f64d02 + ceff39b commit 2a3bb40
Show file tree
Hide file tree
Showing 26 changed files with 114 additions and 60 deletions.
18 changes: 17 additions & 1 deletion docs/en/src/release-notes/2-9.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
# 2.9 versions

## 2.9.2

Release Date: July 28, 2024

## Bugs Fixed

- Browser Twine works in HTTP (e.g. nonsecure) contexts again. 2.9.1 introduced
a change that broke this.
- The layout of the preferences dialog is a little nicer.

## Story Format Updates

- Chapbook has been updated to version [2.2.0](https://klembot.github.io/chapbook/guide/references/version-history.html#220-28-july-2024).
- SugarCube has been updated to version [2.37.3](http://www.motoslave.net/sugarcube/2/releases.php).

## 2.9.1

Release Date: July 21, 2024

## Bugs Fixed

- Importing a story in browser Twine that replaces an existing one no longer creates duplicate stories.
- Importing a story in browser Twine that replaces an existing one no longer
creates duplicate stories.

## Behind the Scenes

Expand Down
24 changes: 22 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Twine",
"version": "2.9.1",
"version": "2.9.2",
"description": "a GUI for creating nonlinear stories",
"author": "Chris Klimas <chris@twinery.org>",
"license": "GPL-3.0",
Expand All @@ -14,6 +14,7 @@
"npm": ">=8"
},
"dependencies": {
"@lukeed/uuid": "^2.0.1",
"@popperjs/core": "^2.9.1",
"@tabler/icons": "^1.119.0",
"@testing-library/dom": "^9.3.1",
Expand Down
1 change: 0 additions & 1 deletion public/story-formats/chapbook-2.1.0/format.js

This file was deleted.

1 change: 1 addition & 0 deletions public/story-formats/chapbook-2.2.0/format.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion public/story-formats/sugarcube-2.37.0/format.js

This file was deleted.

1 change: 1 addition & 0 deletions public/story-formats/sugarcube-2.37.3/format.js

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions src/dialogs/app-prefs.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@
margin: 0;
}

.app-prefs-dialog .text-select > label {
width: 100%;
}

.app-prefs-dialog .text-select .text-select-control {
display: flex;
flex-grow: 1;
}

.app-prefs-dialog .text-select select {
flex-grow: 1;
}

.app-prefs-dialog .text-input,
.app-prefs-dialog input[type='text'] {
width: 100%;
Expand Down
5 changes: 0 additions & 5 deletions src/setupTests.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {toHaveNoViolations} from 'jest-axe';
import {configure} from '@testing-library/dom';
import '@testing-library/jest-dom';
import {faker} from '@faker-js/faker';
import 'jest-canvas-mock';

// Always mock these files so that Jest doesn't see import.meta.
Expand Down Expand Up @@ -51,9 +50,5 @@ afterEach(() => delete (window as any).matchMedia);
}
};

// ... and jsdom doesn't implement the crypto module, which we use to generate UUIDs.

(window as any).crypto.randomUUID = () => faker.string.uuid();

window.Element.prototype.releasePointerCapture = () => {};
window.Element.prototype.setPointerCapture = () => {};
3 changes: 2 additions & 1 deletion src/store/persistence/electron-ipc/story-formats/load.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {TwineElectronWindow} from '../../../../electron/shared';
import {StoryFormatsState} from '../../../story-formats/story-formats.types';

Expand All @@ -15,7 +16,7 @@ export async function load(): Promise<StoryFormatsState> {
}

return storyFormats.map(data => ({
id: window.crypto.randomUUID(),
id: uuid(),
loadState: 'unloaded',
name: data.name,
selected: false,
Expand Down
3 changes: 2 additions & 1 deletion src/store/persistence/local-storage/prefs/save.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {PrefsState} from '../../../prefs';

export function save(state: PrefsState) {
Expand All @@ -17,7 +18,7 @@ export function save(state: PrefsState) {
const ids: string[] = [];

for (const name in state) {
const id = window.crypto.randomUUID();
const id = uuid();

ids.push(id);
window.localStorage.setItem(
Expand Down
7 changes: 4 additions & 3 deletions src/store/persistence/local-storage/story-formats/save.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {StoryFormatsState} from '../../../story-formats/story-formats.types';

export function save(state: StoryFormatsState) {
Expand All @@ -17,8 +18,8 @@ export function save(state: StoryFormatsState) {

const ids: string[] = [];

state.forEach(format => {
const id = window.crypto.randomUUID();
for (const format of state) {
const id = uuid();

// We have to remove the `properties` property if it exists, as that is
// dynamically added when loading.
Expand All @@ -34,7 +35,7 @@ export function save(state: StoryFormatsState) {
selected: undefined
})
);
});
}

window.localStorage.setItem('twine-storyformats', ids.join(','));
}
3 changes: 2 additions & 1 deletion src/store/stories/action-creators/create-story.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {Thunk} from 'react-hook-thunk-reducer';
import {PrefsState} from '../../prefs';
import {StoriesAction, StoriesState, Story} from '../stories.types';
Expand All @@ -10,7 +11,7 @@ export function createStory(
prefs: PrefsState,
props: Partial<Omit<Story, 'id'>> & Pick<Story, 'name'>
): Thunk<StoriesState, StoriesAction> {
const id = window.crypto.randomUUID();
const id = uuid();

if (props.name.trim() === '') {
throw new Error('Story name cannot be empty');
Expand Down
7 changes: 4 additions & 3 deletions src/store/stories/action-creators/duplicate-story.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {CreateStoryAction, Story} from '../stories.types';
import {unusedName} from '../../../util/unused-name';

Expand All @@ -8,21 +9,21 @@ export function duplicateStory(
story: Story,
stories: Story[]
): CreateStoryAction {
const id = window.crypto.randomUUID();
const id = uuid();

return {
type: 'createStory',
props: {
...story,
id,
ifid: window.crypto.randomUUID(),
ifid: uuid(),
name: unusedName(
story.name,
stories.map(story => story.name)
),
passages: story.passages.map(passage => ({
...passage,
id: window.crypto.randomUUID(),
id: uuid(),
story: id
}))
}
Expand Down
3 changes: 2 additions & 1 deletion src/store/stories/reducer/create-passage.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {passageDefaults} from '../defaults';
import {Passage, Story, StoriesState} from '../stories.types';

Expand Down Expand Up @@ -34,7 +35,7 @@ export function createPassage(

const newPassage: Passage = {
...passageDefaults(),
id: window.crypto.randomUUID(),
id: uuid(),
...passageProps,
story: story.id
};
Expand Down
5 changes: 3 additions & 2 deletions src/store/stories/reducer/create-story.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {passageDefaults, storyDefaults} from '../defaults';
import {Story, StoriesState} from '../stories.types';

Expand All @@ -20,9 +21,9 @@ export function createStory(state: StoriesState, storyProps: Partial<Story>) {
}

const story: Story = {
id: window.crypto.randomUUID(),
id: uuid(),
...storyDefaults(),
ifid: window.crypto.randomUUID().toUpperCase(),
ifid: uuid().toUpperCase(),
lastUpdate: new Date(),
passages: [],
tags: [],
Expand Down
20 changes: 11 additions & 9 deletions src/store/stories/reducer/repair/repair-passage.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {passageDefaults} from '../../defaults';
import {Passage, Story} from '../../stories.types';

Expand Down Expand Up @@ -25,15 +26,16 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
// Give the passage an ID if it has none.

if (typeof passage.id !== 'string' || passage.id === '') {
const newId = window.crypto.randomUUID();
const newId = uuid();

logRepair(passage, 'id', newId, 'was undefined or empty string');
repairs.id = window.crypto.randomUUID();
repairs.id = newId;
}

// Apply default properties to the passage.

Object.entries(passageDefs).forEach(([key, value]) => {
for (const key in passageDefs) {
const value = passageDefs[key as keyof typeof passageDefs];
const defKey = key as keyof typeof passageDefs;

if (
Expand All @@ -43,11 +45,11 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
logRepair(passage, defKey, passageDefs[defKey]);
(repairs[defKey] as Passage[typeof defKey]) = passageDefs[defKey];
}
});
}

// Make passage coordinates 0 or greater.

['left', 'top'].forEach(pos => {
for (const pos of ['left', 'top']) {
const posKey = pos as keyof Passage;

if (
Expand All @@ -57,11 +59,11 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
logRepair(passage, posKey, 0, 'was negative');
(repairs[posKey] as Passage[typeof posKey]) = 0;
}
});
}

// Make passage dimensions 5 or greater.

['height', 'width'].forEach(dim => {
for (const dim of ['height', 'width']) {
const dimKey = dim as keyof Passage;

if (
Expand All @@ -71,7 +73,7 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
logRepair(passage, dimKey, 0, 'was less than 5');
(repairs[dimKey] as Passage[typeof dimKey]) = 5;
}
});
}

// Repair story property if it doesn't point to the parent story.

Expand All @@ -91,7 +93,7 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
return otherPassage.id === passage.id;
})
) {
const newId = window.crypto.randomUUID();
const newId = uuid();

logRepair(
passage,
Expand Down
12 changes: 7 additions & 5 deletions src/store/stories/reducer/repair/repair-story.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {satisfies} from 'semver';
import {Story} from '../../stories.types';
import {storyDefaults} from '../../defaults';
Expand Down Expand Up @@ -33,7 +34,7 @@ export function repairStory(
// Give the story an ID if it has none.

if (typeof story.id !== 'string' || story.id === '') {
const newId = window.crypto.randomUUID();
const newId = uuid();

logRepair(story, 'id', newId, 'was bad type or empty string');
repairs.id = newId;
Expand All @@ -42,16 +43,17 @@ export function repairStory(
// Give the story an IFID if it has none.

if (typeof story.ifid !== 'string' || story.id === '') {
const newIfid = window.crypto.randomUUID();
const newIfid = uuid();

logRepair(story, 'ifid', newIfid, 'was bad type or empty string');
repairs.ifid = newIfid;
}

// Apply default properties to the story.

Object.entries(storyDefs).forEach(([key, value]) => {
for (const key in storyDefs) {
const defKey = key as keyof typeof storyDefs;
const value = storyDefs[defKey];

if (
(typeof value === 'number' && !Number.isFinite(story[defKey])) ||
Expand All @@ -60,7 +62,7 @@ export function repairStory(
logRepair(story, defKey, storyDefs[defKey]);
(repairs[defKey] as Story[typeof defKey]) = storyDefs[defKey];
}
});
}

if (
typeof story.storyFormat !== 'string' ||
Expand Down Expand Up @@ -144,7 +146,7 @@ export function repairStory(
return otherStory.id === story.id;
})
) {
const newId = window.crypto.randomUUID();
const newId = uuid();

logRepair(story, 'id', newId, "conflicted with another story's ID");
repairs.id = newId;
Expand Down
8 changes: 4 additions & 4 deletions src/store/story-formats/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export const builtins = () => [
},
{
name: 'Chapbook',
url: 'story-formats/chapbook-2.1.0/format.js',
version: '2.1.0'
url: 'story-formats/chapbook-2.2.0/format.js',
version: '2.2.0'
},
{
name: 'Harlowe',
Expand Down Expand Up @@ -47,7 +47,7 @@ export const builtins = () => [
},
{
name: 'SugarCube',
url: 'story-formats/sugarcube-2.37.0/format.js',
version: '2.37.0'
url: 'story-formats/sugarcube-2.37.3/format.js',
version: '2.37.3'
}
];
Loading

0 comments on commit 2a3bb40

Please sign in to comment.