mirror of
				https://github.com/CorentinTh/it-tools.git
				synced 2025-11-04 02:47:00 -05:00 
			
		
		
		
	refactor(tracker): better tracker injection
This commit is contained in:
		
							parent
							
								
									bf88836dbe
								
							
						
					
					
						commit
						def60e7248
					
				@ -1,24 +1,25 @@
 | 
				
			|||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { useFuzzySearch } from '@/composable/fuzzySearch';
 | 
					import { useFuzzySearch } from '@/composable/fuzzySearch';
 | 
				
			||||||
 | 
					import { useTracker } from '@/modules/tracker/tracker.services';
 | 
				
			||||||
import { tools } from '@/tools';
 | 
					import { tools } from '@/tools';
 | 
				
			||||||
import type { Tool } from '@/tools/tools.types';
 | 
					import type { Tool } from '@/tools/tools.types';
 | 
				
			||||||
import { SearchRound } from '@vicons/material';
 | 
					import { SearchRound } from '@vicons/material';
 | 
				
			||||||
import { useMagicKeys, whenever } from '@vueuse/core';
 | 
					import { useMagicKeys, whenever } from '@vueuse/core';
 | 
				
			||||||
 | 
					import type { NInput } from 'naive-ui';
 | 
				
			||||||
import { computed, h, ref } from 'vue';
 | 
					import { computed, h, ref } from 'vue';
 | 
				
			||||||
import { useRouter } from 'vue-router';
 | 
					import { useRouter } from 'vue-router';
 | 
				
			||||||
import SearchBarItem from './SearchBarItem.vue';
 | 
					import SearchBarItem from './SearchBarItem.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const router = useRouter();
 | 
					 | 
				
			||||||
const queryString = ref('');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const { searchResult } = useFuzzySearch({
 | 
					 | 
				
			||||||
  search: queryString,
 | 
					 | 
				
			||||||
  data: tools,
 | 
					 | 
				
			||||||
  options: { keys: [{ name: 'name', weight: 2 }, 'description', 'keywords'] },
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const toolToOption = (tool: Tool) => ({ label: tool.name, value: tool.path, tool });
 | 
					const toolToOption = (tool: Tool) => ({ label: tool.name, value: tool.path, tool });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const router = useRouter();
 | 
				
			||||||
 | 
					const { tracker } = useTracker();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const queryString = ref('');
 | 
				
			||||||
 | 
					const inputEl = ref<HTMLElement>();
 | 
				
			||||||
 | 
					const displayDropDown = ref(true);
 | 
				
			||||||
 | 
					const isMac = computed(() => window.navigator.userAgent.toLowerCase().includes('mac'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const options = computed(() => {
 | 
					const options = computed(() => {
 | 
				
			||||||
  if (queryString.value === '') {
 | 
					  if (queryString.value === '') {
 | 
				
			||||||
    return tools.map(toolToOption);
 | 
					    return tools.map(toolToOption);
 | 
				
			||||||
@ -27,12 +28,11 @@ const options = computed(() => {
 | 
				
			|||||||
  return searchResult.value.map(toolToOption);
 | 
					  return searchResult.value.map(toolToOption);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function onSelect(path: string) {
 | 
					const { searchResult } = useFuzzySearch({
 | 
				
			||||||
  router.push(path);
 | 
					  search: queryString,
 | 
				
			||||||
  queryString.value = '';
 | 
					  data: tools,
 | 
				
			||||||
}
 | 
					  options: { keys: [{ name: 'name', weight: 2 }, 'description', 'keywords'] },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
const focusTarget = ref();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const keys = useMagicKeys({
 | 
					const keys = useMagicKeys({
 | 
				
			||||||
  passive: false,
 | 
					  passive: false,
 | 
				
			||||||
@ -47,18 +47,33 @@ const keys = useMagicKeys({
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
whenever(keys.ctrl_k, () => {
 | 
					whenever(keys.ctrl_k, claimFocus);
 | 
				
			||||||
  focusTarget.value.focus();
 | 
					whenever(keys.meta_k, claimFocus);
 | 
				
			||||||
});
 | 
					whenever(keys.escape, releaseFocus);
 | 
				
			||||||
whenever(keys.meta_k, () => {
 | 
					 | 
				
			||||||
  focusTarget.value.focus();
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
function renderOption({ tool }: { tool: Tool }) {
 | 
					function renderOption({ tool }: { tool: Tool }) {
 | 
				
			||||||
  return h(SearchBarItem, { tool });
 | 
					  return h(SearchBarItem, { tool });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const isMac = computed(() => window.navigator.userAgent.toLowerCase().includes('mac'));
 | 
					function onSelect(path: string) {
 | 
				
			||||||
 | 
					  router.push(path);
 | 
				
			||||||
 | 
					  queryString.value = '';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function claimFocus() {
 | 
				
			||||||
 | 
					  displayDropDown.value = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  inputEl.value?.focus();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function releaseFocus() {
 | 
				
			||||||
 | 
					  displayDropDown.value = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onFocus() {
 | 
				
			||||||
 | 
					  tracker.trackEvent({ eventName: 'Search-bar focused' });
 | 
				
			||||||
 | 
					  displayDropDown.value = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
@ -69,12 +84,13 @@ const isMac = computed(() => window.navigator.userAgent.toLowerCase().includes('
 | 
				
			|||||||
      :on-select="(value) => onSelect(String(value))"
 | 
					      :on-select="(value) => onSelect(String(value))"
 | 
				
			||||||
      :render-label="renderOption"
 | 
					      :render-label="renderOption"
 | 
				
			||||||
      :default-value="'aa'"
 | 
					      :default-value="'aa'"
 | 
				
			||||||
      :get-show="() => true"
 | 
					      :get-show="() => displayDropDown"
 | 
				
			||||||
      :on-focus="() => $tracker.trackEvent({ eventName: 'Search-bar focused' })"
 | 
					      :on-focus="onFocus"
 | 
				
			||||||
 | 
					      @update:value="() => (displayDropDown = true)"
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      <template #default="{ handleInput, handleBlur, handleFocus, value: slotValue }">
 | 
					      <template #default="{ handleInput, handleBlur, handleFocus, value: slotValue }">
 | 
				
			||||||
        <n-input
 | 
					        <n-input
 | 
				
			||||||
          ref="focusTarget"
 | 
					          ref="inputEl"
 | 
				
			||||||
          round
 | 
					          round
 | 
				
			||||||
          clearable
 | 
					          clearable
 | 
				
			||||||
          :placeholder="`Search a tool (use ${isMac ? 'Cmd' : 'Ctrl'} + K to focus)`"
 | 
					          :placeholder="`Search a tool (use ${isMac ? 'Cmd' : 'Ctrl'} + K to focus)`"
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ import { config } from '@/config';
 | 
				
			|||||||
import MenuIconItem from '@/components/MenuIconItem.vue';
 | 
					import MenuIconItem from '@/components/MenuIconItem.vue';
 | 
				
			||||||
import type { Tool } from '@/tools/tools.types';
 | 
					import type { Tool } from '@/tools/tools.types';
 | 
				
			||||||
import { useToolStore } from '@/tools/tools.store';
 | 
					import { useToolStore } from '@/tools/tools.store';
 | 
				
			||||||
 | 
					import { useTracker } from '@/modules/tracker/tracker.services';
 | 
				
			||||||
import SearchBar from '../components/SearchBar.vue';
 | 
					import SearchBar from '../components/SearchBar.vue';
 | 
				
			||||||
import HeroGradient from '../assets/hero-gradient.svg?component';
 | 
					import HeroGradient from '../assets/hero-gradient.svg?component';
 | 
				
			||||||
import MenuLayout from '../components/MenuLayout.vue';
 | 
					import MenuLayout from '../components/MenuLayout.vue';
 | 
				
			||||||
@ -23,6 +24,8 @@ const commitSha = config.app.lastCommitSha.slice(0, 7);
 | 
				
			|||||||
const makeLabel = (tool: Tool) => () => h(RouterLink, { to: tool.path }, { default: () => tool.name });
 | 
					const makeLabel = (tool: Tool) => () => h(RouterLink, { to: tool.path }, { default: () => tool.name });
 | 
				
			||||||
const makeIcon = (tool: Tool) => () => h(MenuIconItem, { tool });
 | 
					const makeIcon = (tool: Tool) => () => h(MenuIconItem, { tool });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { tracker } = useTracker();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const toolStore = useToolStore();
 | 
					const toolStore = useToolStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const menuOptions = computed<MenuGroupOption[]>(() =>
 | 
					const menuOptions = computed<MenuGroupOption[]>(() =>
 | 
				
			||||||
@ -157,7 +160,7 @@ const menuOptions = computed<MenuGroupOption[]>(() =>
 | 
				
			|||||||
              target="_blank"
 | 
					              target="_blank"
 | 
				
			||||||
              class="support-button"
 | 
					              class="support-button"
 | 
				
			||||||
              :bordered="false"
 | 
					              :bordered="false"
 | 
				
			||||||
              @click="() => $tracker.trackEvent({ eventName: 'Support button clicked' })"
 | 
					              @click="() => tracker.trackEvent({ eventName: 'Support button clicked' })"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              Buy me a coffee
 | 
					              Buy me a coffee
 | 
				
			||||||
              <n-icon v-if="!styleStore.isSmallScreen" :component="Heart" style="margin-left: 5px" />
 | 
					              <n-icon v-if="!styleStore.isSmallScreen" :component="Heart" style="margin-left: 5px" />
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,8 @@
 | 
				
			|||||||
 | 
					import _ from 'lodash';
 | 
				
			||||||
import type Plausible from 'plausible-tracker';
 | 
					import type Plausible from 'plausible-tracker';
 | 
				
			||||||
 | 
					import { inject } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { createTrackerService };
 | 
					export { createTrackerService, useTracker };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function createTrackerService({ plausible }: { plausible: ReturnType<typeof Plausible> }) {
 | 
					function createTrackerService({ plausible }: { plausible: ReturnType<typeof Plausible> }) {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
@ -9,3 +11,17 @@ function createTrackerService({ plausible }: { plausible: ReturnType<typeof Plau
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function useTracker() {
 | 
				
			||||||
 | 
					  const plausible: ReturnType<typeof Plausible> | undefined = inject('plausible');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (_.isNil(plausible)) {
 | 
				
			||||||
 | 
					    throw new Error('Plausible must be instantiated');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const tracker = createTrackerService({ plausible });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    tracker,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,9 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import { useTracker } from '@/modules/tracker/tracker.services';
 | 
				
			||||||
import { useHead } from '@vueuse/head';
 | 
					import { useHead } from '@vueuse/head';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
useHead({ title: 'About - IT Tools' });
 | 
					useHead({ title: 'About - IT Tools' });
 | 
				
			||||||
 | 
					const { tracker } = useTracker();
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
@ -25,7 +27,7 @@ useHead({ title: 'About - IT Tools' });
 | 
				
			|||||||
        href="https://github.com/sponsors/CorentinTh"
 | 
					        href="https://github.com/sponsors/CorentinTh"
 | 
				
			||||||
        rel="noopener"
 | 
					        rel="noopener"
 | 
				
			||||||
        target="_blank"
 | 
					        target="_blank"
 | 
				
			||||||
        @click="() => $tracker.trackEvent({ eventName: 'Support button clicked' })"
 | 
					        @click="() => tracker.trackEvent({ eventName: 'Support button clicked' })"
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        sponsoring me </n-button
 | 
					        sponsoring me </n-button
 | 
				
			||||||
      >.
 | 
					      >.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
import { config } from '@/config';
 | 
					import { config } from '@/config';
 | 
				
			||||||
import { createTrackerService } from '@/modules/tracker/tracker.services';
 | 
					
 | 
				
			||||||
import Plausible from 'plausible-tracker';
 | 
					import Plausible from 'plausible-tracker';
 | 
				
			||||||
import type { App } from 'vue';
 | 
					import type { App } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -8,6 +8,6 @@ export const plausible = {
 | 
				
			|||||||
    const plausible = Plausible(config.plausible);
 | 
					    const plausible = Plausible(config.plausible);
 | 
				
			||||||
    plausible.enableAutoPageviews();
 | 
					    plausible.enableAutoPageviews();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app.config.globalProperties.$tracker = createTrackerService({ plausible });
 | 
					    app.provide('plausible', plausible);
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								src/shims.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								src/shims.d.ts
									
									
									
									
										vendored
									
									
								
							@ -1,10 +1,3 @@
 | 
				
			|||||||
import type { TrackerService } from './modules/tracker/tracker.types';
 | 
					 | 
				
			||||||
declare module 'vue' {
 | 
					 | 
				
			||||||
  interface ComponentCustomProperties {
 | 
					 | 
				
			||||||
    $tracker: TrackerService;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare module '*.vue' {
 | 
					declare module '*.vue' {
 | 
				
			||||||
  import type { ComponentOptions, ComponentOptions } from 'vue';
 | 
					  import type { ComponentOptions, ComponentOptions } from 'vue';
 | 
				
			||||||
  const Component: ComponentOptions;
 | 
					  const Component: ComponentOptions;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user