2024.11.0-yumechinokuni.1 #9
9 changed files with 111 additions and 32 deletions
|
@ -1,8 +1,10 @@
|
||||||
## 2024.10.2
|
## 2024.11.0
|
||||||
|
|
||||||
### General
|
### General
|
||||||
- Feat: コンテンツの表示にログインを必須にできるように
|
- Feat: コンテンツの表示にログインを必須にできるように
|
||||||
- Feat: 過去のノートを非公開化/フォロワーのみ表示可能にできるように
|
- Feat: 過去のノートを非公開化/フォロワーのみ表示可能にできるように
|
||||||
|
- Enhance: 依存関係の更新
|
||||||
|
- Enhance: l10nの更新
|
||||||
|
|
||||||
### Client
|
### Client
|
||||||
- Enhance: Bull DashboardでRelationship Queueの状態も確認できるように
|
- Enhance: Bull DashboardでRelationship Queueの状態も確認できるように
|
||||||
|
@ -25,12 +27,14 @@
|
||||||
- Fix: リンク切れを修正
|
- Fix: リンク切れを修正
|
||||||
= Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正
|
= Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正
|
||||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/305)
|
(Cherry-picked from https://github.com/taiyme/misskey/pull/305)
|
||||||
|
- Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように
|
- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように
|
||||||
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)
|
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)
|
||||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
|
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
|
||||||
- fix(backend): フォロワーへのメッセージの絵文字をemojisに含めるように
|
- Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
|
||||||
|
- Fix: フォロワーへのメッセージの絵文字をemojisに含めるように
|
||||||
- Fix: Nested proxy requestsを検出した際にブロックするように
|
- Fix: Nested proxy requestsを検出した際にブロックするように
|
||||||
[ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
|
[ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
|
||||||
- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正
|
- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正
|
||||||
|
@ -41,7 +45,6 @@
|
||||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/712)
|
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/712)
|
||||||
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
|
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
|
||||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
|
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
|
||||||
- Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
|
|
||||||
|
|
||||||
### Misskey.js
|
### Misskey.js
|
||||||
- Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
|
- Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
|
||||||
|
|
|
@ -85,6 +85,7 @@ Be willing to comment on the good points and not just the things you want fixed
|
||||||
|
|
||||||
読んでおくといいやつ
|
読んでおくといいやつ
|
||||||
- https://blog.lacolaco.net/posts/1e2cf439b3c2/
|
- https://blog.lacolaco.net/posts/1e2cf439b3c2/
|
||||||
|
- https://konifar-zatsu.hatenadiary.jp/entry/2024/11/05/192421
|
||||||
|
|
||||||
### Review perspective
|
### Review perspective
|
||||||
- Scope
|
- Scope
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "2024.11.0-yumechinokuni.0",
|
"version": "2024.11.0-yumechinokuni.1",
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -155,6 +155,8 @@ export type Config = {
|
||||||
signToActivityPubGet: boolean | undefined;
|
signToActivityPubGet: boolean | undefined;
|
||||||
|
|
||||||
version: string;
|
version: string;
|
||||||
|
gitDescribe: string;
|
||||||
|
gitCommit: string;
|
||||||
publishTarballInsteadOfProvideRepositoryUrl: boolean;
|
publishTarballInsteadOfProvideRepositoryUrl: boolean;
|
||||||
setupPassword: string | undefined;
|
setupPassword: string | undefined;
|
||||||
host: string;
|
host: string;
|
||||||
|
@ -218,7 +220,7 @@ export function loadConfig(): Config {
|
||||||
const config = yaml.load(fs.readFileSync(path, 'utf-8')) as Source;
|
const config = yaml.load(fs.readFileSync(path, 'utf-8')) as Source;
|
||||||
|
|
||||||
const url = tryCreateUrl(config.url ?? process.env.MISSKEY_URL ?? '');
|
const url = tryCreateUrl(config.url ?? process.env.MISSKEY_URL ?? '');
|
||||||
const version = meta.version;
|
const { version, gitDescribe, gitCommit } = meta;
|
||||||
const host = url.host;
|
const host = url.host;
|
||||||
const hostname = url.hostname;
|
const hostname = url.hostname;
|
||||||
const scheme = url.protocol.replace(/:$/, '');
|
const scheme = url.protocol.replace(/:$/, '');
|
||||||
|
@ -236,6 +238,8 @@ export function loadConfig(): Config {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
version,
|
version,
|
||||||
|
gitCommit,
|
||||||
|
gitDescribe,
|
||||||
publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl,
|
publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl,
|
||||||
setupPassword: config.setupPassword,
|
setupPassword: config.setupPassword,
|
||||||
url: url.origin,
|
url: url.origin,
|
||||||
|
|
|
@ -105,6 +105,8 @@ export class NodeinfoServerService {
|
||||||
name: meta.maintainerName,
|
name: meta.maintainerName,
|
||||||
email: meta.maintainerEmail,
|
email: meta.maintainerEmail,
|
||||||
},
|
},
|
||||||
|
gitCommit: this.config.gitCommit,
|
||||||
|
gitDescribe: this.config.gitDescribe,
|
||||||
langs: meta.langs,
|
langs: meta.langs,
|
||||||
tosUrl: meta.termsOfServiceUrl,
|
tosUrl: meta.termsOfServiceUrl,
|
||||||
privacyPolicyUrl: meta.privacyPolicyUrl,
|
privacyPolicyUrl: meta.privacyPolicyUrl,
|
||||||
|
|
|
@ -277,7 +277,7 @@ async function onSubmit(): Promise<void> {
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res) {
|
if (res && res.ok) {
|
||||||
if (res.status === 204 || instance.emailRequiredForSignup) {
|
if (res.status === 204 || instance.emailRequiredForSignup) {
|
||||||
os.alert({
|
os.alert({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
|
@ -295,6 +295,8 @@ async function onSubmit(): Promise<void> {
|
||||||
await login(resJson.token);
|
await login(resJson.token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
onSignupApiError();
|
||||||
}
|
}
|
||||||
|
|
||||||
submitting.value = false;
|
submitting.value = false;
|
||||||
|
|
|
@ -7,35 +7,81 @@ import * as Misskey from 'misskey-js';
|
||||||
import { markRaw } from 'vue';
|
import { markRaw } from 'vue';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
import { wsOrigin } from '@@/js/config.js';
|
import { wsOrigin } from '@@/js/config.js';
|
||||||
|
import { DEFAULT_DEVICE_KIND } from '@/scripts/device-kind.js';
|
||||||
// TODO: No WebsocketモードでStreamMockが使えそう
|
// TODO: No WebsocketモードでStreamMockが使えそう
|
||||||
//import { StreamMock } from '@/scripts/stream-mock.js';
|
//import { StreamMock } from '@/scripts/stream-mock.js';
|
||||||
|
|
||||||
// heart beat interval in ms
|
// heart beat interval in ms
|
||||||
const HEART_BEAT_INTERVAL = 1000 * 60;
|
const HEART_BEAT_INTERVAL = DEFAULT_DEVICE_KIND === 'desktop' ? 1000 * 15 : 1000 * 30;
|
||||||
|
|
||||||
|
const RECONNECT_MAX_ATTEMPTS = 10;
|
||||||
|
const RECONNECT_INITIAL_DELAY = 1000;
|
||||||
|
const RECONNECT_MAX_DELAY = 1000 * 30;
|
||||||
|
|
||||||
let stream: Misskey.IStream | null = null;
|
let stream: Misskey.IStream | null = null;
|
||||||
let timeoutHeartBeat: number | null = null;
|
let timeoutHeartBeat: number | null = null;
|
||||||
let lastHeartbeatCall = 0;
|
let lastHeartbeatCall = 0;
|
||||||
|
let reconnectAttempts = 0;
|
||||||
|
let reconnectTimeout: number | null = null;
|
||||||
|
|
||||||
|
function getReconnectDelay(): number {
|
||||||
|
const delay = RECONNECT_INITIAL_DELAY * Math.pow(2, reconnectAttempts);
|
||||||
|
return Math.min(delay, RECONNECT_MAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createStream(): Misskey.IStream {
|
||||||
|
const newStream = markRaw(new Misskey.Stream(wsOrigin, $i ? {
|
||||||
|
token: $i.token,
|
||||||
|
} : null));
|
||||||
|
|
||||||
|
newStream.on('_disconnected_', () => {
|
||||||
|
console.log('Stream disconnected, attempting to reconnect...');
|
||||||
|
if (reconnectAttempts < RECONNECT_MAX_ATTEMPTS) {
|
||||||
|
const delay = getReconnectDelay();
|
||||||
|
reconnectTimeout = window.setTimeout(() => {
|
||||||
|
reconnectAttempts++;
|
||||||
|
stream = null;
|
||||||
|
useStream();
|
||||||
|
}, delay);
|
||||||
|
} else {
|
||||||
|
console.error('Max reconnection attempts reached');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
newStream.on('_connected_', () => {
|
||||||
|
console.log('Stream connected successfully');
|
||||||
|
reconnectAttempts = 0;
|
||||||
|
if (reconnectTimeout) {
|
||||||
|
clearTimeout(reconnectTimeout);
|
||||||
|
reconnectTimeout = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return newStream;
|
||||||
|
}
|
||||||
|
|
||||||
export function useStream(): Misskey.IStream {
|
export function useStream(): Misskey.IStream {
|
||||||
if (stream) return stream;
|
if (stream) return stream;
|
||||||
|
|
||||||
// TODO: No Websocketモードもここで判定
|
stream = createStream();
|
||||||
stream = markRaw(new Misskey.Stream(wsOrigin, $i ? {
|
|
||||||
token: $i.token,
|
|
||||||
} : null));
|
|
||||||
|
|
||||||
if (timeoutHeartBeat) window.clearTimeout(timeoutHeartBeat);
|
if (timeoutHeartBeat) window.clearTimeout(timeoutHeartBeat);
|
||||||
timeoutHeartBeat = window.setTimeout(heartbeat, HEART_BEAT_INTERVAL);
|
timeoutHeartBeat = window.setTimeout(heartbeat, HEART_BEAT_INTERVAL);
|
||||||
|
|
||||||
// send heartbeat right now when last send time is over HEART_BEAT_INTERVAL
|
const target = () => {
|
||||||
document.addEventListener('visibilitychange', () => {
|
|
||||||
if (
|
if (
|
||||||
!stream
|
!stream
|
||||||
|| document.visibilityState !== 'visible'
|
|| document.visibilityState !== 'visible'
|
||||||
|| Date.now() - lastHeartbeatCall < HEART_BEAT_INTERVAL
|
|| Date.now() - lastHeartbeatCall < HEART_BEAT_INTERVAL
|
||||||
) return;
|
) return;
|
||||||
heartbeat();
|
heartbeat();
|
||||||
|
};
|
||||||
|
|
||||||
|
// send heartbeat right now when last send time is over HEART_BEAT_INTERVAL
|
||||||
|
document.addEventListener('visibilitychange', target);
|
||||||
|
|
||||||
|
stream.on('_disconnected_', () => {
|
||||||
|
document.removeEventListener('visibilitychange', target);
|
||||||
});
|
});
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
|
|
|
@ -4,14 +4,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const child_process = require('child_process');
|
||||||
const packageJsonPath = __dirname + '/../package.json'
|
const packageJsonPath = __dirname + '/../package.json'
|
||||||
|
|
||||||
function build() {
|
function build() {
|
||||||
try {
|
try {
|
||||||
|
const gitDescribe = child_process.execSync('git describe --tags --always').toString().trim();
|
||||||
|
const gitCommit = child_process.execSync('git rev-parse HEAD').toString().trim();
|
||||||
const json = fs.readFileSync(packageJsonPath, 'utf-8')
|
const json = fs.readFileSync(packageJsonPath, 'utf-8')
|
||||||
const meta = JSON.parse(json);
|
const meta = JSON.parse(json);
|
||||||
fs.mkdirSync(__dirname + '/../built', { recursive: true });
|
fs.mkdirSync(__dirname + '/../built', { recursive: true });
|
||||||
fs.writeFileSync(__dirname + '/../built/meta.json', JSON.stringify({ version: meta.version }), 'utf-8');
|
fs.writeFileSync(__dirname + '/../built/meta.json',
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
version: meta.version,
|
||||||
|
gitCommit: gitCommit,
|
||||||
|
gitDescribe: gitDescribe,
|
||||||
|
}), 'utf-8');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ pub struct RefConfig {
|
||||||
pub stdout: Option<PathBuf>,
|
pub stdout: Option<PathBuf>,
|
||||||
pub stderr: Option<PathBuf>,
|
pub stderr: Option<PathBuf>,
|
||||||
pub working_dir: PathBuf,
|
pub working_dir: PathBuf,
|
||||||
|
pub profiles: Option<Vec<String>>,
|
||||||
pub compose_flags: Option<Vec<String>>,
|
pub compose_flags: Option<Vec<String>>,
|
||||||
pub env: Option<HashMap<String, String>>,
|
pub env: Option<HashMap<String, String>>,
|
||||||
pub uid: u32,
|
pub uid: u32,
|
||||||
|
@ -200,6 +201,17 @@ impl App {
|
||||||
|
|
||||||
let mut command = Command::new("docker")
|
let mut command = Command::new("docker")
|
||||||
.arg("compose")
|
.arg("compose")
|
||||||
|
.args(
|
||||||
|
matched_ref
|
||||||
|
.config
|
||||||
|
.profiles
|
||||||
|
.as_ref()
|
||||||
|
.map(|profiles|
|
||||||
|
profiles.iter()
|
||||||
|
.flat_map(|profiles| ["--profile", profiles.as_str()])
|
||||||
|
.collect::<Vec<_>>())
|
||||||
|
.unwrap_or(Vec::new()),
|
||||||
|
)
|
||||||
.arg("up")
|
.arg("up")
|
||||||
.arg("--detach")
|
.arg("--detach")
|
||||||
.arg("--build")
|
.arg("--build")
|
||||||
|
@ -289,7 +301,7 @@ impl App {
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Query(query): Query<GetStatusQuery>,
|
Query(query): Query<GetStatusQuery>,
|
||||||
) -> Result<Json<RefStatus>, ApiError> {
|
) -> Result<Json<RefStatus>, ApiError> {
|
||||||
let ref_ = match (&query.ref_, &query.branch) {
|
let ref_ = match (query.ref_.as_ref(), query.branch.as_ref()) {
|
||||||
(Some(ref_), None) => ref_.clone(),
|
(Some(ref_), None) => ref_.clone(),
|
||||||
(None, Some(branch)) => format!("refs/heads/{}", branch),
|
(None, Some(branch)) => format!("refs/heads/{}", branch),
|
||||||
_ => {
|
_ => {
|
||||||
|
|
Loading…
Reference in a new issue