mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-11 07:06:28 +08:00
61c0d01da3
Added a recording popup UI for the audio recording feature in the desktop app, improving the user experience when capturing audio from applications. ### What changed? - Created a new popup window system for displaying recording controls - Added a dedicated recording UI with start/stop controls and status indicators - Moved audio encoding logic from the main app to a dedicated module - Implemented smooth animations for popup appearance/disappearance - Updated the recording workflow to show visual feedback during recording process - Added internationalization support for recording-related text - Modified the recording status flow to include new states: new, recording, stopped, ready fix AF-2340
84 lines
1.8 KiB
TypeScript
84 lines
1.8 KiB
TypeScript
import { join } from 'node:path';
|
|
|
|
import type { EventBasedChannel } from 'async-call-rpc';
|
|
|
|
export function getTime() {
|
|
return Date.now();
|
|
}
|
|
|
|
export const isMacOS = () => {
|
|
return process.platform === 'darwin';
|
|
};
|
|
|
|
export const isWindows = () => {
|
|
return process.platform === 'win32';
|
|
};
|
|
|
|
export const isLinux = () => {
|
|
return process.platform === 'linux';
|
|
};
|
|
|
|
interface MessagePortLike {
|
|
postMessage: (data: unknown) => void;
|
|
addListener: (event: 'message', listener: (...args: any[]) => void) => void;
|
|
removeListener: (
|
|
event: 'message',
|
|
listener: (...args: any[]) => void
|
|
) => void;
|
|
}
|
|
|
|
export class MessageEventChannel implements EventBasedChannel {
|
|
constructor(private readonly worker: MessagePortLike) {}
|
|
|
|
on(listener: (data: unknown) => void) {
|
|
const f = (data: unknown) => {
|
|
listener(data);
|
|
};
|
|
this.worker.addListener('message', f);
|
|
return () => {
|
|
this.worker.removeListener('message', f);
|
|
};
|
|
}
|
|
|
|
send(data: unknown) {
|
|
this.worker.postMessage(data);
|
|
}
|
|
}
|
|
|
|
export const resourcesPath = join(__dirname, `../resources`);
|
|
|
|
// credit: https://github.com/facebook/fbjs/blob/main/packages/fbjs/src/core/shallowEqual.js
|
|
export function shallowEqual<T>(objA: T, objB: T) {
|
|
if (Object.is(objA, objB)) {
|
|
return true;
|
|
}
|
|
|
|
if (
|
|
typeof objA !== 'object' ||
|
|
objA === null ||
|
|
typeof objB !== 'object' ||
|
|
objB === null
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
const keysA = Object.keys(objA);
|
|
const keysB = Object.keys(objB);
|
|
|
|
if (keysA.length !== keysB.length) {
|
|
return false;
|
|
}
|
|
|
|
// Test for A's keys different from B.
|
|
for (const key of keysA) {
|
|
if (
|
|
!Object.prototype.hasOwnProperty.call(objB, key) ||
|
|
!Object.is(objA[key as keyof T], objB[key as keyof T])
|
|
) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|