parent
c75afad64a
commit
93ea9c2033
@ -1,7 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, h, PropType, TransitionGroup, useCssModule } from 'vue';
|
import { defineComponent, h, PropType, TransitionGroup, useCssModule } from 'vue';
|
||||||
import MkAd from '@/components/global/MkAd.vue';
|
import MkAd from '@/components/global/MkAd.vue';
|
||||||
|
import { isDebuggerEnabled, stackTraceInstances } from '@/debug';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
import * as os from '@/os';
|
||||||
import { defaultStore } from '@/store';
|
import { defaultStore } from '@/store';
|
||||||
import { MisskeyEntity } from '@/types/date-separated-list';
|
import { MisskeyEntity } from '@/types/date-separated-list';
|
||||||
|
|
||||||
@ -46,7 +48,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
if (props.items.length === 0) return;
|
if (props.items.length === 0) return;
|
||||||
|
|
||||||
const renderChildren = () => props.items.map((item, i) => {
|
const renderChildrenImpl = () => props.items.map((item, i) => {
|
||||||
if (!slots || !slots.default) return;
|
if (!slots || !slots.default) return;
|
||||||
|
|
||||||
const el = slots.default({
|
const el = slots.default({
|
||||||
@ -95,6 +97,21 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const renderChildren = () => {
|
||||||
|
const children = renderChildrenImpl();
|
||||||
|
if (isDebuggerEnabled(6864)) {
|
||||||
|
const nodes = children.flatMap((node) => node ?? []);
|
||||||
|
const keys = new Set(nodes.map((node) => node.key));
|
||||||
|
if (keys.size !== nodes.length) {
|
||||||
|
const id = crypto.randomUUID();
|
||||||
|
const instances = stackTraceInstances();
|
||||||
|
os.toast(instances.reduce((a, c) => `${a} at ${c.type.name}`, `[DEBUG_6864 (${id})]: ${nodes.length - keys.size} duplicated keys found`));
|
||||||
|
console.warn({ id, debugId: 6864, stack: instances });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
};
|
||||||
|
|
||||||
function onBeforeLeave(el: HTMLElement) {
|
function onBeforeLeave(el: HTMLElement) {
|
||||||
el.style.top = `${el.offsetTop}px`;
|
el.style.top = `${el.offsetTop}px`;
|
||||||
el.style.left = `${el.offsetLeft}px`;
|
el.style.left = `${el.offsetLeft}px`;
|
||||||
|
27
packages/frontend/src/debug.ts
Normal file
27
packages/frontend/src/debug.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { type ComponentInternalInstance, getCurrentInstance } from 'vue';
|
||||||
|
|
||||||
|
export function isDebuggerEnabled(id: number): boolean {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(`DEBUG_${id}`) !== null;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function switchDebuggerEnabled(id: number, enabled: boolean): void {
|
||||||
|
if (enabled) {
|
||||||
|
localStorage.setItem(`DEBUG_${id}`, '');
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(`DEBUG_${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function stackTraceInstances(): ComponentInternalInstance[] {
|
||||||
|
let instance = getCurrentInstance();
|
||||||
|
const stack: ComponentInternalInstance[] = [];
|
||||||
|
while (instance) {
|
||||||
|
stack.push(instance);
|
||||||
|
instance = instance.parent;
|
||||||
|
}
|
||||||
|
return stack;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user