bloby-bot 0.18.7 → 0.18.9

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.
@@ -1 +1 @@
1
- import{c as e,r as t,t as n}from"./jsx-runtime-C0W9Wf2W.js";import{n as r,r as i,t as a}from"./bloby-BB0UI7YK.js";var o=e(t(),1),s=n(),c=({code:e,language:t,raw:n,className:c,startLine:l,lineNumbers:u,...d})=>{let{shikiTheme:f}=(0,o.useContext)(i),p=r(),[m,h]=(0,o.useState)(n);return(0,o.useEffect)(()=>{if(!p){h(n);return}let r=p.highlight({code:e,language:t,themes:f},e=>{h(e)});r&&h(r)},[e,t,f,p,n]),(0,s.jsx)(a,{className:c,language:t,lineNumbers:u,result:m,startLine:l,...d})};export{c as HighlightedCodeBlockBody};
1
+ import{c as e,r as t,t as n}from"./jsx-runtime-C0W9Wf2W.js";import{n as r,r as i,t as a}from"./bloby-C0lGB4pP.js";var o=e(t(),1),s=n(),c=({code:e,language:t,raw:n,className:c,startLine:l,lineNumbers:u,...d})=>{let{shikiTheme:f}=(0,o.useContext)(i),p=r(),[m,h]=(0,o.useState)(n);return(0,o.useEffect)(()=>{if(!p){h(n);return}let r=p.highlight({code:e,language:t,themes:f},e=>{h(e)});r&&h(r)},[e,t,f,p,n]),(0,s.jsx)(a,{className:c,language:t,lineNumbers:u,result:m,startLine:l,...d})};export{c as HighlightedCodeBlockBody};
@@ -0,0 +1 @@
1
+ import{i as e}from"./bloby-C0lGB4pP.js";export{e as Mermaid};
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content" />
6
6
  <title>Bloby Chat</title>
7
- <script type="module" crossorigin src="/bloby/assets/bloby-BB0UI7YK.js"></script>
7
+ <script type="module" crossorigin src="/bloby/assets/bloby-C0lGB4pP.js"></script>
8
8
  <link rel="modulepreload" crossorigin href="/bloby/assets/jsx-runtime-C0W9Wf2W.js">
9
9
  <link rel="modulepreload" crossorigin href="/bloby/assets/globals-CSKRxRcm.js">
10
10
  <link rel="stylesheet" crossorigin href="/bloby/assets/globals-DwlMzgUn.css">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bloby-bot",
3
- "version": "0.18.7",
3
+ "version": "0.18.9",
4
4
  "releaseNotes": [
5
5
  "1. react router implemented",
6
6
  "2. new workspace design",
@@ -1,16 +1,16 @@
1
1
  import { useEffect, useRef, useCallback } from 'react';
2
2
 
3
+ // v2 sprite config
3
4
  const HP_COLS = 16;
4
5
  const HP_FRAME_W = 126;
5
6
  const HP_FRAME_H = 84;
7
+ const HP_IDLE_FRAME = 10;
6
8
  const HP_ACTIVATE_START = 11;
7
9
  const HP_ACTIVATE_END = 40;
8
- const HP_RECORD_START = 41;
10
+ const HP_RECORD_START = 40;
9
11
  const HP_RECORD_END = 85;
10
- const HP_DEACTIVATE_START = 85;
11
- const HP_DEACTIVATE_END = 191;
12
- const HP_FPS = 24;
13
- const FRAME_MS = 1000 / HP_FPS;
12
+ const HP_BASE_FPS = 24;
13
+ const HP_FAST_FPS = 48;
14
14
 
15
15
  let cachedSprite: HTMLImageElement | null = null;
16
16
  function getSprite(): Promise<HTMLImageElement> {
@@ -29,10 +29,12 @@ interface Props {
29
29
  onDone?: () => void;
30
30
  }
31
31
 
32
+ type HpState = 'idle' | 'activating' | 'activating_then_deactivate' | 'recording' | 'deactivating';
33
+
32
34
  export default function HeadphonesAnimation({ recording, height = 36, onDone }: Props) {
33
35
  const canvasRef = useRef<HTMLCanvasElement>(null);
34
36
  const spriteRef = useRef<HTMLImageElement | null>(cachedSprite);
35
- const stateRef = useRef<'idle' | 'activating' | 'recording' | 'deactivating'>('idle');
37
+ const stateRef = useRef<HpState>('idle');
36
38
  const frameRef = useRef(HP_ACTIVATE_START);
37
39
  const pingPongRef = useRef(1);
38
40
  const lastRef = useRef(0);
@@ -44,28 +46,27 @@ export default function HeadphonesAnimation({ recording, height = 36, onDone }:
44
46
  const displayH = height;
45
47
  const displayW = Math.round(displayH * (HP_FRAME_W / HP_FRAME_H));
46
48
 
47
- // Load sprite once
48
- useEffect(() => {
49
- getSprite().then((img) => { spriteRef.current = img; });
50
- }, []);
49
+ useEffect(() => { getSprite().then((img) => { spriteRef.current = img; }); }, []);
51
50
 
52
- // React to recording prop changes
51
+ // React to recording prop
53
52
  useEffect(() => {
54
53
  if (recording && !prevRecording.current) {
55
54
  stateRef.current = 'activating';
56
55
  frameRef.current = HP_ACTIVATE_START;
56
+ pingPongRef.current = 1;
57
57
  lastRef.current = performance.now();
58
58
  } else if (!recording && prevRecording.current) {
59
- if (stateRef.current === 'activating' || stateRef.current === 'recording') {
59
+ if (stateRef.current === 'activating') {
60
+ stateRef.current = 'activating_then_deactivate';
61
+ } else if (stateRef.current === 'recording') {
60
62
  stateRef.current = 'deactivating';
61
- frameRef.current = HP_DEACTIVATE_START;
63
+ frameRef.current = HP_ACTIVATE_END;
62
64
  lastRef.current = performance.now();
63
65
  }
64
66
  }
65
67
  prevRecording.current = recording;
66
68
  }, [recording]);
67
69
 
68
- // Animation loop
69
70
  const tick = useCallback((now: number) => {
70
71
  const canvas = canvasRef.current;
71
72
  const sprite = spriteRef.current;
@@ -79,24 +80,31 @@ export default function HeadphonesAnimation({ recording, height = 36, onDone }:
79
80
  return;
80
81
  }
81
82
 
83
+ const fps = (state === 'activating' || state === 'activating_then_deactivate' || state === 'deactivating') ? HP_FAST_FPS : HP_BASE_FPS;
84
+ const frameMs = 1000 / fps;
82
85
  const delta = now - lastRef.current;
83
- if (delta >= FRAME_MS) {
84
- lastRef.current = now - (delta % FRAME_MS);
86
+ if (delta >= frameMs) {
87
+ lastRef.current = now - (delta % frameMs);
85
88
 
86
- if (state === 'activating') {
89
+ if (state === 'activating' || state === 'activating_then_deactivate') {
87
90
  frameRef.current++;
88
91
  if (frameRef.current > HP_ACTIVATE_END) {
89
- stateRef.current = 'recording';
90
- frameRef.current = HP_RECORD_START;
91
- pingPongRef.current = 1;
92
+ if (state === 'activating_then_deactivate') {
93
+ stateRef.current = 'deactivating';
94
+ frameRef.current = HP_ACTIVATE_END;
95
+ } else {
96
+ stateRef.current = 'recording';
97
+ frameRef.current = HP_RECORD_START;
98
+ pingPongRef.current = 1;
99
+ }
92
100
  }
93
101
  } else if (state === 'recording') {
94
102
  frameRef.current += pingPongRef.current;
95
103
  if (frameRef.current >= HP_RECORD_END) { frameRef.current = HP_RECORD_END; pingPongRef.current = -1; }
96
104
  else if (frameRef.current <= HP_RECORD_START) { frameRef.current = HP_RECORD_START; pingPongRef.current = 1; }
97
105
  } else if (state === 'deactivating') {
98
- frameRef.current++;
99
- if (frameRef.current > HP_DEACTIVATE_END) {
106
+ frameRef.current--;
107
+ if (frameRef.current < HP_ACTIVATE_START) {
100
108
  stateRef.current = 'idle';
101
109
  ctx.clearRect(0, 0, displayW, displayH);
102
110
  onDoneRef.current?.();
@@ -124,15 +132,9 @@ export default function HeadphonesAnimation({ recording, height = 36, onDone }:
124
132
  canvas.height = displayH * dpr;
125
133
  const ctx = canvas.getContext('2d')!;
126
134
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
127
-
128
135
  rafRef.current = requestAnimationFrame(tick);
129
136
  return () => cancelAnimationFrame(rafRef.current);
130
137
  }, [tick, displayW, displayH]);
131
138
 
132
- return (
133
- <canvas
134
- ref={canvasRef}
135
- style={{ width: displayW, height: displayH, display: 'block' }}
136
- />
137
- );
139
+ return <canvas ref={canvasRef} style={{ width: displayW, height: displayH, display: 'block' }} />;
138
140
  }