Newer
Older
bugtrail / packages / extension / src / content / overlay / App.vue
<script setup lang="ts">
import { ref } from "vue";
import browser from "webextension-polyfill";
import type { ElementContext } from "@ltt/shared";
import type { OverlayState } from "./mount";
import PickerLayer from "./PickerLayer.vue";
import NoteComposer from "./NoteComposer.vue";
import RecorderBar from "./RecorderBar.vue";

const props = defineProps<{ state: OverlayState }>();

const pickedElement = ref<ElementContext | null>(null);
const composerOpen = ref(false);

function onPick(element: ElementContext) {
  pickedElement.value = element;
  composerOpen.value = true;
}

function closeComposer() {
  composerOpen.value = false;
  pickedElement.value = null;
  // keep the picker alive while recording so another element can be picked
  props.state.mode = props.state.recording ? "picker" : "idle";
}

function cancelPicker() {
  props.state.mode = "idle";
}

async function stopRecorder() {
  const response = (await browser.runtime.sendMessage({ type: "recorder_stop" })) as {
    ok: boolean;
    error?: string;
  };
  if (!response?.ok) console.error("[ltt] recorder stop failed:", response?.error);
  props.state.recording = false;
  props.state.mode = "idle";
}
</script>

<template>
  <div class="ltt-overlay-root">
    <PickerLayer
      v-if="state.mode === 'picker' && !composerOpen"
      class="ltt-interactive"
      @pick="onPick"
      @cancel="cancelPicker"
    />
    <NoteComposer
      v-if="composerOpen && pickedElement"
      class="ltt-interactive"
      :element="pickedElement"
      @close="closeComposer"
      @submitted="closeComposer"
    />
    <RecorderBar
      v-if="state.recording && !composerOpen"
      class="ltt-interactive"
      @note="state.mode = 'picker'"
      @stop="stopRecorder"
    />
  </div>
</template>