@christianriedl/utils 1.0.106 → 1.0.108

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/types.d.ts CHANGED
@@ -134,3 +134,7 @@ export interface IAppConfig {
134
134
  loggerQueueSize: number;
135
135
  logDescending: boolean;
136
136
  }
137
+ export type IdType = string | number;
138
+ export interface IEntity {
139
+ id: IdType;
140
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@christianriedl/utils",
3
- "version": "1.0.106",
3
+ "version": "1.0.108",
4
4
  "description": "Interfaces, local storage, service worker, configuration, application state",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,8 +12,11 @@
12
12
  const appConfig = inject(appConfigSymbol)!;
13
13
  const question = toRef(props, "prompt");
14
14
  const replyLines = ref<string[]>([]);
15
- const qcols = computed(() => appState.size.value >= ESize.md ? 11 : 10);
15
+ const qcols = computed(() => appState.size.value >= ESize.md ? 10 : 9);
16
16
  const isCamera = ref(false);
17
+ const isUpload = ref(false);
18
+ const files = ref<File[]>([]);
19
+ const dataUrl = ref("");
17
20
  const camera = ref<InstanceType<typeof Camera>>();
18
21
 
19
22
  onUnmounted (() => {
@@ -22,11 +25,19 @@
22
25
  });
23
26
 
24
27
  async function onComplete() {
25
- let answer: ICompleteData;
26
28
  replyLines.value = [ "WAITING ..." ];
27
- if (isCamera.value && camera.value) {
28
- const dataurl = await camera.value.snapshot();
29
- answer = await openAI.completeImage(question.value, dataurl!);
29
+ files.value = [];
30
+ isUpload.value = false;
31
+ let answer: ICompleteData;
32
+ if (camera.value) {
33
+ dataUrl.value = await camera.value.snapshot() as string;
34
+ camera.value.stop();
35
+ camera.value = undefined;
36
+ isCamera.value = false;
37
+ }
38
+ if (dataUrl.value) {
39
+ answer = await openAI.completeImage(question.value, dataUrl.value);
40
+ dataUrl.value = "";
30
41
  }
31
42
  else {
32
43
  answer = await openAI.complete(question.value);
@@ -42,6 +53,7 @@
42
53
  question.value = result.item(0).transcript;
43
54
  }
44
55
  function onCamera() {
56
+ replyLines.value = [];
45
57
  isCamera.value = !isCamera.value;
46
58
  if (isCamera.value && !question.value) {
47
59
  question.value = "Was erkennst du auf dem Bild ?";
@@ -51,6 +63,19 @@
51
63
  camera.value = undefined;
52
64
  }
53
65
  }
66
+ function onFile() {
67
+ if (!question.value) {
68
+ question.value = "Was erkennst du auf dem Bild ?";
69
+ }
70
+ if (files.value && files.value.length > 0) {
71
+ const reader = new FileReader();
72
+ reader.addEventListener ("load", async() => {
73
+ // convert image file to base64 string
74
+ dataUrl.value = reader.result as string;
75
+ }, false, );
76
+ reader.readAsDataURL(files.value[0]);
77
+ }
78
+ }
54
79
  </script>
55
80
 
56
81
  <template>
@@ -60,11 +85,14 @@
60
85
  <v-text-field name="subject" type="text" v-model="question" density="compact" hide-details></v-text-field>
61
86
  </v-col>
62
87
  <v-col :cols="12 - qcols">
63
- <v-btn @click="onComplete">AI</v-btn>
64
- <microphone lang="de" @result="onResult"></microphone>
65
- <v-btn variant="tonal" class="bg-office" @click="onCamera">
88
+ <v-btn class="aibutton" @click="onComplete">AI</v-btn>
89
+ <microphone lang="de" cls="aibutton" @result="onResult"></microphone>
90
+ <v-btn variant="tonal" class="bg-office aibutton" @click="onCamera">
66
91
  <v-icon size="large" icon="$webcam" color="primary"></v-icon>
67
92
  </v-btn>
93
+ <v-btn variant="tonal" class="bg-office aibutton" @click="isUpload=true;replyLines=[]">
94
+ <v-icon size="large" icon="$image" color="primary"></v-icon>
95
+ </v-btn>
68
96
  </v-col>
69
97
  </v-row>
70
98
  <v-row v-if="isCamera" dense align="center">
@@ -77,9 +105,26 @@
77
105
  </v-row>
78
106
  </v-col>
79
107
  </v-row>
108
+ <v-row v-if="isUpload" dense align="center">
109
+ <v-col cols="6">
110
+ <v-file-input show-size clearable multiple hide-details v-model="files" accept="image/*" label="Select File" prepend-icon="" append-icon="" @update:modelValue="onFile">
111
+ </v-file-input>
112
+ </v-col>
113
+ <v-col cols="6">
114
+ <img width="100%" :src="dataUrl">
115
+ </img>
116
+ </v-col>
117
+ </v-row>
80
118
  <v-row v-else v-for="(line, index) in replyLines" :key=index dense align="center">
81
119
  <v-col cols="12">{{line}}</v-col>
82
120
  </v-row>
83
121
  </v-container>
84
122
  </template>
85
123
 
124
+ <style scoped>
125
+ .aibutton {
126
+ min-width: 32px;
127
+ padding: 0 8px;
128
+ }
129
+ </style>
130
+