feat: クライアントのアップデート通知を改善

This commit is contained in:
NoriDev 2023-10-04 21:09:54 +09:00
parent 4ab2c3766d
commit b94731163a
17 changed files with 87 additions and 9 deletions

View file

@ -34,7 +34,9 @@ Misskey의 전체 변경 사항을 확인하려면, [CHANGELOG.md#2023xx](CHANGE
> 문제가 발생하면 '설정 - 캐시 비우기'를 진행하거나, 브라우저 캐시를 삭제하십시오. > 문제가 발생하면 '설정 - 캐시 비우기'를 진행하거나, 브라우저 캐시를 삭제하십시오.
### Client ### Client
- Feat: 클라이언트 업데이트 알림 채널을 선택할 수 있음 - Feat: 클라이언트 업데이트 알림 개선
- 알림 채널을 선택할 수 있음
- 다음 릴리즈 출시까지 알리지 않도록 설정할 수 있음
- Enhance: 그룹 대화에서 읽음 표시를 개선 - Enhance: 그룹 대화에서 읽음 표시를 개선
- Fix: 서브 노트 기능 오류 - Fix: 서브 노트 기능 오류
- 서브 노트에서 더 보기 버튼을 사용할 수 없음 - 서브 노트에서 더 보기 버튼을 사용할 수 없음

View file

@ -1,5 +1,6 @@
--- ---
_lang_: "English" _lang_: "English"
skipThisVersion: "Skip this release"
enableReceivePrerelease: "Get notified of pre-release versions" enableReceivePrerelease: "Get notified of pre-release versions"
youAreRunningBetaClient: "Unreleased version of CherryPick in use!" youAreRunningBetaClient: "Unreleased version of CherryPick in use!"
cherrypickUpdate: "CherryPick Update" cherrypickUpdate: "CherryPick Update"

1
locales/index.d.ts vendored
View file

@ -3,6 +3,7 @@
// Do not edit this file directly. // Do not edit this file directly.
export interface Locale { export interface Locale {
"_lang_": string; "_lang_": string;
"skipThisVersion": string;
"enableReceivePrerelease": string; "enableReceivePrerelease": string;
"youAreRunningBetaClient": string; "youAreRunningBetaClient": string;
"cherrypickUpdate": string; "cherrypickUpdate": string;

View file

@ -1,5 +1,6 @@
_lang_: "日本語" _lang_: "日本語"
skipThisVersion: "このリリースをスキップする"
enableReceivePrerelease: "プレリリース版の通知を受け取る" enableReceivePrerelease: "プレリリース版の通知を受け取る"
youAreRunningBetaClient: "未発売バージョンのCherryPickを利用しています" youAreRunningBetaClient: "未発売バージョンのCherryPickを利用しています"
cherrypickUpdate: "CherryPickアップデート" cherrypickUpdate: "CherryPickアップデート"

View file

@ -1,5 +1,6 @@
--- ---
_lang_: "한국어" _lang_: "한국어"
skipThisVersion: "이 릴리즈 건너뛰기"
enableReceivePrerelease: "출시 전 버전 알림 받기" enableReceivePrerelease: "출시 전 버전 알림 받기"
youAreRunningBetaClient: "아직 출시되지 않은 버전의 CherryPick를 이용하고 있어요!" youAreRunningBetaClient: "아직 출시되지 않은 버전의 CherryPick를 이용하고 있어요!"
cherrypickUpdate: "CherryPick 업데이트" cherrypickUpdate: "CherryPick 업데이트"

View file

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: syuilo and noridev and other misskey, cherrypick contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class AddMetaOptions1696417300000 {
name = 'AddMetaOptions1696417300000'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "skipVersion" boolean NOT NULL DEFAULT false`);
await queryRunner.query(`ALTER TABLE "meta" ADD "skipCherryPickVersion" character varying(32)`, undefined);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "skipVersion"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "skipCherryPickVersion"`);
}
}

View file

@ -594,4 +594,15 @@ export class MiMeta {
default: false, default: false,
}) })
public enableReceivePrerelease: boolean; public enableReceivePrerelease: boolean;
@Column('boolean', {
default: false,
})
public skipVersion: boolean;
@Column('varchar', {
length: 32,
nullable: true,
})
public skipCherryPickVersion: string | null;
} }

View file

@ -358,6 +358,14 @@ export const meta = {
type: 'boolean', type: 'boolean',
optional: false, nullable: false, optional: false, nullable: false,
}, },
skipVersion: {
type: 'boolean',
optional: false, nullable: false,
},
skipCherryPickVersion: {
type: 'string',
optional: true, nullable: true,
},
}, },
}, },
} as const; } as const;
@ -489,6 +497,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
policies: { ...DEFAULT_POLICIES, ...instance.policies }, policies: { ...DEFAULT_POLICIES, ...instance.policies },
manifestJsonOverride: instance.manifestJsonOverride, manifestJsonOverride: instance.manifestJsonOverride,
enableReceivePrerelease: instance.enableReceivePrerelease, enableReceivePrerelease: instance.enableReceivePrerelease,
skipVersion: instance.skipVersion,
skipCherryPickVersion: instance.skipCherryPickVersion,
}; };
}); });
} }

View file

@ -131,6 +131,9 @@ export const paramDef = {
serverRules: { type: 'array', items: { type: 'string' } }, serverRules: { type: 'array', items: { type: 'string' } },
preservedUsernames: { type: 'array', items: { type: 'string' } }, preservedUsernames: { type: 'array', items: { type: 'string' } },
manifestJsonOverride: { type: 'string' }, manifestJsonOverride: { type: 'string' },
enableReceivePrerelease: { type: 'boolean' },
skipVersion: { type: 'boolean' },
skipCherryPickVersion: { type: 'string', nullable: true },
}, },
required: [], required: [],
} as const; } as const;
@ -557,6 +560,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
set.enableReceivePrerelease = ps.enableReceivePrerelease; set.enableReceivePrerelease = ps.enableReceivePrerelease;
} }
if (ps.skipVersion !== undefined) {
set.skipVersion = ps.skipVersion;
}
if (ps.skipCherryPickVersion !== undefined) {
set.skipCherryPickVersion = ps.skipCherryPickVersion;
}
const before = await this.metaService.fetch(true); const before = await this.metaService.fetch(true);
await this.metaService.update(set); await this.metaService.update(set);

View file

@ -80,7 +80,7 @@ fetch('https://api.github.com/repos/kokonect-link/cherrypick/releases', {
const meta = await os.api('admin/meta'); const meta = await os.api('admin/meta');
if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true); if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true);
else releasesCherryPick = res.filter(x => x.prerelease === false); else releasesCherryPick = res.filter(x => x.prerelease === false);
if (version < releasesCherryPick[0].tag_name) updateAvailable = true; if ((version < releasesCherryPick[0].tag_name) && (meta.skipCherryPickVersion < releasesCherryPick[0].tag_name)) updateAvailable = true;
}); });
const NARROW_THRESHOLD = 600; const NARROW_THRESHOLD = 600;

View file

@ -27,11 +27,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #key>{{ i18n.ts.currentVersion }} <i class="ti ti-external-link"></i></template> <template #key>{{ i18n.ts.currentVersion }} <i class="ti ti-external-link"></i></template>
<template #value>{{ version }}</template> <template #value>{{ version }}</template>
</MkKeyValue> </MkKeyValue>
<MkKeyValue v-if="version < releasesCherryPick[0].tag_name" style="margin-top: 10px;" @click="whatIsNewLatestCherryPick"> <MkKeyValue v-if="version < releasesCherryPick[0].tag_name && !skipVersion" style="margin-top: 10px;" @click="whatIsNewLatestCherryPick">
<template #key>{{ i18n.ts.latestVersion }} <i class="ti ti-external-link"></i></template> <template #key>{{ i18n.ts.latestVersion }} <i class="ti ti-external-link"></i></template>
<template v-if="releasesCherryPick" #value>{{ releasesCherryPick[0].tag_name }}</template> <template v-if="releasesCherryPick" #value>{{ releasesCherryPick[0].tag_name }}</template>
<template v-else #value><MkEllipsis/></template> <template v-else #value><MkEllipsis/></template>
</MkKeyValue> </MkKeyValue>
<MkButton v-if="!skipVersion && (version < releasesCherryPick[0].tag_name)" style="margin-top: 10px;" @click="skipThisRelease">{{ i18n.ts.skipThisRelease }}</MkButton>
</FormSection> </FormSection>
<FormSection @click="whatIsNewLatestCherryPick"> <FormSection @click="whatIsNewLatestCherryPick">
@ -78,8 +79,11 @@ import XHeader from '@/pages/admin/_header_.vue';
import MkSwitch from '@/components/MkSwitch.vue'; import MkSwitch from '@/components/MkSwitch.vue';
import { fetchInstance } from '@/instance.js'; import { fetchInstance } from '@/instance.js';
import FormSuspense from '@/components/form/suspense.vue'; import FormSuspense from '@/components/form/suspense.vue';
import MkButton from '@/components/MkButton.vue';
let enableReceivePrerelease: boolean = $ref(false); let enableReceivePrerelease: boolean = $ref(false);
let skipVersion: boolean = $ref(false);
let skipCherryPickVersion = $ref<string | null>(null);
let releasesCherryPick = $ref(); let releasesCherryPick = $ref();
let releasesMisskey = $ref(); let releasesMisskey = $ref();
@ -88,6 +92,8 @@ const meta = await os.api('admin/meta');
async function init() { async function init() {
enableReceivePrerelease = meta.enableReceivePrerelease; enableReceivePrerelease = meta.enableReceivePrerelease;
skipVersion = meta.skipVersion;
skipCherryPickVersion = meta.skipCherryPickVersion;
} }
function save() { function save() {
@ -98,6 +104,18 @@ function save() {
}); });
} }
function skipThisRelease() {
skipCherryPickVersion = releasesCherryPick[0].tag_name;
skipVersion = true;
os.apiWithDialog('admin/update-meta', {
skipVersion,
skipCherryPickVersion,
}).then(() => {
fetchInstance();
});
}
onMounted(() => { onMounted(() => {
fetch('https://api.github.com/repos/kokonect-link/cherrypick/releases', { fetch('https://api.github.com/repos/kokonect-link/cherrypick/releases', {
method: 'GET', method: 'GET',
@ -105,6 +123,10 @@ onMounted(() => {
.then(res => { .then(res => {
if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true); if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true);
else releasesCherryPick = res.filter(x => x.prerelease === false); else releasesCherryPick = res.filter(x => x.prerelease === false);
if (skipCherryPickVersion < releasesCherryPick[0].tag_name) {
skipVersion = false;
os.api('admin/update-meta', { skipVersion });
}
}); });
fetch('https://api.github.com/repos/misskey-dev/misskey/releases', { fetch('https://api.github.com/repos/misskey-dev/misskey/releases', {

View file

@ -85,7 +85,7 @@ if ($i.isAdmin || $i.isModerator) {
const meta = await os.api('admin/meta'); const meta = await os.api('admin/meta');
if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true); if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true);
else releasesCherryPick = res.filter(x => x.prerelease === false); else releasesCherryPick = res.filter(x => x.prerelease === false);
if (version < releasesCherryPick[0].tag_name) controlPanelIndicated = true; if ((version < releasesCherryPick[0].tag_name) && (meta.skipCherryPickVersion < releasesCherryPick[0].tag_name)) controlPanelIndicated = true;
}); });
} }

View file

@ -99,7 +99,7 @@ if ($i.isAdmin || $i.isModerator) {
const meta = await os.api('admin/meta'); const meta = await os.api('admin/meta');
if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true); if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true);
else releasesCherryPick = res.filter(x => x.prerelease === false); else releasesCherryPick = res.filter(x => x.prerelease === false);
if (version < releasesCherryPick[0].tag_name) controlPanelIndicated = true; if ((version < releasesCherryPick[0].tag_name) && (meta.skipCherryPickVersion < releasesCherryPick[0].tag_name)) controlPanelIndicated = true;
}); });
} }

View file

@ -90,7 +90,7 @@ if ($i.isAdmin || $i.isModerator) {
const meta = await os.api('admin/meta'); const meta = await os.api('admin/meta');
if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true); if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true);
else releasesCherryPick = res.filter(x => x.prerelease === false); else releasesCherryPick = res.filter(x => x.prerelease === false);
if (version < releasesCherryPick[0].tag_name) controlPanelIndicated = true; if ((version < releasesCherryPick[0].tag_name) && (meta.skipCherryPickVersion < releasesCherryPick[0].tag_name)) controlPanelIndicated = true;
}); });
} }

View file

@ -96,7 +96,7 @@ if ($i.isAdmin || $i.isModerator) {
const meta = await os.api('admin/meta'); const meta = await os.api('admin/meta');
if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true); if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true);
else releasesCherryPick = res.filter(x => x.prerelease === false); else releasesCherryPick = res.filter(x => x.prerelease === false);
if (version < releasesCherryPick[0].tag_name) controlPanelIndicated = true; if ((version < releasesCherryPick[0].tag_name) && (meta.skipCherryPickVersion < releasesCherryPick[0].tag_name)) controlPanelIndicated = true;
}); });
} }

View file

@ -89,7 +89,7 @@ if ($i.isAdmin || $i.isModerator) {
const meta = await os.api('admin/meta'); const meta = await os.api('admin/meta');
if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true); if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true);
else releasesCherryPick = res.filter(x => x.prerelease === false); else releasesCherryPick = res.filter(x => x.prerelease === false);
if (version < releasesCherryPick[0].tag_name) controlPanelIndicated = true; if ((version < releasesCherryPick[0].tag_name) && (meta.skipCherryPickVersion < releasesCherryPick[0].tag_name)) controlPanelIndicated = true;
}); });
} }

View file

@ -106,7 +106,7 @@ if ($i.isAdmin || $i.isModerator) {
const meta = await os.api('admin/meta'); const meta = await os.api('admin/meta');
if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true); if (meta.enableReceivePrerelease) releasesCherryPick = res.filter(x => x.prerelease === true);
else releasesCherryPick = res.filter(x => x.prerelease === false); else releasesCherryPick = res.filter(x => x.prerelease === false);
if (version < releasesCherryPick[0].tag_name) controlPanelIndicated = true; if ((version < releasesCherryPick[0].tag_name) && (meta.skipCherryPickVersion < releasesCherryPick[0].tag_name)) controlPanelIndicated = true;
}); });
} }