fix(frontend): FolderPageViewでブラウザの戻るボタンを使えるようにwip

This commit is contained in:
kakkokari-gtyih 2025-09-24 14:54:21 +09:00
parent 0f8c068e84
commit 30de43163e
5 changed files with 77 additions and 21 deletions

View File

@ -106,6 +106,11 @@ export async function common(createVue: () => Promise<App<Element>>) {
window.history.replaceState(null, '', window.location.href.replace('#pswp', '')); window.history.replaceState(null, '', window.location.href.replace('#pswp', ''));
} }
// URLにfolderPageのhashが含まれる場合は取り除く
if (window.location.hash.startsWith('#fp_')) {
window.history.replaceState(null, '', window.location.href.replace(window.location.hash, ''));
}
// 一斉リロード // 一斉リロード
reloadChannel.addEventListener('message', path => { reloadChannel.addEventListener('message', path => {
if (path !== null) window.location.href = path; if (path !== null) window.location.href = path;

View File

@ -96,10 +96,12 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { nextTick, onMounted, ref, useTemplateRef } from 'vue'; import { nextTick, onMounted, ref, useTemplateRef, watch } from 'vue';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import { getBgColor } from '@/utility/get-bg-color.js'; import { getBgColor } from '@/utility/get-bg-color.js';
import { pageFolderTeleportCount, popup } from '@/os.js'; import { popup } from '@/os.js';
import { pageFolderTeleportedIds } from '@/utility/folder-page.js';
import { genId } from '@/utility/id.js';
import MkFolderPage from '@/components/MkFolderPage.vue'; import MkFolderPage from '@/components/MkFolderPage.vue';
import { deviceKind } from '@/utility/device-kind.js'; import { deviceKind } from '@/utility/device-kind.js';
@ -123,6 +125,8 @@ const rootEl = useTemplateRef('rootEl');
const asPage = props.canPage && deviceKind === 'smartphone' && prefer.s['experimental.enableFolderPageView']; const asPage = props.canPage && deviceKind === 'smartphone' && prefer.s['experimental.enableFolderPageView'];
const bgSame = ref(false); const bgSame = ref(false);
const opened = ref(asPage ? false : props.defaultOpen); const opened = ref(asPage ? false : props.defaultOpen);
const pageShowing = ref(false);
const pageId = ref(genId());
const openedAtLeastOnce = ref(opened.value); const openedAtLeastOnce = ref(opened.value);
//#region interpolate-sizeTODO: //#region interpolate-sizeTODO:
@ -161,17 +165,24 @@ function afterLeave(el: Element) {
} }
//#endregion //#endregion
let pageId = pageFolderTeleportCount.value;
pageFolderTeleportCount.value += 1000;
async function toggle() { async function toggle() {
if (asPage && !opened.value) { if (asPage && !opened.value && !pageShowing.value) {
pageId++; if (pageFolderTeleportedIds.value.includes(pageId.value)) {
const { dispose } = await popup(MkFolderPage, { return;
}
pageShowing.value = true;
pageId.value = genId();
pageFolderTeleportedIds.value.push(pageId.value);
const { dispose } = popup(MkFolderPage, {
pageId, pageId,
showing: pageShowing,
}, { }, {
closed: () => { closed: () => {
opened.value = false; opened.value = false;
pageShowing.value = false;
pageFolderTeleportedIds.value = pageFolderTeleportedIds.value.filter((v) => v !== pageId.value);
dispose(); dispose();
}, },
}); });
@ -186,6 +197,12 @@ async function toggle() {
}); });
} }
watch(pageFolderTeleportedIds, (newVal) => {
if (!newVal.includes(pageId.value) && pageShowing.value) {
pageShowing.value = false;
}
}, { deep: true });
onMounted(() => { onMounted(() => {
const computedStyle = getComputedStyle(window.document.documentElement); const computedStyle = getComputedStyle(window.document.documentElement);
const parentBg = getBgColor(rootEl.value?.parentElement) ?? 'transparent'; const parentBg = getBgColor(rootEl.value?.parentElement) ?? 'transparent';

View File

@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:leaveToClass="prefer.s.animation ? $style.transition_x_leaveTo : ''" :leaveToClass="prefer.s.animation ? $style.transition_x_leaveTo : ''"
:duration="300" appear @afterLeave="onClosed" :duration="300" appear @afterLeave="onClosed"
> >
<div v-show="showing" :class="[$style.root]" :style="{ zIndex }"> <div v-show="actualShowingState" :class="[$style.root]" :style="{ zIndex }">
<div :class="[$style.bg]" :style="{ zIndex }"></div> <div :class="[$style.bg]" :style="{ zIndex }"></div>
<div :class="[$style.content]" :style="{ zIndex }"> <div :class="[$style.content]" :style="{ zIndex }">
<div :class="$style.header"> <div :class="$style.header">
@ -27,31 +27,30 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref } from 'vue'; import { ref, computed } from 'vue';
import { claimZIndex } from '@/os.js'; import { claimZIndex } from '@/os.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
const props = withDefaults(defineProps<{ const props = defineProps<{
pageId: number, pageId: string;
}>(), { showing: boolean;
pageId: 0, }>();
});
const emit = defineEmits<{ const emit = defineEmits<{
(_: 'closed'): void (_: 'closed'): void;
}>(); }>();
const zIndex = claimZIndex('low'); const zIndex = claimZIndex('low');
const showing = ref(true); const manualShowing = ref(true);
const actualShowingState = computed(() => props.showing && manualShowing.value);
function closePage() { function closePage() {
showing.value = false; manualShowing.value = false;
} }
function onClosed() { function onClosed() {
emit('closed'); emit('closed');
} }
</script> </script>
<style lang="scss" module> <style lang="scss" module>

View File

@ -803,5 +803,3 @@ export function launchUploader(
}); });
}); });
} }
export const pageFolderTeleportCount = ref(0);

View File

@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { ref, watch } from 'vue';
const FOLDER_PAGE_HASH_PREFIX = 'fp_';
export const pageFolderTeleportedIds = ref<string[]>([]);
window.addEventListener('popstate', () => {
const newHash = location.hash.split('#')[1] ?? '';
let newHashIds: string[] | null = null;
if (newHash.startsWith(FOLDER_PAGE_HASH_PREFIX)) {
newHashIds = newHash
.slice(FOLDER_PAGE_HASH_PREFIX.length)
.split(',');
}
if (newHashIds === null || newHashIds.length === 0) {
pageFolderTeleportedIds.value = [];
}
if (newHashIds !== null) {
pageFolderTeleportedIds.value = newHashIds;
}
});
watch(pageFolderTeleportedIds, (newVal) => {
const newHash = newVal.join(',');
const expectedHash = newHash ? `#${FOLDER_PAGE_HASH_PREFIX}${newHash}` : location.pathname + location.search;
if (location.hash !== expectedHash) {
history.pushState(null, '', expectedHash);
}
}, { immediate: true, deep: true });