Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 3 additions & 23 deletions components/CustomizationSettings.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div ref="settingsRef" class="customization-settings">
<div class="customization-settings">
<header class="customization-settings__header">
<h3>Customization Settings</h3>
</header>
Expand All @@ -25,7 +25,7 @@
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { ref } from 'vue'
import CustomColors from '@/components/Custom/Colors/Index.vue'
import CustomFonts from '@/components/Custom/Fonts/Index.vue'
import CustomLayouts from '@/components/Custom/Layouts/Index.vue'
Expand All @@ -37,28 +37,11 @@ const tabs = [
]

const activeTab = ref('colors')
const settingsRef = ref(null)
const emit = defineEmits(['close'])

function handleClickOutside(event) {
if (settingsRef.value && !settingsRef.value.contains(event.target)) {
emit('close')
}
}

onMounted(() => {
document.addEventListener('click', handleClickOutside)
})

onBeforeUnmount(() => {
document.removeEventListener('click', handleClickOutside)
})
</script>

<style lang="scss">
.customization-settings {
// @include scrollbar;

// --w-scrollbar: 0.2rem;
--p: 2.5rem;
--max-h: 65dvh;
Expand All @@ -77,7 +60,7 @@ onBeforeUnmount(() => {
overflow: clip scroll;
font-family: var(--fontFamily), var(--fontFamilyDefault);
font-size: 1.2rem;
z-index: 10; // z-index of code-block markdown banner is 6, so we need to be above that
z-index: 10;

@include dev('md') {
--max-h: 85dvh;
Expand All @@ -86,9 +69,6 @@ onBeforeUnmount(() => {
width: clamp(16rem, 60vw, 30rem);
}

// @include dev('sm') {
// }

@include dev('xs') {
--p: 4vw;
width: 85vw;
Expand Down
42 changes: 21 additions & 21 deletions components/ThemeManager.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div ref="themeManagerRef" class="theme-manager" :class="{ 'is-active': isActive }">
<div class="theme-manager__roller" @click.stop="toggleActive">
<div class="theme-manager" :class="{ 'is-active': isActive }" ref="refThemeManager">
<div class="theme-manager__roller" @click.stop="toggleActive" ref="refRollerButton">
<IconRoller />
</div>

Expand All @@ -22,13 +22,14 @@
</div>

<Transition name="slideX">
<CustomizationSettings v-show="settingsOpen" @close="closeSettings" />
<CustomizationSettings v-show="settingsOpen" ref="refCustomSettings" />
</Transition>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { ref } from 'vue'
import { useThemeManager } from '@/composables/useThemeManager'
import { useClickOutsideWatcher } from '@/composables/useClickOutsideWatcher'
import { THEMES } from '@/utils/storage'
import CustomizationSettings from '@/components/CustomizationSettings.vue'
import IconSettings from '@/components/Icons/IconSettings.vue'
Expand All @@ -37,9 +38,17 @@ import IconSun from '@/components/Icons/IconSun.vue'
import IconMoon from '@/components/Icons/IconMoon.vue'
import IconMoonFull from '@/components/Icons/IconMoonFull.vue'

const THEME_OPTIONS = [
{ id: THEMES.LIGHT, icon: IconSun },
{ id: THEMES.DARK, icon: IconMoon },
{ id: THEMES.OLED, icon: IconMoonFull },
]

const { changeTheme } = useThemeManager()

const themeManagerRef = ref(null)
const refThemeManager = ref(null)
const refCustomSettings = ref(null)
const refRollerButton = ref(null)
const settingsOpen = ref(false)
const isActive = ref(false)

Expand All @@ -50,27 +59,18 @@ const openSettings = () => {
isActive.value = false
}

const closeSettings = () => (settingsOpen.value = false)

const handleClickOutside = (event) => {
if (themeManagerRef.value && !themeManagerRef.value.contains(event.target)) {
isActive.value = false
}
const closeSettings = () => {
settingsOpen.value = false
}

onMounted(() => {
document.addEventListener('click', handleClickOutside)
// Setup click-outside watchers using the composable
useClickOutsideWatcher(refCustomSettings, settingsOpen, closeSettings, {
ignore: [refRollerButton], // Prevent immediate close when opening
})

onUnmounted(() => {
document.removeEventListener('click', handleClickOutside)
useClickOutsideWatcher(refThemeManager, isActive, () => {
isActive.value = false
})

const THEME_OPTIONS = [
{ id: THEMES.LIGHT, icon: IconSun },
{ id: THEMES.DARK, icon: IconMoon },
{ id: THEMES.OLED, icon: IconMoonFull },
]
</script>

<style scoped lang="scss">
Expand Down
1 change: 0 additions & 1 deletion composables/useAccentColors.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// composables/useAccentColors.js
import { ref, computed } from 'vue'
import { accentLightItem, accentDarkItem } from '@/utils/storage'
import { hexToHSL } from '@/composables/useColorConversion'
Expand Down
35 changes: 35 additions & 0 deletions composables/useClickOutsideWatcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { onClickOutside } from '@vueuse/core'

/*
* Reactive click-outside watcher that automatically manages listener lifecycle
- target - Element ref to watch
- isOpen - Reactive boolean that controls when listener is active
- onClose - Callback to execute when clicked outside
- options - VueUse onClickOutside options (ignore, etc.)
- Manual cleanup function is returned */
export function useClickOutsideWatcher(target, isOpen, onClose, options = {}) {
let stopListener = null

const cleanup = () => {
stopListener?.()
stopListener = null
}

watch(
isOpen,
(open) => {
cleanup() // Always cleanup previous listener

if (open && target.value) {
stopListener = onClickOutside(target, onClose, options)
}
},
{ flush: 'post' } // Wait for DOM updates
)

// Cleanup on component unmount
onScopeDispose(cleanup)

// Return manual cleanup function for edge cases
return cleanup
}
12 changes: 12 additions & 0 deletions entrypoints/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export default defineContentScript({
matches: ['*://chat.deepseek.com/*'],
// cssInjectionMode: 'manifest', // Ensure CSS is handled correctly
async main(ctx) {
// content.js - runs before page scripts
DEV__CLEAR_DEFAULT_VENDORS_CONSOLE_CLEARING()

// Force theme initialization before the UI mounts.
useThemeManager()

Expand All @@ -35,3 +38,12 @@ export default defineContentScript({
ui.mount()
},
})

function DEV__CLEAR_DEFAULT_VENDORS_CONSOLE_CLEARING() {
// Find the highest interval ID and nuke them all
const maxIntervalId = setTimeout(() => {}, 0)
for (let i = 1; i <= maxIntervalId; i++) {
clearInterval(i)
}
clearTimeout(maxIntervalId) // Clean up the one we just made
}