diff --git a/CALCKEY.md b/CALCKEY.md
index a23953b3f..7eb807867 100644
--- a/CALCKEY.md
+++ b/CALCKEY.md
@@ -85,6 +85,7 @@
- Link hover effect
- Replace all `$ts` with i18n
- AVIF support
+- Page drafts
- Obliteration of Ai-chan
- [Make showing ads optional](https://github.com/misskey-dev/misskey/pull/8996)
- [Tapping avatar in mobile opens account modal](https://github.com/misskey-dev/misskey/pull/9056)
diff --git a/package.json b/package.json
index d43fb4679..2b40098ee 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "calckey",
- "version": "12.119.0-calc.15-beta.8",
+ "version": "12.119.0-calc.15-beta.9",
"codename": "aqua",
"repository": {
"type": "git",
diff --git a/packages/backend/src/models/entities/page.ts b/packages/backend/src/models/entities/page.ts
index baad3a36f..fac59479e 100644
--- a/packages/backend/src/models/entities/page.ts
+++ b/packages/backend/src/models/entities/page.ts
@@ -40,6 +40,9 @@ export class Page {
@Column('boolean')
public alignCenter: boolean;
+ @Column('boolean')
+ public isPublic: boolean;
+
@Column('boolean', {
default: false,
})
diff --git a/packages/backend/src/models/repositories/page.ts b/packages/backend/src/models/repositories/page.ts
index 092b26b39..65b54f8b8 100644
--- a/packages/backend/src/models/repositories/page.ts
+++ b/packages/backend/src/models/repositories/page.ts
@@ -65,6 +65,7 @@ export const PageRepository = db.getRepository(Page).extend({
content: page.content,
variables: page.variables,
title: page.title,
+ isPublic: page.isPublic,
name: page.name,
summary: page.summary,
hideTitleWhenPinned: page.hideTitleWhenPinned,
diff --git a/packages/backend/src/models/schema/page.ts b/packages/backend/src/models/schema/page.ts
index 55ba3ce7f..19074947b 100644
--- a/packages/backend/src/models/schema/page.ts
+++ b/packages/backend/src/models/schema/page.ts
@@ -47,5 +47,9 @@ export const packedPageSchema = {
ref: 'UserLite',
optional: false, nullable: false,
},
+ isPublic: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
},
} as const;
diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts
index e7b78fb38..063faf6ec 100644
--- a/packages/backend/src/server/api/endpoints/pages/create.ts
+++ b/packages/backend/src/server/api/endpoints/pages/create.ts
@@ -53,6 +53,7 @@ export const paramDef = {
eyeCatchingImageId: { type: 'string', format: 'misskey:id', nullable: true },
font: { type: 'string', enum: ['serif', 'sans-serif'], default: 'sans-serif' },
alignCenter: { type: 'boolean', default: false },
+ isPublic: { type: 'boolean', default: true },
hideTitleWhenPinned: { type: 'boolean', default: false },
},
required: ['title', 'name', 'content', 'variables', 'script'],
@@ -97,6 +98,7 @@ export default define(meta, paramDef, async (ps, user) => {
alignCenter: ps.alignCenter,
hideTitleWhenPinned: ps.hideTitleWhenPinned,
font: ps.font,
+ isPublic: ps.isPublic,
})).then(x => Pages.findOneByOrFail(x.identifiers[0]));
return await Pages.pack(page);
diff --git a/packages/backend/src/server/api/endpoints/pages/show.ts b/packages/backend/src/server/api/endpoints/pages/show.ts
index 54ae43deb..384975af7 100644
--- a/packages/backend/src/server/api/endpoints/pages/show.ts
+++ b/packages/backend/src/server/api/endpoints/pages/show.ts
@@ -67,5 +67,9 @@ export default define(meta, paramDef, async (ps, user) => {
throw new ApiError(meta.errors.noSuchPage);
}
+ if (!page.isPublic && (user == null || (page.userId !== user.id))) {
+ throw new ApiError(meta.errors.noSuchPage);
+ }
+
return await Pages.pack(page, user);
});
diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts
index 8230ea09b..585e9e73e 100644
--- a/packages/backend/src/server/api/endpoints/pages/update.ts
+++ b/packages/backend/src/server/api/endpoints/pages/update.ts
@@ -60,6 +60,7 @@ export const paramDef = {
font: { type: 'string', enum: ['serif', 'sans-serif'] },
alignCenter: { type: 'boolean' },
hideTitleWhenPinned: { type: 'boolean' },
+ isPublic: { type: 'boolean' },
},
required: ['pageId', 'title', 'name', 'content', 'variables', 'script'],
} as const;
@@ -104,6 +105,7 @@ export default define(meta, paramDef, async (ps, user) => {
content: ps.content,
variables: ps.variables,
script: ps.script,
+ isPublic: ps.isPublic,
alignCenter: ps.alignCenter === undefined ? page.alignCenter : ps.alignCenter,
hideTitleWhenPinned: ps.hideTitleWhenPinned === undefined ? page.hideTitleWhenPinned : ps.hideTitleWhenPinned,
font: ps.font === undefined ? page.font : ps.font,
diff --git a/packages/backend/src/server/api/endpoints/users/pages.ts b/packages/backend/src/server/api/endpoints/users/pages.ts
index e1d876e6b..b76071264 100644
--- a/packages/backend/src/server/api/endpoints/users/pages.ts
+++ b/packages/backend/src/server/api/endpoints/users/pages.ts
@@ -34,7 +34,8 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const query = makePaginationQuery(Pages.createQueryBuilder('page'), ps.sinceId, ps.untilId)
.andWhere('page.userId = :userId', { userId: ps.userId })
- .andWhere('page.visibility = \'public\'');
+ .andWhere('page.visibility = \'public\'')
+ .andWhere('page.isPublic = true');
const pages = await query
.take(ps.limit)
diff --git a/packages/client/src/pages/clip.vue b/packages/client/src/pages/clip.vue
index 0c779914a..232cc9da1 100644
--- a/packages/client/src/pages/clip.vue
+++ b/packages/client/src/pages/clip.vue
@@ -48,7 +48,7 @@ watch(() => props.clipId, async () => {
});
}, {
immediate: true,
-});
+});
provide('currentClipPage', $$(clip));
diff --git a/packages/client/src/pages/page-editor/page-editor.vue b/packages/client/src/pages/page-editor/page-editor.vue
index fb8e11e52..498dac62b 100644
--- a/packages/client/src/pages/page-editor/page-editor.vue
+++ b/packages/client/src/pages/page-editor/page-editor.vue
@@ -24,6 +24,7 @@
{{ i18n.ts._pages.url }}
+ {{ i18n.ts._pages.isPublic }}
{{ i18n.ts._pages.alignCenter }}
@@ -130,6 +131,7 @@ let eyeCatchingImageId = $ref(null);
let font = $ref('sans-serif');
let content = $ref([]);
let alignCenter = $ref(false);
+let isPublic = $ref(true);
let hideTitleWhenPinned = $ref(false);
let variables = $ref([]);
let hpml = $ref(null);
@@ -158,6 +160,7 @@ function getSaveOptions() {
script: script,
hideTitleWhenPinned: hideTitleWhenPinned,
alignCenter: alignCenter,
+ isPublic: isPublic,
content: content,
variables: variables,
eyeCatchingImageId: eyeCatchingImageId,
@@ -393,6 +396,7 @@ async function init() {
script = page.script;
hideTitleWhenPinned = page.hideTitleWhenPinned;
alignCenter = page.alignCenter;
+ isPublic = page.isPublic;
content = page.content;
variables = page.variables;
eyeCatchingImageId = page.eyeCatchingImageId;
@@ -401,7 +405,7 @@ async function init() {
content = [{
id,
type: 'text',
- text: 'Hello World!',
+ text: '',
}];
}
}