Compare commits

..

6 Commits

Author SHA1 Message Date
f2203e896e chore: bump version to 0.6.16
All checks were successful
Deploy to Production / deploy (push) Successful in 13s
2026-03-03 10:03:44 +00:00
cb8d3d01ec fix: update extension link to Chrome Web Store 2026-03-03 10:03:41 +00:00
5b31171964 0.6.15
All checks were successful
Deploy to Production / deploy (push) Successful in 13s
2026-03-03 00:02:34 +00:00
e98761a18e feat: make header title a link to home page 2026-03-03 00:02:17 +00:00
bc8168e724 0.6.14
All checks were successful
Deploy to Production / deploy (push) Successful in 14s
2026-03-02 23:59:04 +00:00
dcde3b0799 feat: add ESC key support to close all modals and fullscreen modes 2026-03-02 23:58:50 +00:00
7 changed files with 70 additions and 10 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "tools-app", "name": "tools-app",
"version": "0.6.13", "version": "0.6.16",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "tools-app", "name": "tools-app",
"version": "0.6.13", "version": "0.6.16",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"barcode-detector": "^3.1.0", "barcode-detector": "^3.1.0",

View File

@@ -1,7 +1,7 @@
{ {
"name": "tools-app", "name": "tools-app",
"private": true, "private": true,
"version": "0.6.13", "version": "0.6.16",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@@ -44,7 +44,7 @@ onMounted(() => {
<line x1="3" y1="18" x2="21" y2="18"></line> <line x1="3" y1="18" x2="21" y2="18"></line>
</svg> </svg>
</button> </button>
<h1 class="app-title">Tools App</h1> <router-link to="/" class="app-title">Tools App</router-link>
</div> </div>
<button <button
@@ -115,10 +115,11 @@ onMounted(() => {
.app-title { .app-title {
margin: 0; margin: 0;
font-size: 1.5rem; font-size: 1.5rem;
font-weight: 600;
background: var(--title-gradient); background: var(--title-gradient);
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text; background-clip: text;
color: transparent;
text-decoration: none;
font-weight: bold;
} }
</style> </style>

View File

@@ -51,12 +51,20 @@ const dismissPrompt = () => {
deferredPrompt = null deferredPrompt = null
} }
const handleKeydown = (e) => {
if (e.key === 'Escape' && showInstallPrompt.value) {
dismissPrompt()
}
}
onMounted(() => { onMounted(() => {
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt) window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
window.addEventListener('keydown', handleKeydown)
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt) window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt)
window.removeEventListener('keydown', handleKeydown)
}) })
</script> </script>

View File

@@ -377,11 +377,18 @@ watch(scannedCodes, (newVal) => {
localStorage.setItem('qr-history', JSON.stringify(newVal)) localStorage.setItem('qr-history', JSON.stringify(newVal))
}, { deep: true }) }, { deep: true })
const handleKeydown = (e) => {
if (e.key === 'Escape' && isFullscreen.value) {
toggleFullscreen()
}
}
onMounted(() => { onMounted(() => {
checkCameras() checkCameras()
loadHistory() loadHistory()
window.addEventListener('resize', updateVideoAspect) window.addEventListener('resize', updateVideoAspect)
window.addEventListener('resize', startBackgroundLoop) window.addEventListener('resize', startBackgroundLoop)
window.addEventListener('keydown', handleKeydown)
watch(isFullscreen, (fs) => { watch(isFullscreen, (fs) => {
if (fs) { if (fs) {
startBackgroundLoop() startBackgroundLoop()
@@ -389,13 +396,14 @@ onMounted(() => {
stopBackgroundLoop() stopBackgroundLoop()
} }
}, { immediate: true }) }, { immediate: true })
startScan() startScan()
}) })
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('resize', updateVideoAspect) window.removeEventListener('resize', updateVideoAspect)
window.removeEventListener('resize', startBackgroundLoop) window.removeEventListener('resize', startBackgroundLoop)
window.removeEventListener('keydown', handleKeydown)
stopScan() stopScan()
}) })

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, computed } from 'vue' import { ref, computed, watch, onUnmounted } from 'vue'
import { X, Plus, Trash2, RotateCcw } from 'lucide-vue-next' import { X, Plus, Trash2, RotateCcw } from 'lucide-vue-next'
const props = defineProps({ const props = defineProps({
@@ -10,6 +10,24 @@ const props = defineProps({
const emit = defineEmits(['close', 'update:exceptions']) const emit = defineEmits(['close', 'update:exceptions'])
const handleKeydown = (e) => {
if (e.key === 'Escape') {
emit('close')
}
}
watch(() => props.isOpen, (isOpen) => {
if (isOpen) {
window.addEventListener('keydown', handleKeydown)
} else {
window.removeEventListener('keydown', handleKeydown)
}
})
onUnmounted(() => {
window.removeEventListener('keydown', handleKeydown)
})
const newRule = ref({ const newRule = ref({
domainPattern: '', domainPattern: '',
keepParams: '', keepParams: '',

View File

@@ -5,7 +5,7 @@ export default {
</script> </script>
<script setup> <script setup>
import { ref } from 'vue' import { ref, watch, onUnmounted } from 'vue'
import { Plug, Plus, X } from 'lucide-vue-next' import { Plug, Plus, X } from 'lucide-vue-next'
const props = defineProps({ const props = defineProps({
@@ -13,6 +13,24 @@ const props = defineProps({
}) })
const showModal = ref(false) const showModal = ref(false)
const handleKeydown = (e) => {
if (e.key === 'Escape' && showModal.value) {
showModal.value = false
}
}
watch(showModal, (isOpen) => {
if (isOpen) {
window.addEventListener('keydown', handleKeydown)
} else {
window.removeEventListener('keydown', handleKeydown)
}
})
onUnmounted(() => {
window.removeEventListener('keydown', handleKeydown)
})
</script> </script>
<template> <template>
@@ -38,7 +56,14 @@ const showModal = ref(false)
With the extension, you can capture and process content even when you're working in other apps. With the extension, you can capture and process content even when you're working in other apps.
</p> </p>
<div class="modal-actions"> <div class="modal-actions">
<a href="#" class="btn-neon" @click.prevent>Extension Coming Soon</a> <a
href="https://chromewebstore.google.com/detail/tools-app-extension/bhcpbmfncohogehbhebiffcgjcndnneg"
target="_blank"
rel="noopener noreferrer"
class="btn-neon"
>
Install Extension
</a>
</div> </div>
</div> </div>