feat(electron): add welcome page for meetings (#12042)

fix AF-2572

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/0e56b58a-97b4-4984-81fa-f8e45f8cc561.png)

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/97e3bb97-e326-48f6-8dd4-27734f583775.png)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a Meetings welcome page with a beta disclaimer and "Get Started" flow.
  - Added separate toggles for AI auto summary and AI auto todo list in meeting settings.
  - Added "Beta" labels to relevant settings and sidebar items for clearer feature status.
  - Enhanced settings UI with improved headers, subtitles, and new styling.

- **Improvements**
  - Meeting settings now allow independent control over AI-generated summaries and todo lists.
  - Updated internationalization to support new meeting and AI transcription features, including richer prompts and hints.
  - Refined logic for enabling meeting recording, including improved permission handling.
  - Simplified transcription logic to rely solely on AI enablement flag.

- **Bug Fixes**
  - Fixed display and control of meeting settings based on beta disclaimer acceptance.

- **Chores**
  - Updated localization files and completeness percentages for several languages.
  - Removed deprecated feature flag for enabling meetings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
pengx17
2025-05-06 09:29:57 +00:00
parent f79dfe837f
commit 53c531c931
36 changed files with 1470 additions and 201 deletions
@@ -260,18 +260,6 @@ export const AFFINE_FLAGS = {
configurable: isCanaryBuild,
defaultState: false,
},
enable_meetings: {
category: 'affine',
displayName:
'com.affine.settings.workspace.experimental-features.enable-meetings.name',
description:
'com.affine.settings.workspace.experimental-features.enable-meetings.description',
configurable: !isMobile && environment.isMacOs && BUILD_CONFIG.isElectron,
feedbackType: 'discord',
feedbackLink:
'https://discord.com/channels/959027316334407691/1358384103925350542',
defaultState: false,
},
// TODO(@L-Sun): remove this flag after the feature is released
enable_embed_doc_with_alias: {
category: 'blocksuite',
@@ -16,6 +16,7 @@ import { cssVarV2 } from '@toeverything/theme/v2';
import type { WorkspaceService } from '../../workspace';
import type { AudioMediaManagerService } from '../services/audio-media-manager';
import type { MeetingSettingsService } from '../services/meeting-settings';
import type { AudioMedia } from './audio-media';
import { AudioTranscriptionJob } from './audio-transcription-job';
import type { TranscriptionResult } from './types';
@@ -44,7 +45,8 @@ export class AudioAttachmentBlock extends Entity<AttachmentBlockModel> {
readonly audioMedia: AudioMedia;
constructor(
readonly audioMediaManagerService: AudioMediaManagerService,
readonly workspaceService: WorkspaceService
readonly workspaceService: WorkspaceService,
readonly meetingSettingsService: MeetingSettingsService
) {
super();
const mediaRef = audioMediaManagerService.ensureMediaEntity(this.props);
@@ -256,7 +258,11 @@ export class AudioAttachmentBlock extends Entity<AttachmentBlockModel> {
);
};
fillTranscription(result.segments);
await fillSummary(result.summary);
await fillActions(result.actions);
if (this.meetingSettingsService.settings.autoTranscriptionSummary) {
await fillSummary(result.summary);
}
if (this.meetingSettingsService.settings.autoTranscriptionTodo) {
await fillActions(result.actions);
}
};
}
@@ -22,7 +22,11 @@ export function configureMediaModule(framework: Framework) {
.service(MeetingSettingsService, [GlobalStateService])
.scope(WorkspaceScope)
.entity(AudioMedia, [WorkspaceService])
.entity(AudioAttachmentBlock, [AudioMediaManagerService, WorkspaceService])
.entity(AudioAttachmentBlock, [
AudioMediaManagerService,
WorkspaceService,
MeetingSettingsService,
])
.entity(AudioTranscriptionJob, [
WorkspaceServerService,
DefaultServerService,
@@ -12,8 +12,10 @@ const MEETING_SETTINGS_KEY: typeof MeetingSettingsKey = 'meetingSettings';
const defaultMeetingSettings: MeetingSettingsSchema = {
enabled: false,
betaDisclaimerAccepted: false,
recordingSavingMode: 'new-doc',
autoTranscription: true,
autoTranscriptionSummary: true,
autoTranscriptionTodo: true,
recordingMode: 'prompt',
};
@@ -41,6 +43,13 @@ export class MeetingSettingsService extends Service {
return this.settings$.value;
}
setBetaDisclaimerAccepted(accepted: boolean) {
this.globalStateService.globalState.set(MEETING_SETTINGS_KEY, {
...this.settings$.value,
betaDisclaimerAccepted: accepted,
});
}
// we do not want the caller to directly set the settings,
// there could be some side effects when the settings are changed.
async setEnabled(enabled: boolean) {
@@ -91,10 +100,17 @@ export class MeetingSettingsService extends Service {
});
}
setAutoTranscription(autoTranscription: boolean) {
setAutoSummary(autoSummary: boolean) {
this.globalStateService.globalState.set(MEETING_SETTINGS_KEY, {
...this.settings$.value,
autoTranscription,
autoTranscriptionSummary: autoSummary,
});
}
setAutoTodo(autoTodo: boolean) {
this.globalStateService.globalState.set(MEETING_SETTINGS_KEY, {
...this.settings$.value,
autoTranscriptionTodo: autoTodo,
});
}