From e092008dc5768cb57b9eeb2ff70e5b831e0dfa24 Mon Sep 17 00:00:00 2001
From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Fri, 1 Aug 2025 17:20:40 +0900
Subject: feat(frontend): セーフモード (#16245)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* feat(frontend): セーフモード

* Update Changelog

* Update Changelog

* fix

* fix

* Update Changelog

* Update Changelog

* PWAのショートカット経由でもセーフモードで起動できるように

* Update ClientServerService.ts

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
---
 packages/frontend/src/ui/_common_/common.vue | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

(limited to 'packages/frontend/src/ui/_common_/common.vue')

diff --git a/packages/frontend/src/ui/_common_/common.vue b/packages/frontend/src/ui/_common_/common.vue
index da20d23cfd..37c95f2db2 100644
--- a/packages/frontend/src/ui/_common_/common.vue
+++ b/packages/frontend/src/ui/_common_/common.vue
@@ -94,6 +94,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 <div v-if="dev" id="devTicker"><span style="animation: dev-ticker-blink 2s infinite;">DEV BUILD</span></div>
 
 <div v-if="$i && $i.isBot" id="botWarn"><span style="animation: dev-ticker-blink 2s infinite;">{{ i18n.ts.loggedInAsBot }}</span></div>
+
+<div v-if="isSafeMode" id="safemodeWarn">
+	<span style="animation: dev-ticker-blink 2s infinite;">{{ i18n.ts.safeModeEnabled }}</span>&nbsp;
+	<button class="_textButton" style="pointer-events: all;" @click="exitSafeMode">{{ i18n.ts.turnItOff }}</button>
+</div>
 </template>
 
 <script lang="ts" setup>
@@ -101,7 +106,10 @@ import { defineAsyncComponent, ref, TransitionGroup } from 'vue';
 import * as Misskey from 'misskey-js';
 import { swInject } from './sw-inject.js';
 import XNotification from './notification.vue';
+import { isSafeMode } from '@@/js/config.js';
 import { popups } from '@/os.js';
+import { unisonReload } from '@/utility/unison-reload.js';
+import { miLocalStorage } from '@/local-storage.js';
 import { pendingApiRequestsCount } from '@/utility/misskey-api.js';
 import * as sound from '@/utility/sound.js';
 import { $i } from '@/i.js';
@@ -144,6 +152,13 @@ function onNotification(notification: Misskey.entities.Notification, isClient =
 	sound.playMisskeySfx('notification');
 }
 
+function exitSafeMode() {
+	miLocalStorage.removeItem('isSafeMode');
+	const url = new URL(window.location.href);
+	url.searchParams.delete('safemode');
+	unisonReload(url.toString());
+}
+
 if ($i) {
 	if (store.s.realtimeMode) {
 		const connection = useStream().useChannel('main');
@@ -396,7 +411,7 @@ if ($i) {
 	width: 100%;
 	height: max-content;
 	text-align: center;
-	z-index: 2147483647;
+	z-index: 2147483646;
 	color: #ff0;
 	background: rgba(0, 0, 0, 0.5);
 	padding: 4px 7px;
@@ -405,6 +420,11 @@ if ($i) {
 	user-select: none;
 }
 
+#safemodeWarn {
+	@extend #botWarn;
+	z-index: 2147483647;
+}
+
 #devTicker {
 	position: fixed;
 	bottom: 0;
-- 
cgit v1.2.3-freya

