initial commit

This commit is contained in:
Tholut A 2026-08-08 17:55:56 +07:00
commit 7e466e29d2
28 changed files with 17360 additions and 0 deletions

114
components/BlockedSite.vue Normal file
View file

@ -0,0 +1,114 @@
<script lang="ts" setup>
import { BLOCKED_SITES_REPO_KEY } from "@/utils/proxy-service-keys";
import { BlockedSite } from "@/utils/types";
import { createProxyService } from '@webext-core/proxy-service';
import { v4 as uuidv4 } from "uuid"
const blockedSitesRepo = createProxyService(BLOCKED_SITES_REPO_KEY);
const props = defineProps<{}>()
const blockedSites = ref<BlockedSite[]>([]);
const inputNewSite = ref<string | null>();
const refreshBlockedSite = async () => {
blockedSites.value = await blockedSitesRepo.getAll();
}
onBeforeMount(async () => refreshBlockedSite())
const insertBlockedSite = async () => {
if (!inputNewSite.value) return
if (!inputNewSite.value.trim()) return
const generateTodoId = uuidv4()
await blockedSitesRepo.insert({
id: generateTodoId,
url: inputNewSite.value,
blocked: true
})
inputNewSite.value = null
refreshBlockedSite()
}
const updateBlockedSite = async (blockedSite: BlockedSite) => {
await blockedSitesRepo.update(toRaw(blockedSite))
refreshBlockedSite()
}
const deleteBlockedSite = async (blockedSite: BlockedSite) => {
await blockedSitesRepo.delete(toRaw(blockedSite))
refreshBlockedSite()
}
</script>
<template>
<div class="container">
<h2>[blocked sites]</h2>
<div class="form-input">
<input @keydown.enter="insertBlockedSite" v-model="inputNewSite" placeholder="ba-ka.org" type="input"/>
<button @click="insertBlockedSite">[add site]</button>
</div>
<br/>
<div v-if="blockedSites.length === 0">no blocked sites :(</div>
<ul v-else v-for="blockedSite in blockedSites">
<li :key="blockedSite.id">
<label>
<input type="checkbox" @change="updateBlockedSite(blockedSite)" v-model="blockedSite.blocked" :id="blockedSite.id"/>
{{ blockedSite.url }}
<button class="button-delete" @click="deleteBlockedSite(blockedSite)">x</button>
</label>
</li>
</ul>
</div>
</template>
<style scoped>
.container {
min-width: 300px;
}
ul {
padding: 0;
}
li {
list-style: none;
text-align: left;
font-size: 14pt;
}
li label {
display: block;
}
li label:hover {
cursor: pointer;
border: 1px solid #ffffff;
}
li .button-delete {
display: none;
padding: 1px 4px;
font-size: 10pt;
float: right
}
li:hover .button-delete {
display: inline-block;
}
.form-input input,
.form-input button {
width: 100%;
padding: 2px 4px;
margin-bottom: 5px;
}
.form-input input {
font-size: 12pt;
box-sizing: border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing: border-box;
}
</style>

140
components/Todo.vue Normal file
View file

@ -0,0 +1,140 @@
<script lang="ts" setup>
import { TODOS_REPO_KEY } from "@/utils/proxy-service-keys";
import { Todo } from "@/utils/types";
import { createProxyService } from '@webext-core/proxy-service';
import { v4 as uuidv4 } from "uuid"
const todosRepo = createProxyService(TODOS_REPO_KEY);
const props = defineProps<{
showCompleted?: boolean,
showOnlyCompleted?: boolean,
showInput?: boolean,
hoverShowDeleteButton?: boolean,
showClearAllTodo?: boolean
}>()
const todos = ref<Todo[]>([]);
const inputNewTodo = ref<string | null>();
const refreshTodo = async () => {
const allTodos = await todosRepo.getAll();
todos.value = allTodos.filter(
(todo: Todo) =>
(props.showCompleted && todo.completed) ||
(props.showOnlyCompleted && todo.completed) ||
(!props.showOnlyCompleted && !todo.completed)
)
}
onBeforeMount(async () => refreshTodo())
const insertTodo = async () => {
if (!inputNewTodo.value) return
if (!inputNewTodo.value.trim()) return
const generateTodoId = uuidv4()
await todosRepo.insert({
id: generateTodoId,
name: inputNewTodo.value,
completed: false
})
inputNewTodo.value = null
refreshTodo()
}
const updateTodo = async (todo: Todo) => {
await todosRepo.update(toRaw(todo))
refreshTodo()
}
const deleteTodo = async (todo: Todo) => {
await todosRepo.delete(toRaw(todo))
refreshTodo()
}
const clearAllCompletedTodo = async () => {
const allTodos = await todosRepo.getAll()
const completedTodos = allTodos.filter((todo) => todo.completed)
const deletePromises = completedTodos.map((todo) => todosRepo.delete(todo))
await Promise.all(deletePromises)
refreshTodo()
}
</script>
<template>
<div class="container">
<h2 v-if="props.showOnlyCompleted">[completed todos]</h2>
<h2 v-if="!props.showOnlyCompleted">[todos]</h2>
<div v-if="showInput" class="form-input">
<input @keydown.enter="insertTodo" v-model="inputNewTodo" placeholder="playing skateboard at 5am" type="input"/>
<button @click="insertTodo">[add todo]</button>
</div>
<div v-if="showClearAllTodo">
<button @click="clearAllCompletedTodo">[clear all completed todos]</button>
</div>
<br/>
<div v-if="todos.length === 0">no todos :D</div>
<ul v-else v-for="todo in todos">
<li :class="{ completed: todo.completed }" :key="todo.id">
<label>
<input type="checkbox" @change="updateTodo(todo)" v-model="todo.completed" :id="todo.id"/>
{{ todo.name }}
<button class="button-delete" v-if="props.hoverShowDeleteButton" @click="deleteTodo(todo)">x</button>
</label>
</li>
</ul>
</div>
</template>
<style scoped>
.container {
min-width: 300px;
}
ul {
padding: 0;
}
li {
list-style: none;
text-align: left;
font-size: 14pt;
}
li label {
display: block;
}
li label:hover {
cursor: pointer;
}
li.completed {
text-decoration: line-through;
}
li .button-delete {
display: none;
padding: 1px 4px;
font-size: 10pt;
float: right
}
li:hover .button-delete {
display: inline-block;
}
.form-input input,
.form-input button {
width: 100%;
padding: 2px 4px;
margin-bottom: 5px;
}
.form-input input {
font-size: 12pt;
box-sizing: border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing: border-box;
}
</style>

View file

@ -0,0 +1,54 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { featureEnableBlock } from "@/utils/storage"
const isEnabled = ref(false)
let unwatchStorage: (() => void | undefined)
onMounted(async() => {
isEnabled.value = await featureEnableBlock.getValue()
unwatchStorage = featureEnableBlock.watch((newValue) => {
if (newValue !== isEnabled.value) {
isEnabled.value = newValue
}
})
})
onUnmounted(() => {
if (unwatchStorage) unwatchStorage();
})
watch(isEnabled, async (newValue) => {
await featureEnableBlock.setValue(newValue)
})
const toggleOnOff = () => {
isEnabled.value = !isEnabled.value
}
</script>
<template>
<button @click="toggleOnOff" class="button-toggle">
<img src="/icon/128.png" class="logo" :class="{ 'logo-on': isEnabled }" alt="let me focus logo" />
</button>
<br/>
{{ isEnabled ? '[on]' : '[off]' }}
</template>
<style scoped>
.button-toggle {
padding: 0;
margin: 0;
border: none;
background: none;
}
.button-toggle .logo {
width: 80%;
cursor: pointer;
}
.button-toggle .logo-on {
filter: drop-shadow(0 0 1em #ffffff);
}
</style>