Merge branch 'develop' into feat-frontend-expand-profile-links
This commit is contained in:
commit
da86f303f3
|
@ -4,6 +4,8 @@
|
|||
-
|
||||
|
||||
### Client
|
||||
- Enhance: AiScriptAppウィジェットで構文エラーを検知してもダイアログではなくウィジェット内にエラーを表示するように
|
||||
- Enhance: /flushページでサイトキャッシュをクリアできるようになりました
|
||||
- Enhance: プロフィールへのリンクをユーザーポップアップのアバターに追加
|
||||
- Enhance: ユーザーのノート、フォロー、フォロワーページへのリンクをユーザーポップアップに追加
|
||||
- Fix: RSSティッカーウィジェットが正しく動作しない問題を修正
|
||||
|
|
|
@ -201,6 +201,8 @@ export class ClientServerService {
|
|||
|
||||
@bindThis
|
||||
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
|
||||
const configUrl = new URL(this.config.url);
|
||||
|
||||
fastify.register(fastifyView, {
|
||||
root: _dirname + '/views',
|
||||
engine: {
|
||||
|
@ -239,7 +241,6 @@ export class ClientServerService {
|
|||
done();
|
||||
});
|
||||
} else {
|
||||
const configUrl = new URL(this.config.url);
|
||||
const urlOriginWithoutPort = configUrl.origin.replace(/:\d+$/, '');
|
||||
|
||||
const port = (process.env.VITE_PORT ?? '5173');
|
||||
|
@ -887,6 +888,22 @@ export class ClientServerService {
|
|||
[, ...target.split('/').filter(x => x), ...source.split('/').filter(x => x).splice(depth)].join('/');
|
||||
|
||||
fastify.get('/flush', async (request, reply) => {
|
||||
let sendHeader = true;
|
||||
|
||||
if (request.headers['origin']) {
|
||||
const originURL = new URL(request.headers['origin']);
|
||||
if (originURL.protocol !== 'https:') { // Clear-Site-Data only supports https
|
||||
sendHeader = false;
|
||||
}
|
||||
if (originURL.host !== configUrl.host) {
|
||||
sendHeader = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (sendHeader) {
|
||||
reply.header('Clear-Site-Data', '"*"');
|
||||
}
|
||||
reply.header('Set-Cookie', 'http-flush-failed=1; Path=/flush; Max-Age=60');
|
||||
return await reply.view('flush');
|
||||
});
|
||||
|
||||
|
|
|
@ -6,41 +6,45 @@ html
|
|||
const msg = document.getElementById('msg');
|
||||
const successText = `\nSuccess Flush! <a href="/">Back to Misskey</a>\n成功しました。<a href="/">Misskeyを開き直してください。</a>`;
|
||||
|
||||
message('Start flushing.');
|
||||
if (!document.cookie) {
|
||||
message('Your site data is fully cleared by your browser.');
|
||||
message(successText);
|
||||
} else {
|
||||
message('Your browser does not support Clear-Site-Data header. Start opportunistic flushing.');
|
||||
(async function() {
|
||||
try {
|
||||
localStorage.clear();
|
||||
message('localStorage cleared.');
|
||||
|
||||
(async function() {
|
||||
try {
|
||||
localStorage.clear();
|
||||
message('localStorage cleared.');
|
||||
const idbPromises = ['MisskeyClient', 'keyval-store'].map((name, i, arr) => new Promise((res, rej) => {
|
||||
const delidb = indexedDB.deleteDatabase(name);
|
||||
delidb.onsuccess = () => res(message(`indexedDB "${name}" cleared. (${i + 1}/${arr.length})`));
|
||||
delidb.onerror = e => rej(e)
|
||||
}));
|
||||
|
||||
const idbPromises = ['MisskeyClient', 'keyval-store'].map((name, i, arr) => new Promise((res, rej) => {
|
||||
const delidb = indexedDB.deleteDatabase(name);
|
||||
delidb.onsuccess = () => res(message(`indexedDB "${name}" cleared. (${i + 1}/${arr.length})`));
|
||||
delidb.onerror = e => rej(e)
|
||||
}));
|
||||
await Promise.all(idbPromises);
|
||||
|
||||
await Promise.all(idbPromises);
|
||||
if (navigator.serviceWorker.controller) {
|
||||
navigator.serviceWorker.controller.postMessage('clear');
|
||||
await navigator.serviceWorker.getRegistrations()
|
||||
.then(registrations => {
|
||||
return Promise.all(registrations.map(registration => registration.unregister()));
|
||||
})
|
||||
.catch(e => { throw new Error(e) });
|
||||
}
|
||||
|
||||
if (navigator.serviceWorker.controller) {
|
||||
navigator.serviceWorker.controller.postMessage('clear');
|
||||
await navigator.serviceWorker.getRegistrations()
|
||||
.then(registrations => {
|
||||
return Promise.all(registrations.map(registration => registration.unregister()));
|
||||
})
|
||||
.catch(e => { throw new Error(e) });
|
||||
message(successText);
|
||||
} catch (e) {
|
||||
message(`\n${e}\n\nFlush Failed. <a href="/flush">Please retry.</a>\n失敗しました。<a href="/flush">もう一度試してみてください。</a>`);
|
||||
message(`\nIf you retry more than 3 times, try manually clearing the browser cache or contact to instance admin.\n3回以上試しても失敗する場合、ブラウザのキャッシュを手動で消去し、それでもだめならインスタンス管理者に連絡してみてください。\n`)
|
||||
|
||||
console.error(e);
|
||||
setTimeout(() => {
|
||||
location = '/';
|
||||
}, 10000)
|
||||
}
|
||||
|
||||
message(successText);
|
||||
} catch (e) {
|
||||
message(`\n${e}\n\nFlush Failed. <a href="/flush">Please retry.</a>\n失敗しました。<a href="/flush">もう一度試してみてください。</a>`);
|
||||
message(`\nIf you retry more than 3 times, clear the browser cache or contact to instance admin.\n3回以上試しても失敗する場合、ブラウザのキャッシュを消去し、それでもだめならインスタンス管理者に連絡してみてください。\n`)
|
||||
|
||||
console.error(e);
|
||||
setTimeout(() => {
|
||||
location = '/';
|
||||
}, 10000)
|
||||
}
|
||||
})();
|
||||
})();
|
||||
}
|
||||
|
||||
function message(text) {
|
||||
msg.insertAdjacentHTML('beforeend', `<p>[${(new Date()).toString()}] ${text.replace(/\n/g,'<br>')}</p>`)
|
||||
|
|
|
@ -34,7 +34,7 @@ import { instance as meta } from '@/instance.js';
|
|||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 80vw; // 100%からshapeの幅を引いている
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,25 +7,26 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkContainer :showHeader="widgetProps.showHeader" class="mkw-aiscriptApp">
|
||||
<template #header>App</template>
|
||||
<div :class="$style.root">
|
||||
<MkAsUi v-if="root" :component="root" :components="components" size="small"/>
|
||||
<div v-if="isSyntaxError">Syntax error :(</div>
|
||||
<MkAsUi v-else-if="root" :component="root" :components="components" size="small"/>
|
||||
</div>
|
||||
</MkContainer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import type { Ref } from 'vue';
|
||||
import { Interpreter, Parser } from '@syuilo/aiscript';
|
||||
import { useWidgetPropsManager } from './widget.js';
|
||||
import type { Ref } from 'vue';
|
||||
import type { WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js';
|
||||
import type { FormWithDefault, GetFormResultType } from '@/utility/form.js';
|
||||
import type { AsUiComponent, AsUiRoot } from '@/aiscript/ui.js';
|
||||
import * as os from '@/os.js';
|
||||
import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js';
|
||||
import { $i } from '@/i.js';
|
||||
import MkAsUi from '@/components/MkAsUi.vue';
|
||||
import MkContainer from '@/components/MkContainer.vue';
|
||||
import { registerAsUiLib } from '@/aiscript/ui.js';
|
||||
import type { AsUiComponent, AsUiRoot } from '@/aiscript/ui.js';
|
||||
|
||||
const name = 'aiscriptApp';
|
||||
|
||||
|
@ -56,8 +57,11 @@ const parser = new Parser();
|
|||
|
||||
const root = ref<AsUiRoot>();
|
||||
const components = ref<Ref<AsUiComponent>[]>([]);
|
||||
const isSyntaxError = ref(false);
|
||||
|
||||
async function run() {
|
||||
isSyntaxError.value = false;
|
||||
|
||||
const aiscript = new Interpreter({
|
||||
...createAiScriptEnv({
|
||||
storageKey: 'widget',
|
||||
|
@ -80,10 +84,7 @@ async function run() {
|
|||
try {
|
||||
ast = parser.parse(widgetProps.script);
|
||||
} catch (err) {
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: 'Syntax error :(',
|
||||
});
|
||||
isSyntaxError.value = true;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -52,7 +52,7 @@ const { widgetProps, configure } = useWidgetPropsManager(name,
|
|||
|
||||
const parser = new Parser();
|
||||
|
||||
const run = async () => {
|
||||
async function run() {
|
||||
const aiscript = new Interpreter(createAiScriptEnv({
|
||||
storageKey: 'widget',
|
||||
token: $i?.token,
|
||||
|
@ -84,7 +84,7 @@ const run = async () => {
|
|||
text: err instanceof Error ? err.message : String(err),
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
defineExpose<WidgetComponentExpose>({
|
||||
name,
|
||||
|
|
Loading…
Reference in New Issue