fmode-ng 0.0.39 → 0.0.41
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/esm2022/fmode-ng.mjs +5 -10
- package/esm2022/lib/aigc/agent/agent.prompt.mjs +122 -10
- package/esm2022/lib/aigc/agent/index.mjs +2 -10
- package/esm2022/lib/aigc/avatar/avatar.module.mjs +45 -10
- package/esm2022/lib/aigc/avatar/comp-avatar-particle/avatar.role.mjs +2 -10
- package/esm2022/lib/aigc/avatar/comp-avatar-particle/comp-avatar-particle.component.mjs +315 -10
- package/esm2022/lib/aigc/avatar/comp-avatar-particle/index.mjs +3 -10
- package/esm2022/lib/aigc/avatar/comp-avatar-particle/role-points.class.mjs +57 -10
- package/esm2022/lib/aigc/avatar/comp-avatar-role-image/comp-avatar-role-image.component.mjs +97 -10
- package/esm2022/lib/aigc/avatar/comp-avatar-role-video/comp-avatar-role-video.component.mjs +104 -10
- package/esm2022/lib/aigc/avatar/comp-avatar-talk/comp-avatar-talk.component.mjs +111 -10
- package/esm2022/lib/aigc/avatar/index.mjs +8 -10
- package/esm2022/lib/aigc/avatar/interface-avatar-role.mjs +2 -10
- package/esm2022/lib/aigc/avatar/modal-chat-voice-input/modal-chat-voice-input.component.mjs +166 -8
- package/esm2022/lib/aigc/chat/chat-header-area/comp-header-area.component.mjs +36 -10
- package/esm2022/lib/aigc/chat/chat-header-area/index.mjs +2 -10
- package/esm2022/lib/aigc/chat/chat-list/chat-list.component.mjs +141 -8
- package/esm2022/lib/aigc/chat/chat-list/index.mjs +2 -10
- package/esm2022/lib/aigc/chat/chat-message-area/comp-message-area.component.mjs +40 -10
- package/esm2022/lib/aigc/chat/chat-message-area/index.mjs +2 -10
- package/esm2022/lib/aigc/chat/chat-message-card/comp-message-card.component.mjs +92 -10
- package/esm2022/lib/aigc/chat/chat-message-card/index.mjs +2 -10
- package/esm2022/lib/aigc/chat/chat-modal-input/index.mjs +2 -10
- package/esm2022/lib/aigc/chat/chat-modal-input/modal-audio-message/modal-audio-message.component.mjs +207 -8
- package/esm2022/lib/aigc/chat/chat-modal-input/modal-input.component.mjs +236 -10
- package/esm2022/lib/aigc/chat/chat-panel/chat-panel.component.mjs +137 -10
- package/esm2022/lib/aigc/chat/comp-role-prompt/comp-role-prompt.component.mjs +69 -10
- package/esm2022/lib/aigc/chat/comp-role-prompt/index.mjs +2 -10
- package/esm2022/lib/aigc/chat/index.mjs +8 -10
- package/esm2022/lib/aigc/comp-markdown-preview/clipboard.service.mjs +82 -10
- package/esm2022/lib/aigc/comp-markdown-preview/markdown-parse.mjs +269 -8
- package/esm2022/lib/aigc/comp-markdown-preview/markdown-preview.component.mjs +51 -10
- package/esm2022/lib/aigc/comp-markdown-preview/markdown-preview.module.mjs +24 -10
- package/esm2022/lib/aigc/comp-markdown-preview/plugins/md-mathjax/index.mjs +94 -10
- package/esm2022/lib/aigc/index.mjs +13 -10
- package/esm2022/lib/aigc/service-fmai/fmai.service.mjs +21 -10
- package/esm2022/lib/aigc/service-fmai/service-chat/chat-class.mjs +736 -8
- package/esm2022/lib/aigc/service-fmai/service-chat/chat.service.mjs +181 -8
- package/esm2022/lib/aigc/service-fmai/service-chat/index.mjs +7 -10
- package/esm2022/lib/aigc/service-fmai/service-chat/mask-list.mjs +194 -9
- package/esm2022/lib/aigc/service-fmai/service-chat/pipes/chat-content.pipe.mjs +27 -10
- package/esm2022/lib/aigc/service-fmai/service-chat/pipes/hidexml.pipe.mjs +27 -10
- package/esm2022/lib/aigc/service-fmai/service-chat/utilnow.pipe.mjs +68 -10
- package/esm2022/lib/aigc/service-fmai/service-imagine/imagine.service.mjs +229 -8
- package/esm2022/lib/aigc/service-fmai/service-imagine/index.mjs +2 -10
- package/esm2022/lib/aigc/voice/audio.player.mjs +52 -10
- package/esm2022/lib/aigc/voice/class-asr.mjs +79 -8
- package/esm2022/lib/aigc/voice/fmode-voice.service.mjs +501 -8
- package/esm2022/lib/aigc/voice/index.mjs +3 -10
- package/esm2022/lib/aigc/voice/lib/pcm2wav.mjs +38 -10
- package/esm2022/lib/aigc/voice/lib/resample.mjs +34 -10
- package/esm2022/lib/aigc/voice/tts/fmode-tts-class.mjs +233 -8
- package/esm2022/lib/aigc/voice/tts/index.mjs +2 -10
- package/esm2022/lib/map/comp-poi-picker/comp-poi-picker.component.mjs +190 -10
- package/esm2022/lib/map/comp-poi-picker/comp-poi-picker.module.mjs +33 -10
- package/esm2022/lib/map/index.mjs +4 -10
- package/esm2022/lib/map/map.module.mjs +61 -10
- package/esm2022/lib/map/page-loca-scatter/page-loca-scatter.component.mjs +110 -10
- package/esm2022/lib/map/page-map.start/page-map.start.component.mjs +98 -8
- package/esm2022/lib/map/page-plan-route/page-plan-route.component.mjs +100 -8
- package/esm2022/lib/nova-cloud/index.mjs +2 -10
- package/esm2022/lib/nova-cloud/nova-cloud.service.mjs +148 -10
- package/esm2022/lib/platform/cross.service.mjs +63 -10
- package/esm2022/lib/platform/index.mjs +2 -10
- package/esm2022/lib/social/index.mjs +2 -10
- package/esm2022/lib/social/wechat/wechat-jssdk.service.mjs +236 -8
- package/esm2022/lib/storage/comp-hwobs-manager/hwobs-manager.component.mjs +59 -10
- package/esm2022/lib/storage/index.mjs +5 -10
- package/esm2022/lib/storage/service-hwobs/hwobs.service.mjs +130 -8
- package/esm2022/lib/storage/service-upload/index.mjs +2 -10
- package/esm2022/lib/storage/service-upload/nova-upload.service.mjs +462 -8
- package/esm2022/lib/storage/service-upload/util-file-md5.mjs +28 -10
- package/esm2022/lib/storage/storage.module.mjs +41 -10
- package/esm2022/lib/user/account/account.service.mjs +221 -10
- package/esm2022/lib/user/captcha/captcha.component.mjs +135 -10
- package/esm2022/lib/user/comp-user-avatar/comp-user-avatar.component.mjs +62 -10
- package/esm2022/lib/user/index.mjs +17 -10
- package/esm2022/lib/user/login/auth.guard.mjs +28 -10
- package/esm2022/lib/user/login/auth.service.mjs +373 -8
- package/esm2022/lib/user/login/login.component.mjs +913 -10
- package/esm2022/lib/user/modal-user-login/modal-user-login.component.mjs +273 -10
- package/esm2022/lib/user/profile/auth-profile.guard.mjs +27 -10
- package/esm2022/lib/user/profile/auth-profile.service.mjs +122 -10
- package/esm2022/lib/user/profile/profile-bind/profile-bind.component.mjs +115 -10
- package/esm2022/lib/user/profile/profile.module.mjs +57 -10
- package/esm2022/lib/user/staff/index.mjs +4 -10
- package/esm2022/lib/user/staff/staff.guard.mjs +26 -10
- package/esm2022/lib/user/staff/staff.module.mjs +18 -10
- package/esm2022/lib/user/staff/staff.service.mjs +85 -10
- package/esm2022/lib/user/user-name.pipe.mjs +29 -10
- package/esm2022/lib/user/user.module.mjs +106 -10
- package/esm2022/lib/video/fm-video/fm-video.component.mjs +67 -10
- package/esm2022/lib/video/index.mjs +2 -10
- package/esm2022/public-api.mjs +13 -10
- package/fesm2022/fmode-ng.mjs +8895 -7
- package/fesm2022/fmode-ng.mjs.map +1 -1
- package/lib/user/login/auth.service.d.ts +18 -3
- package/lib/user/modal-user-login/modal-user-login.component.d.ts +4 -2
- package/package.json +1 -1
- package/LICENSE.md +0 -8
package/esm2022/lib/aigc/chat/chat-modal-input/modal-audio-message/modal-audio-message.component.mjs
CHANGED
|
@@ -1,10 +1,209 @@
|
|
|
1
|
-
|
|
1
|
+
import { Component, Input } from '@angular/core';
|
|
2
|
+
import { IonButton, IonIcon, IonSpinner, ModalController, ToastController } from '@ionic/angular/standalone';
|
|
3
|
+
import { FmodeVoiceService } from '../../../voice/fmode-voice.service';
|
|
4
|
+
import { FmodeChat } from '../../../service-fmai/service-chat';
|
|
5
|
+
import { CommonModule } from '@angular/common';
|
|
6
|
+
import { NovaUploadService } from '../../../../storage/service-upload/nova-upload.service';
|
|
7
|
+
import Parse from "parse";
|
|
8
|
+
import * as i0 from "@angular/core";
|
|
9
|
+
import * as i1 from "../../../voice/fmode-voice.service";
|
|
10
|
+
import * as i2 from "@ionic/angular/standalone";
|
|
11
|
+
import * as i3 from "../../../../storage/service-upload/nova-upload.service";
|
|
12
|
+
import * as i4 from "@angular/common";
|
|
13
|
+
export class ModalAudioMessageComponent {
|
|
14
|
+
constructor(voiceServ, toastCtrl, uploadServ) {
|
|
15
|
+
this.voiceServ = voiceServ;
|
|
16
|
+
this.toastCtrl = toastCtrl;
|
|
17
|
+
this.uploadServ = uploadServ;
|
|
18
|
+
this.isRecording = false;
|
|
19
|
+
/**
|
|
20
|
+
* 语音听写服务 ==============================================
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* 音频提示音播放
|
|
24
|
+
*/
|
|
25
|
+
this.player = new Audio();
|
|
26
|
+
/**
|
|
27
|
+
* 计时器
|
|
28
|
+
*/
|
|
29
|
+
this.clockStr = "0:00";
|
|
30
|
+
}
|
|
31
|
+
ngOnInit() {
|
|
32
|
+
// setTimeout(() => {
|
|
33
|
+
this.chat.userInput = ``;
|
|
34
|
+
this.initVoiceSevice();
|
|
35
|
+
this.voiceServ.startTalk();
|
|
36
|
+
// }, 500);
|
|
37
|
+
}
|
|
38
|
+
playMusic(action) {
|
|
39
|
+
if (!this.player) {
|
|
40
|
+
this.player = new Audio();
|
|
41
|
+
}
|
|
42
|
+
this.player.src = `/assets/avatar/voice/${action}.mp3`;
|
|
43
|
+
try {
|
|
44
|
+
this.player?.play();
|
|
45
|
+
}
|
|
46
|
+
catch (err) { }
|
|
47
|
+
}
|
|
2
48
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
49
|
+
* 初始化录音转录服务
|
|
50
|
+
* @desc
|
|
51
|
+
* 根据数字角色对话状态,设计语音转录各事件处理过程
|
|
52
|
+
* 嵌入提示音
|
|
53
|
+
* 嵌入动画
|
|
54
|
+
* 嵌入唤醒词切换逻辑
|
|
55
|
+
*/
|
|
56
|
+
initVoiceSevice() {
|
|
57
|
+
this.chat.userInput = this.voiceServ.resultText;
|
|
58
|
+
this.voiceServ.requestPermission().then(() => {
|
|
59
|
+
this.voiceServ.openWithPriviledge();
|
|
60
|
+
});
|
|
61
|
+
// 开始录音前 播放倾听动画
|
|
62
|
+
// 开始录音前 播放提示音
|
|
63
|
+
this.voiceServ.onBeforeStartTalk = () => {
|
|
64
|
+
this.chat.playAnimation("listening");
|
|
65
|
+
this.playMusic("start-talk");
|
|
66
|
+
};
|
|
67
|
+
// 开始录音后 加载计时器
|
|
68
|
+
this.voiceServ.onAfterRecordStart = () => {
|
|
69
|
+
this.isRecording = true;
|
|
70
|
+
this.timerInt = setInterval(() => {
|
|
71
|
+
this.countTimer();
|
|
72
|
+
}, 1000);
|
|
73
|
+
};
|
|
74
|
+
// 用户取消录音前 播放提示音
|
|
75
|
+
this.voiceServ.onBeforeCancelTalk = () => {
|
|
76
|
+
this.playMusic("interupt-talk");
|
|
77
|
+
this.chat.playAnimation("waiting");
|
|
78
|
+
};
|
|
79
|
+
// 用户取消录音后 麦克风实时监听唤醒词
|
|
80
|
+
this.voiceServ.onAfterCancelTalk = () => {
|
|
81
|
+
// this.startASRAwake() // 监听与麦克风冲突,需要重启
|
|
82
|
+
};
|
|
83
|
+
// 完成录音前 播放提示音
|
|
84
|
+
// 完成录音后 执行处理过程
|
|
85
|
+
this.voiceServ.onBeforeFinishTalk = () => {
|
|
86
|
+
this.chat.playAnimation("thinking");
|
|
87
|
+
this.playMusic("stop-talk");
|
|
88
|
+
};
|
|
89
|
+
this.voiceServ.onAfterFinishTalk = async () => {
|
|
90
|
+
console.log("onAfterFinishTalk1", this.voiceServ?.resultText);
|
|
91
|
+
console.log("onAfterFinishTalk2", this.voiceServ?.resultTextTemp);
|
|
92
|
+
this.chat.userInput = "" + (this.voiceServ?.resultTextTemp || this.voiceServ?.resultText);
|
|
93
|
+
if (this.chat?.userInput) {
|
|
94
|
+
await this.saveChatVoice();
|
|
95
|
+
}
|
|
96
|
+
this.sendMessage(); // 发送消息
|
|
97
|
+
// this.startASRAwake() // 监听与麦克风冲突,需要重启
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async saveChatVoice() {
|
|
101
|
+
let blob = this.voiceServ.recordWavBlob;
|
|
102
|
+
let duration = this.voiceServ.recordDuration;
|
|
103
|
+
if (blob) {
|
|
104
|
+
// 创建声音数据对象
|
|
105
|
+
let ChatVoice = Parse.Object.extend("ChatVoice");
|
|
106
|
+
this.chatVoice = new ChatVoice();
|
|
107
|
+
this.chatVoice.set("content", this.chat.userInput);
|
|
108
|
+
this.chatVoice.set("role", "user");
|
|
109
|
+
this.chatVoice.set("duration", duration);
|
|
110
|
+
let company = localStorage.getItem("company");
|
|
111
|
+
company && this.chatVoice.set("company", { __type: "Pointer", className: "Company", objectId: company });
|
|
112
|
+
Parse.User.current()?.id && this.chatVoice.set("user", Parse.User.current().toPointer());
|
|
113
|
+
// 上传音频文件并保存
|
|
114
|
+
let id = this.chatVoice?.id || this.uploadServ?.genMd5(this.chatVoice?.get("content") || this.chatVoice?.get("ssml"));
|
|
115
|
+
let now = new Date();
|
|
116
|
+
let filename = id + now.getFullYear() + (now.getMonth() + 1) + now.getDate() + now.getHours() + now.getMinutes() + now.getSeconds() + ".wav";
|
|
117
|
+
let file = new File([blob], filename, { type: 'audio/wav' });
|
|
118
|
+
let fileResult = await this.uploadServ.upload(file, (res) => {
|
|
119
|
+
console.log(res); // 上传进度,可以同步更新页面上传百分比
|
|
120
|
+
});
|
|
121
|
+
let attachPointer = { __type: "Pointer", className: "Attachment", objectId: fileResult?.id };
|
|
122
|
+
if (attachPointer?.objectId) {
|
|
123
|
+
this.chatVoice.set("voiceFile", attachPointer);
|
|
124
|
+
this.chatVoice = await this.chatVoice.save();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
async sendMessage() {
|
|
130
|
+
// 检测用户登录情况
|
|
131
|
+
// let isLoginLock = await this.authServ.checkLoginLock()
|
|
132
|
+
// if(!isLoginLock) return false
|
|
133
|
+
// 检测余额及模型付费限制
|
|
134
|
+
// let payCheck = await this.checkBalance()
|
|
135
|
+
// if(!payCheck) return false
|
|
136
|
+
// 检测用户输入内容空值
|
|
137
|
+
if (!this.chat.userInput) {
|
|
138
|
+
let toast = await this.toastCtrl.create({
|
|
139
|
+
message: `内容不能为空`,
|
|
140
|
+
position: "top",
|
|
141
|
+
icon: 'alert',
|
|
142
|
+
color: "warning-circle",
|
|
143
|
+
duration: 1000
|
|
144
|
+
});
|
|
145
|
+
toast.present();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// 正常发送消息
|
|
149
|
+
// this.chat.isTalkMode = true;
|
|
150
|
+
this.chat?.sendMessage("" + this.chat?.userInput, this.chat?.userImage, (msg) => {
|
|
151
|
+
}, {
|
|
152
|
+
onSSMLComplete: (voice) => {
|
|
153
|
+
console.log(voice);
|
|
154
|
+
}
|
|
155
|
+
}, { id: this.chatVoice?.id, duration: this.chatVoice?.get("duration") });
|
|
156
|
+
}
|
|
157
|
+
countTimer() {
|
|
158
|
+
if (!this.now)
|
|
159
|
+
this.now = new Date();
|
|
160
|
+
let diff = new Date().getTime() - this.now.getTime();
|
|
161
|
+
diff = diff / 1000;
|
|
162
|
+
if (diff / 1000 > 59) {
|
|
163
|
+
this.send();
|
|
164
|
+
}
|
|
165
|
+
// 60s 倒计时
|
|
166
|
+
if (diff < 60) {
|
|
167
|
+
this.clockStr = (60 - diff).toFixed(0) + "s";
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
this.clockStr = "0s";
|
|
171
|
+
}
|
|
172
|
+
// 无限增长计时
|
|
173
|
+
// this.clockStr = (diff/60).toFixed(0) + ":" + String((diff%60).toFixed(0)).padStart(2,"0");
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 操作区
|
|
7
177
|
*/
|
|
8
|
-
import{Component,Input}from"@angular/core";import{IonButton,IonIcon,IonSpinner,ModalController,ToastController}from"@ionic/angular/standalone";import{FmodeVoiceService}from"../../../voice/fmode-voice.service";import{FmodeChat}from"../../../service-fmai/service-chat";import{CommonModule}from"@angular/common";import{NovaUploadService}from"../../../../storage/service-upload/nova-upload.service";import Parse from"parse";import*as i0 from"@angular/core";import*as i1 from"../../../voice/fmode-voice.service";import*as i2 from"@ionic/angular/standalone";import*as i3 from"../../../../storage/service-upload/nova-upload.service";import*as i4 from"@angular/common";export class ModalAudioMessageComponent{constructor(e,i,t){this.voiceServ=e,this.toastCtrl=i,this.uploadServ=t,this.isRecording=!1,this.player=new Audio,this.clockStr="0:00"}ngOnInit(){this.chat.userInput="",this.initVoiceSevice(),this.voiceServ.startTalk()}playMusic(e){this.player||(this.player=new Audio),this.player.src=`/assets/avatar/voice/${e}.mp3`;try{this.player?.play()}catch(e){}}initVoiceSevice(){this.chat.userInput=this.voiceServ.resultText,this.voiceServ.requestPermission().then((()=>{this.voiceServ.openWithPriviledge()})),this.voiceServ.onBeforeStartTalk=()=>{this.chat.playAnimation("listening"),this.playMusic("start-talk")},this.voiceServ.onAfterRecordStart=()=>{this.isRecording=!0,this.timerInt=setInterval((()=>{this.countTimer()}),1e3)},this.voiceServ.onBeforeCancelTalk=()=>{this.playMusic("interupt-talk"),this.chat.playAnimation("waiting")},this.voiceServ.onAfterCancelTalk=()=>{},this.voiceServ.onBeforeFinishTalk=()=>{this.chat.playAnimation("thinking"),this.playMusic("stop-talk")},this.voiceServ.onAfterFinishTalk=async()=>{console.log("onAfterFinishTalk1",this.voiceServ?.resultText),console.log("onAfterFinishTalk2",this.voiceServ?.resultTextTemp),this.chat.userInput=""+(this.voiceServ?.resultTextTemp||this.voiceServ?.resultText),this.chat?.userInput&&await this.saveChatVoice(),this.sendMessage()}}async saveChatVoice(){let e=this.voiceServ.recordWavBlob,i=this.voiceServ.recordDuration;if(e){let t=Parse.Object.extend("ChatVoice");this.chatVoice=new t,this.chatVoice.set("content",this.chat.userInput),this.chatVoice.set("role","user"),this.chatVoice.set("duration",i);let n=localStorage.getItem("company");n&&this.chatVoice.set("company",{__type:"Pointer",className:"Company",objectId:n}),Parse.User.current()?.id&&this.chatVoice.set("user",Parse.User.current().toPointer());let o=this.chatVoice?.id||this.uploadServ?.genMd5(this.chatVoice?.get("content")||this.chatVoice?.get("ssml")),a=new Date,s=o+a.getFullYear()+(a.getMonth()+1)+a.getDate()+a.getHours()+a.getMinutes()+a.getSeconds()+".wav",r=new File([e],s,{type:"audio/wav"}),c=await this.uploadServ.upload(r,(e=>{console.log(e)})),l={__type:"Pointer",className:"Attachment",objectId:c?.id};l?.objectId&&(this.chatVoice.set("voiceFile",l),this.chatVoice=await this.chatVoice.save())}}async sendMessage(){if(this.chat.userInput)this.chat?.sendMessage(""+this.chat?.userInput,this.chat?.userImage,(e=>{}),{onSSMLComplete:e=>{console.log(e)}},{id:this.chatVoice?.id,duration:this.chatVoice?.get("duration")});else{(await this.toastCtrl.create({message:"内容不能为空",position:"top",icon:"alert",color:"warning-circle",duration:1e3})).present()}}countTimer(){this.now||(this.now=new Date);let e=(new Date).getTime()-this.now.getTime();e/=1e3,e/1e3>59&&this.send(),this.clockStr=(e/60).toFixed(0)+":"+String((e%60).toFixed(0)).padStart(2,"0")}cancel(){this.clear(),this.voiceServ.cancelTalk(),this.modal?.dismiss(null,"cancel")}send(){this.clear(),this.voiceServ.finishTalk(),this.modal?.dismiss(null,"send")}clear(){this.timerInt&&clearInterval(this.timerInt),this.now=void 0,this.isRecording=!1}static{this.ɵfac=i0.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalAudioMessageComponent,deps:[{token:i1.FmodeVoiceService},{token:i2.ToastController},{token:i3.NovaUploadService}],target:i0.ɵɵFactoryTarget.Component})}static{this.ɵcmp=i0.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"17.3.12",type:ModalAudioMessageComponent,isStandalone:!0,selector:"fm-modal-audio-message",inputs:{chat:"chat",modal:"modal"},providers:[ModalController],ngImport:i0,template:'\x3c!-- <div style="background:#FFFFFF;color:#000000;width:100%">\n {{this.chat.userInput}}\n</div> --\x3e\n<div class="modal-area">\n\n \x3c!-- 加载WebSockets动画 --\x3e\n <ng-container *ngIf="!isRecording">\n <div class="row">\n <ion-spinner name="crescent" color="success" style="width:80px;height:80px;"></ion-spinner>\n </div>\n </ng-container>\n \x3c!-- 录音中动画 --\x3e\n <ng-container *ngIf="isRecording">\n <div class="tips row">\n 请您讲话,AI会识别!\n </div>\n <div class="timer row">\n {{clockStr || "0:00"}}\n </div>\n <div class="audio-wave row">\n <div class="audio">\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n </div>\n </div>\n <div class="actions row">\n <ion-button (click)="cancel()" size="large" shape="round" color="light">\n <ion-icon name="close-outline"></ion-icon>\n </ion-button>\n <ion-button (click)="send()" size="large" shape="round" color="success">\n <ion-icon name="send-outline"></ion-icon>\n </ion-button>\n </div>\n </ng-container>\n</div>',styles:[":host-context(body.dark) .modal-area{color:#fff}.modal-area{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%}.modal-area .row{margin:10px}.modal-area .timer{font-size:1.5rem;font-weight:700}.modal-area .actions{display:flex;justify-content:space-around;width:100%;height:86px}.audio{display:flex;justify-content:space-between;align-items:center;gap:8px;width:60px;height:40px}.audio .wave{height:40px;display:block;width:10px;height:6px;border-radius:8px;background:orange}.audio .wave{animation:audio-wave 2s ease-in-out infinite}.audio .wave:nth-child(1){animation-delay:.1s}.audio .wave:nth-child(2){animation-delay:.2s}.audio .wave:nth-child(3){animation-delay:.3s}.audio .wave:nth-child(4){animation-delay:.4s}.audio .wave:nth-child(5){animation-delay:.5s}@keyframes audio-wave{0%{height:6px;transform:translateY(0);background:#ff8e3a}25%{height:6px;transform:translateY(0);background:#9c73f8}50%{height:30px;transform:translateY(-5px) scaleY(1.5);background:#ed509e}75%{height:6px;transform:translateY(0);background:#9c73f8}to{height:6px;transform:translateY(0);background:#0fccce}}\n"],dependencies:[{kind:"ngmodule",type:CommonModule},{kind:"directive",type:i4.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:IonButton,selector:"ion-button",inputs:["buttonType","color","disabled","download","expand","fill","form","href","mode","rel","routerAnimation","routerDirection","shape","size","strong","target","type"]},{kind:"component",type:IonIcon,selector:"ion-icon",inputs:["color","flipRtl","icon","ios","lazy","md","mode","name","sanitize","size","src"]},{kind:"component",type:IonSpinner,selector:"ion-spinner",inputs:["color","duration","name","paused"]}]})}}i0.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"17.3.12",ngImport:i0,type:ModalAudioMessageComponent,decorators:[{type:Component,args:[{selector:"fm-modal-audio-message",standalone:!0,imports:[CommonModule,IonButton,IonIcon,IonSpinner],providers:[ModalController],template:'\x3c!-- <div style="background:#FFFFFF;color:#000000;width:100%">\n {{this.chat.userInput}}\n</div> --\x3e\n<div class="modal-area">\n\n \x3c!-- 加载WebSockets动画 --\x3e\n <ng-container *ngIf="!isRecording">\n <div class="row">\n <ion-spinner name="crescent" color="success" style="width:80px;height:80px;"></ion-spinner>\n </div>\n </ng-container>\n \x3c!-- 录音中动画 --\x3e\n <ng-container *ngIf="isRecording">\n <div class="tips row">\n 请您讲话,AI会识别!\n </div>\n <div class="timer row">\n {{clockStr || "0:00"}}\n </div>\n <div class="audio-wave row">\n <div class="audio">\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n <div class="wave"></div>\n </div>\n </div>\n <div class="actions row">\n <ion-button (click)="cancel()" size="large" shape="round" color="light">\n <ion-icon name="close-outline"></ion-icon>\n </ion-button>\n <ion-button (click)="send()" size="large" shape="round" color="success">\n <ion-icon name="send-outline"></ion-icon>\n </ion-button>\n </div>\n </ng-container>\n</div>',styles:[":host-context(body.dark) .modal-area{color:#fff}.modal-area{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%}.modal-area .row{margin:10px}.modal-area .timer{font-size:1.5rem;font-weight:700}.modal-area .actions{display:flex;justify-content:space-around;width:100%;height:86px}.audio{display:flex;justify-content:space-between;align-items:center;gap:8px;width:60px;height:40px}.audio .wave{height:40px;display:block;width:10px;height:6px;border-radius:8px;background:orange}.audio .wave{animation:audio-wave 2s ease-in-out infinite}.audio .wave:nth-child(1){animation-delay:.1s}.audio .wave:nth-child(2){animation-delay:.2s}.audio .wave:nth-child(3){animation-delay:.3s}.audio .wave:nth-child(4){animation-delay:.4s}.audio .wave:nth-child(5){animation-delay:.5s}@keyframes audio-wave{0%{height:6px;transform:translateY(0);background:#ff8e3a}25%{height:6px;transform:translateY(0);background:#9c73f8}50%{height:30px;transform:translateY(-5px) scaleY(1.5);background:#ed509e}75%{height:6px;transform:translateY(0);background:#9c73f8}to{height:6px;transform:translateY(0);background:#0fccce}}\n"]}]}],ctorParameters:()=>[{type:i1.FmodeVoiceService},{type:i2.ToastController},{type:i3.NovaUploadService}],propDecorators:{chat:[{type:Input}],modal:[{type:Input}]}});
|
|
9
|
-
|
|
10
|
-
|
|
178
|
+
cancel() {
|
|
179
|
+
this.clear();
|
|
180
|
+
this.voiceServ.cancelTalk();
|
|
181
|
+
this.modal?.dismiss(null, "cancel");
|
|
182
|
+
}
|
|
183
|
+
send() {
|
|
184
|
+
this.clear();
|
|
185
|
+
this.voiceServ.finishTalk();
|
|
186
|
+
this.modal?.dismiss(null, "send");
|
|
187
|
+
}
|
|
188
|
+
clear() {
|
|
189
|
+
this.timerInt && clearInterval(this.timerInt);
|
|
190
|
+
this.now = undefined;
|
|
191
|
+
this.isRecording = false;
|
|
192
|
+
}
|
|
193
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ModalAudioMessageComponent, deps: [{ token: i1.FmodeVoiceService }, { token: i2.ToastController }, { token: i3.NovaUploadService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
194
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ModalAudioMessageComponent, isStandalone: true, selector: "fm-modal-audio-message", inputs: { chat: "chat", modal: "modal" }, providers: [ModalController], ngImport: i0, template: "<!-- <div style=\"background:#FFFFFF;color:#000000;width:100%\">\n {{this.chat.userInput}}\n</div> -->\n<div class=\"modal-area\">\n\n <!-- \u52A0\u8F7DWebSockets\u52A8\u753B -->\n <ng-container *ngIf=\"!isRecording\">\n <div class=\"row\">\n <ion-spinner name=\"crescent\" color=\"success\" style=\"width:80px;height:80px;\"></ion-spinner>\n </div>\n </ng-container>\n <!-- \u5F55\u97F3\u4E2D\u52A8\u753B -->\n <ng-container *ngIf=\"isRecording\">\n <div class=\"tips row\">\n \u8BF7\u60A8\u8BB2\u8BDD\uFF0CAI\u4F1A\u8BC6\u522B\uFF01\n </div>\n <div class=\"timer row\">\n {{clockStr || \"0:00\"}}\n </div>\n <div class=\"audio-wave row\">\n <div class=\"audio\">\n <div class=\"wave\"></div>\n <div class=\"wave\"></div>\n <div class=\"wave\"></div>\n <div class=\"wave\"></div>\n <div class=\"wave\"></div>\n </div>\n </div>\n <div class=\"actions row\">\n <ion-button (click)=\"cancel()\" size=\"large\" shape=\"round\" color=\"light\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"send()\" size=\"large\" shape=\"round\" color=\"success\">\n <ion-icon name=\"send-outline\"></ion-icon>\n </ion-button>\n </div>\n </ng-container>\n</div>", styles: [":host-context(body.dark) .modal-area{color:#fff}.modal-area{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%}.modal-area .row{margin:10px}.modal-area .timer{font-size:1.5rem;font-weight:700}.modal-area .actions{display:flex;justify-content:space-around;width:100%;height:86px}.audio{display:flex;justify-content:space-between;align-items:center;gap:8px;width:60px;height:40px}.audio .wave{height:40px;display:block;width:10px;height:6px;border-radius:8px;background:orange}.audio .wave{animation:audio-wave 2s ease-in-out infinite}.audio .wave:nth-child(1){animation-delay:.1s}.audio .wave:nth-child(2){animation-delay:.2s}.audio .wave:nth-child(3){animation-delay:.3s}.audio .wave:nth-child(4){animation-delay:.4s}.audio .wave:nth-child(5){animation-delay:.5s}@keyframes audio-wave{0%{height:6px;transform:translateY(0);background:#ff8e3a}25%{height:6px;transform:translateY(0);background:#9c73f8}50%{height:30px;transform:translateY(-5px) scaleY(1.5);background:#ed509e}75%{height:6px;transform:translateY(0);background:#9c73f8}to{height:6px;transform:translateY(0);background:#0fccce}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }] }); }
|
|
195
|
+
}
|
|
196
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ModalAudioMessageComponent, decorators: [{
|
|
197
|
+
type: Component,
|
|
198
|
+
args: [{ selector: 'fm-modal-audio-message', standalone: true, imports: [
|
|
199
|
+
CommonModule,
|
|
200
|
+
IonButton,
|
|
201
|
+
IonIcon,
|
|
202
|
+
IonSpinner
|
|
203
|
+
], providers: [ModalController], template: "<!-- <div style=\"background:#FFFFFF;color:#000000;width:100%\">\n {{this.chat.userInput}}\n</div> -->\n<div class=\"modal-area\">\n\n <!-- \u52A0\u8F7DWebSockets\u52A8\u753B -->\n <ng-container *ngIf=\"!isRecording\">\n <div class=\"row\">\n <ion-spinner name=\"crescent\" color=\"success\" style=\"width:80px;height:80px;\"></ion-spinner>\n </div>\n </ng-container>\n <!-- \u5F55\u97F3\u4E2D\u52A8\u753B -->\n <ng-container *ngIf=\"isRecording\">\n <div class=\"tips row\">\n \u8BF7\u60A8\u8BB2\u8BDD\uFF0CAI\u4F1A\u8BC6\u522B\uFF01\n </div>\n <div class=\"timer row\">\n {{clockStr || \"0:00\"}}\n </div>\n <div class=\"audio-wave row\">\n <div class=\"audio\">\n <div class=\"wave\"></div>\n <div class=\"wave\"></div>\n <div class=\"wave\"></div>\n <div class=\"wave\"></div>\n <div class=\"wave\"></div>\n </div>\n </div>\n <div class=\"actions row\">\n <ion-button (click)=\"cancel()\" size=\"large\" shape=\"round\" color=\"light\">\n <ion-icon name=\"close-outline\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"send()\" size=\"large\" shape=\"round\" color=\"success\">\n <ion-icon name=\"send-outline\"></ion-icon>\n </ion-button>\n </div>\n </ng-container>\n</div>", styles: [":host-context(body.dark) .modal-area{color:#fff}.modal-area{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%;height:100%}.modal-area .row{margin:10px}.modal-area .timer{font-size:1.5rem;font-weight:700}.modal-area .actions{display:flex;justify-content:space-around;width:100%;height:86px}.audio{display:flex;justify-content:space-between;align-items:center;gap:8px;width:60px;height:40px}.audio .wave{height:40px;display:block;width:10px;height:6px;border-radius:8px;background:orange}.audio .wave{animation:audio-wave 2s ease-in-out infinite}.audio .wave:nth-child(1){animation-delay:.1s}.audio .wave:nth-child(2){animation-delay:.2s}.audio .wave:nth-child(3){animation-delay:.3s}.audio .wave:nth-child(4){animation-delay:.4s}.audio .wave:nth-child(5){animation-delay:.5s}@keyframes audio-wave{0%{height:6px;transform:translateY(0);background:#ff8e3a}25%{height:6px;transform:translateY(0);background:#9c73f8}50%{height:30px;transform:translateY(-5px) scaleY(1.5);background:#ed509e}75%{height:6px;transform:translateY(0);background:#9c73f8}to{height:6px;transform:translateY(0);background:#0fccce}}\n"] }]
|
|
204
|
+
}], ctorParameters: () => [{ type: i1.FmodeVoiceService }, { type: i2.ToastController }, { type: i3.NovaUploadService }], propDecorators: { chat: [{
|
|
205
|
+
type: Input
|
|
206
|
+
}], modal: [{
|
|
207
|
+
type: Input
|
|
208
|
+
}] } });
|
|
209
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwtYXVkaW8tbWVzc2FnZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9mbW9kZS1uZy9zcmMvbGliL2FpZ2MvY2hhdC9jaGF0LW1vZGFsLWlucHV0L21vZGFsLWF1ZGlvLW1lc3NhZ2UvbW9kYWwtYXVkaW8tbWVzc2FnZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9mbW9kZS1uZy9zcmMvbGliL2FpZ2MvY2hhdC9jaGF0LW1vZGFsLWlucHV0L21vZGFsLWF1ZGlvLW1lc3NhZ2UvbW9kYWwtYXVkaW8tbWVzc2FnZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFDLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdHLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxTQUFTLEVBQW1CLE1BQU0sb0NBQW9DLENBQUM7QUFDaEYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHdEQUF3RCxDQUFDO0FBQzNGLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQzs7Ozs7O0FBZTFCLE1BQU0sT0FBTywwQkFBMEI7SUFPckMsWUFDUyxTQUEyQixFQUMxQixTQUF5QixFQUN6QixVQUE0QjtRQUY3QixjQUFTLEdBQVQsU0FBUyxDQUFrQjtRQUMxQixjQUFTLEdBQVQsU0FBUyxDQUFnQjtRQUN6QixlQUFVLEdBQVYsVUFBVSxDQUFrQjtRQUp0QyxnQkFBVyxHQUFXLEtBQUssQ0FBQztRQWdCNUI7O1dB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QUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUMsTUFBTSxDQUFDLENBQUE7SUFDbEMsQ0FBQztJQUNELEtBQUs7UUFDSCxJQUFJLENBQUMsUUFBUSxJQUFFLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxTQUFTLENBQUM7UUFDckIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7SUFDM0IsQ0FBQzsrR0E3TVUsMEJBQTBCO21HQUExQiwwQkFBMEIsK0dBSjNCLENBQUMsZUFBZSxDQUFDLDBCQ2pCN0IsbytDQXFDTSw4cUNEekJGLFlBQVksbUlBQ1osU0FBUyxvUEFDVCxPQUFPLDJKQUNQLFVBQVU7OzRGQU1ELDBCQUEwQjtrQkFidEMsU0FBUzsrQkFDRSx3QkFBd0IsY0FDdEIsSUFBSSxXQUNQO3dCQUNQLFlBQVk7d0JBQ1osU0FBUzt3QkFDVCxPQUFPO3dCQUNQLFVBQVU7cUJBQ1gsYUFDUyxDQUFDLGVBQWUsQ0FBQztvSkFNbEIsSUFBSTtzQkFBWixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCxJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSW9uQnV0dG9uLCBJb25JY29uLCBJb25TcGlubmVyLCBNb2RhbENvbnRyb2xsZXIsIFRvYXN0Q29udHJvbGxlciB9IGZyb20gJ0Bpb25pYy9hbmd1bGFyL3N0YW5kYWxvbmUnO1xuaW1wb3J0IHsgRm1vZGVWb2ljZVNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi92b2ljZS9mbW9kZS12b2ljZS5zZXJ2aWNlJztcbmltcG9ydCB7IEZtb2RlQ2hhdCxGbW9kZUNoYXRNZXNzYWdlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZS1mbWFpL3NlcnZpY2UtY2hhdCc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgTm92YVVwbG9hZFNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi8uLi9zdG9yYWdlL3NlcnZpY2UtdXBsb2FkL25vdmEtdXBsb2FkLnNlcnZpY2UnO1xuaW1wb3J0IFBhcnNlIGZyb20gXCJwYXJzZVwiO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdmbS1tb2RhbC1hdWRpby1tZXNzYWdlJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBJb25CdXR0b24sXG4gICAgSW9uSWNvbixcbiAgICBJb25TcGlubmVyXG4gIF0sXG4gIHByb3ZpZGVyczpbTW9kYWxDb250cm9sbGVyXSxcbiAgdGVtcGxhdGVVcmw6ICcuL21vZGFsLWF1ZGlvLW1lc3NhZ2UuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vbW9kYWwtYXVkaW8tbWVzc2FnZS5jb21wb25lbnQuc2Nzcydcbn0pXG5leHBvcnQgY2xhc3MgTW9kYWxBdWRpb01lc3NhZ2VDb21wb25lbnQge1xuXG4gIEBJbnB1dCgpIGNoYXQ6Rm1vZGVDaGF0O1xuICBASW5wdXQoKSBtb2RhbDpNb2RhbENvbnRyb2xsZXJcbiAgbm93OkRhdGV8dW5kZWZpbmVkO1xuXG4gIGlzUmVjb3JkaW5nOmJvb2xlYW4gPSBmYWxzZTtcbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIHZvaWNlU2VydjpGbW9kZVZvaWNlU2VydmljZSxcbiAgICBwcml2YXRlIHRvYXN0Q3RybDpUb2FzdENvbnRyb2xsZXIsXG4gICAgcHJpdmF0ZSB1cGxvYWRTZXJ2Ok5vdmFVcGxvYWRTZXJ2aWNlXG4gICl7XG4gICAgXG4gIH1cbiAgbmdPbkluaXQoKXtcbiAgICAvLyBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICB0aGlzLmNoYXQudXNlcklucHV0ID0gYGBcbiAgICB0aGlzLmluaXRWb2ljZVNldmljZSgpXG4gICAgdGhpcy52b2ljZVNlcnYuc3RhcnRUYWxrKCk7XG4gICAgLy8gfSwgNTAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDor63pn7PlkKzlhpnmnI3liqEgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgKi9cbiAgXG4gIC8qKlxuICAgKiDpn7PpopHmj5DnpLrpn7Pmkq3mlL5cbiAgICovXG4gICBwbGF5ZXIgPSBuZXcgQXVkaW8oKTtcblxuICAgcGxheU11c2ljKGFjdGlvbil7XG4gICAgaWYoIXRoaXMucGxheWVyKXtcbiAgICAgIHRoaXMucGxheWVyID0gbmV3IEF1ZGlvKCk7XG4gICAgfVxuICAgICB0aGlzLnBsYXllci5zcmMgPSBgL2Fzc2V0cy9hdmF0YXIvdm9pY2UvJHthY3Rpb259Lm1wM2BcbiAgICAgdHJ5e1xuICAgICAgIHRoaXMucGxheWVyPy5wbGF5KCk7XG4gICAgfWNhdGNoKGVycil7fVxuICAgfVxuXG5cbiAgIC8qKlxuICAgICAqIOWIneWni+WMluW9lemfs+i9rOW9leacjeWKoVxuICAgICAqIEBkZXNjXG4gICAgICog5qC55o2u5pWw5a2X6KeS6Imy5a+56K+d54q25oCB77yM6K6+6K6h6K+t6Z+z6L2s5b2V5ZCE5LqL5Lu25aSE55CG6L+H56iLXG4gICAgICog5bWM5YWl5o+Q56S66Z+zXG4gICAgICog5bWM5YWl5Yqo55S7XG4gICAgICog5bWM5YWl5ZSk6YaS6K+N5YiH5o2i6YC76L6RXG4gICAgICovXG4gICAgaW5pdFZvaWNlU2V2aWNlKCl7XG4gICAgICB0aGlzLmNoYXQudXNlcklucHV0ID0gdGhpcy52b2ljZVNlcnYucmVzdWx0VGV4dFxuICAgICAgdGhpcy52b2ljZVNlcnYucmVxdWVzdFBlcm1pc3Npb24oKS50aGVuKCgpPT57XG4gICAgICAgIHRoaXMudm9pY2VTZXJ2Lm9wZW5XaXRoUHJpdmlsZWRnZSgpXG4gICAgICB9KVxuXG4gICAgICAvLyDlvIDlp4vlvZXpn7PliY0g5pKt5pS+5YC+5ZCs5Yqo55S7XG4gICAgICAvLyDlvIDlp4vlvZXpn7PliY0g5pKt5pS+5o+Q56S66Z+zXG4gICAgICB0aGlzLnZvaWNlU2Vydi5vbkJlZm9yZVN0YXJ0VGFsayA9ICgpPT57XG4gICAgICAgIHRoaXMuY2hhdC5wbGF5QW5pbWF0aW9uKFwibGlzdGVuaW5nXCIpXG4gICAgICAgIHRoaXMucGxheU11c2ljKFwic3RhcnQtdGFsa1wiKVxuICAgICAgfVxuXG4gICAgICAvLyDlvIDlp4vlvZXpn7PlkI4g5Yqg6L296K6h5pe25ZmoXG4gICAgICB0aGlzLnZvaWNlU2Vydi5vbkFmdGVyUmVjb3JkU3RhcnQgPSAoKT0+e1xuICAgICAgICB0aGlzLmlzUmVjb3JkaW5nID0gdHJ1ZVxuICAgICAgICB0aGlzLnRpbWVySW50ID0gc2V0SW50ZXJ2YWwoKCk9PntcbiAgICAgICAgICB0aGlzLmNvdW50VGltZXIoKTtcbiAgICAgICAgfSwxMDAwKVxuICAgICAgfVxuICAgICAgLy8g55So5oi35Y+W5raI5b2V6Z+z5YmNIOaSreaUvuaPkOekuumfs1xuICAgICAgdGhpcy52b2ljZVNlcnYub25CZWZvcmVDYW5jZWxUYWxrID0gKCk9PntcbiAgICAgICAgdGhpcy5wbGF5TXVzaWMoXCJpbnRlcnVwdC10YWxrXCIpXG4gICAgICAgIHRoaXMuY2hhdC5wbGF5QW5pbWF0aW9uKFwid2FpdGluZ1wiKVxuICAgICAgfVxuICAgICAgLy8g55So5oi35Y+W5raI5b2V6Z+z5ZCOIOm6puWFi+mjjuWunuaXtuebkeWQrOWUpOmGkuivjVxuICAgICAgdGhpcy52b2ljZVNlcnYub25BZnRlckNhbmNlbFRhbGsgPSAoKT0+e1xuICAgICAgICAvLyB0aGlzLnN0YXJ0QVNSQXdha2UoKSAvLyDnm5HlkKzkuI7puqblhYvpo47lhrLnqoHvvIzpnIDopoHph43lkK9cbiAgICAgIH1cbiAgICAgIC8vIOWujOaIkOW9lemfs+WJjSDmkq3mlL7mj5DnpLrpn7NcbiAgICAgIC8vIOWujOaIkOW9lemfs+WQjiDmiafooYzlpITnkIbov4fnqItcbiAgICAgIHRoaXMudm9pY2VTZXJ2Lm9uQmVmb3JlRmluaXNoVGFsayA9ICgpPT57XG4gICAgICAgIHRoaXMuY2hhdC5wbGF5QW5pbWF0aW9uKFwidGhpbmtpbmdcIilcbiAgICAgICAgdGhpcy5wbGF5TXVzaWMoXCJzdG9wLXRhbGtcIilcbiAgICAgIH1cbiAgICAgIHRoaXMudm9pY2VTZXJ2Lm9uQWZ0ZXJGaW5pc2hUYWxrID0gYXN5bmMgKCk9PntcbiAgICAgICAgY29uc29sZS5sb2coXCJvbkFmdGVyRmluaXNoVGFsazFcIix0aGlzLnZvaWNlU2Vydj8ucmVzdWx0VGV4dClcbiAgICAgICAgY29uc29sZS5sb2coXCJvbkFmdGVyRmluaXNoVGFsazJcIix0aGlzLnZvaWNlU2Vydj8ucmVzdWx0VGV4dFRlbXApXG4gICAgICAgIHRoaXMuY2hhdC51c2VySW5wdXQgPSBcIlwiKyh0aGlzLnZvaWNlU2Vydj8ucmVzdWx0VGV4dFRlbXB8fHRoaXMudm9pY2VTZXJ2Py5yZXN1bHRUZXh0KVxuICAgICAgICBcbiAgICAgICAgaWYodGhpcy5jaGF0Py51c2VySW5wdXQpe1xuICAgICAgICAgIGF3YWl0IHRoaXMuc2F2ZUNoYXRWb2ljZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZW5kTWVzc2FnZSgpIC8vIOWPkemAgea2iOaBr1xuICAgICAgICAvLyB0aGlzLnN0YXJ0QVNSQXdha2UoKSAvLyDnm5HlkKzkuI7puqblhYvpo47lhrLnqoHvvIzpnIDopoHph43lkK9cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjaGF0Vm9pY2U6UGFyc2UuT2JqZWN0XG4gICAgYXN5bmMgc2F2ZUNoYXRWb2ljZSgpe1xuICAgICAgbGV0IGJsb2IgPSB0aGlzLnZvaWNlU2Vydi5yZWNvcmRXYXZCbG9iXG4gICAgICBsZXQgZHVyYXRpb24gPSB0aGlzLnZvaWNlU2Vydi5yZWNvcmREdXJhdGlvblxuICAgICAgaWYoYmxvYil7XG4gICAgICAgIC8vIOWIm+W7uuWjsOmfs+aVsOaNruWvueixoVxuICAgICAgICBsZXQgQ2hhdFZvaWNlID0gUGFyc2UuT2JqZWN0LmV4dGVuZChcIkNoYXRWb2ljZVwiKTtcbiAgICAgICAgdGhpcy5jaGF0Vm9pY2UgPSBuZXcgQ2hhdFZvaWNlKCk7XG4gICAgICAgIHRoaXMuY2hhdFZvaWNlLnNldChcImNvbnRlbnRcIix0aGlzLmNoYXQudXNlcklucHV0KTtcbiAgICAgICAgdGhpcy5jaGF0Vm9pY2Uuc2V0KFwicm9sZVwiLFwidXNlclwiKTtcbiAgICAgICAgdGhpcy5jaGF0Vm9pY2Uuc2V0KFwiZHVyYXRpb25cIixkdXJhdGlvbik7XG4gICAgICAgIGxldCBjb21wYW55ID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJjb21wYW55XCIpXG4gICAgICAgIGNvbXBhbnkmJnRoaXMuY2hhdFZvaWNlLnNldChcImNvbXBhbnlcIix7X190eXBlOlwiUG9pbnRlclwiLGNsYXNzTmFtZTpcIkNvbXBhbnlcIixvYmplY3RJZDpjb21wYW55fSk7XG4gICAgICAgIFBhcnNlLlVzZXIuY3VycmVudCgpPy5pZCYmdGhpcy5jaGF0Vm9pY2Uuc2V0KFwidXNlclwiLFBhcnNlLlVzZXIuY3VycmVudCgpLnRvUG9pbnRlcigpKTtcblxuICAgICAgICAvLyDkuIrkvKDpn7PpopHmlofku7blubbkv53lrZhcbiAgICAgICAgbGV0IGlkID0gdGhpcy5jaGF0Vm9pY2U/LmlkIHx8IHRoaXMudXBsb2FkU2Vydj8uZ2VuTWQ1KHRoaXMuY2hhdFZvaWNlPy5nZXQoXCJjb250ZW50XCIpfHx0aGlzLmNoYXRWb2ljZT8uZ2V0KFwic3NtbFwiKSlcbiAgICAgICAgbGV0IG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgICAgIGxldCBmaWxlbmFtZSA9IGlkICsgbm93LmdldEZ1bGxZZWFyKCkrKG5vdy5nZXRNb250aCgpKzEpK25vdy5nZXREYXRlKCkrbm93LmdldEhvdXJzKCkrbm93LmdldE1pbnV0ZXMoKStub3cuZ2V0U2Vjb25kcygpICsgXCIud2F2XCJcbiAgICAgICAgbGV0IGZpbGUgPSBuZXcgRmlsZShbYmxvYl0sIGZpbGVuYW1lLCB7IHR5cGU6ICdhdWRpby93YXYnIH0pO1xuICAgICAgICBsZXQgZmlsZVJlc3VsdCA9IGF3YWl0IHRoaXMudXBsb2FkU2Vydi51cGxvYWQoZmlsZSwocmVzKT0+e1xuICAgICAgICAgICAgY29uc29sZS5sb2cocmVzKSAvLyDkuIrkvKDov5vluqbvvIzlj6/ku6XlkIzmraXmm7TmlrDpobXpnaLkuIrkvKDnmb7liIbmr5RcbiAgICAgICAgfSk7XG4gICAgICAgIGxldCBhdHRhY2hQb2ludGVyID0ge19fdHlwZTpcIlBvaW50ZXJcIixjbGFzc05hbWU6XCJBdHRhY2htZW50XCIsb2JqZWN0SWQ6ZmlsZVJlc3VsdD8uaWR9XG4gICAgICAgIGlmKGF0dGFjaFBvaW50ZXI/Lm9iamVjdElkKXtcbiAgICAgICAgICAgIHRoaXMuY2hhdFZvaWNlLnNldChcInZvaWNlRmlsZVwiLGF0dGFjaFBvaW50ZXIpXG4gICAgICAgICAgICB0aGlzLmNoYXRWb2ljZSA9IGF3YWl0IHRoaXMuY2hhdFZvaWNlLnNhdmUoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgYXN5bmMgc2VuZE1lc3NhZ2UoKXtcblxuICAgICAgLy8g5qOA5rWL55So5oi355m75b2V5oOF5Ya1XG4gICAgICAvLyBsZXQgaXNMb2dpbkxvY2sgPSBhd2FpdCB0aGlzLmF1dGhTZXJ2LmNoZWNrTG9naW5Mb2NrKClcbiAgICAgIC8vIGlmKCFpc0xvZ2luTG9jaykgcmV0dXJuIGZhbHNlXG4gIFxuICAgICAgLy8g5qOA5rWL5L2Z6aKd5Y+K5qih5Z6L5LuY6LS56ZmQ5Yi2XG4gICAgICAvLyBsZXQgcGF5Q2hlY2sgPSBhd2FpdCB0aGlzLmNoZWNrQmFsYW5jZSgpXG4gICAgICAvLyBpZighcGF5Q2hlY2spIHJldHVybiBmYWxzZVxuICBcbiAgICAgIC8vIOajgOa1i+eUqOaIt+i+k+WFpeWGheWuueepuuWAvFxuICAgICAgaWYoIXRoaXMuY2hhdC51c2VySW5wdXQpe1xuICAgICAgICBsZXQgdG9hc3QgPSBhd2FpdCB0aGlzLnRvYXN0Q3RybC5jcmVhdGUoe1xuICAgICAgICAgIG1lc3NhZ2U6YOWGheWuueS4jeiDveS4uuepumAsXG4gICAgICAgICAgcG9zaXRpb246XCJ0b3BcIixcbiAgICAgICAgICBpY29uOidhbGVydCcsXG4gICAgICAgICAgY29sb3I6XCJ3YXJuaW5nLWNpcmNsZVwiLFxuICAgICAgICAgIGR1cmF0aW9uOjEwMDBcbiAgICAgICAgfSlcbiAgICAgICAgdG9hc3QucHJlc2VudCgpO1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgXG4gICAgICAvLyDmraPluLjlj5HpgIHmtojmga9cbiAgICAgIC8vIHRoaXMuY2hhdC5pc1RhbGtNb2RlID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2hhdD8uc2VuZE1lc3NhZ2UoXCJcIit0aGlzLmNoYXQ/LnVzZXJJbnB1dCx0aGlzLmNoYXQ/LnVzZXJJbWFnZSwobXNnOmFueSk9PntcbiAgICAgICAgXG4gICAgICB9LHtcbiAgICAgICAgb25TU01MQ29tcGxldGU6KHZvaWNlOmFueSk9PntcbiAgICAgICAgICBjb25zb2xlLmxvZyh2b2ljZSlcbiAgICAgICAgfVxuICAgICAgfSx7aWQ6dGhpcy5jaGF0Vm9pY2U/LmlkLGR1cmF0aW9uOnRoaXMuY2hhdFZvaWNlPy5nZXQoXCJkdXJhdGlvblwiKX0pO1xuICAgIH1cblxuICAvKipcbiAgICog6K6h5pe25ZmoXG4gICAqL1xuICBjbG9ja1N0cjpzdHJpbmcgPSBcIjA6MDBcIlxuICB0aW1lckludDphbnlcbiAgY291bnRUaW1lcigpe1xuICAgIGlmKCF0aGlzLm5vdykgdGhpcy5ub3cgPSBuZXcgRGF0ZSgpXG4gICAgbGV0IGRpZmYgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKSAtIHRoaXMubm93LmdldFRpbWUoKTtcbiAgICBkaWZmID0gZGlmZiAvIDEwMDBcbiAgICBpZihkaWZmLzEwMDAgPiA1OSl7XG4gICAgICB0aGlzLnNlbmQoKTtcbiAgICB9XG4gICAgLy8gNjBzIOWAkuiuoeaXtlxuICAgIGlmKGRpZmY8NjApe1xuICAgICAgdGhpcy5jbG9ja1N0ciA9ICg2MC1kaWZmKS50b0ZpeGVkKDApICsgXCJzXCI7XG4gICAgfWVsc2V7XG4gICAgICB0aGlzLmNsb2NrU3RyID0gXCIwc1wiXG4gICAgfVxuICAgIC8vIOaXoOmZkOWinumVv+iuoeaXtlxuICAgIC8vIHRoaXMuY2xvY2tTdHIgPSAoZGlmZi82MCkudG9GaXhlZCgwKSArIFwiOlwiICsgU3RyaW5nKChkaWZmJTYwKS50b0ZpeGVkKDApKS5wYWRTdGFydCgyLFwiMFwiKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIOaTjeS9nOWMulxuICAgKi9cbiAgY2FuY2VsKCl7XG4gICAgdGhpcy5jbGVhcigpO1xuICAgIHRoaXMudm9pY2VTZXJ2LmNhbmNlbFRhbGsoKTtcbiAgICB0aGlzLm1vZGFsPy5kaXNtaXNzKG51bGwsXCJjYW5jZWxcIilcbiAgfVxuICBzZW5kKCl7XG4gICAgdGhpcy5jbGVhcigpO1xuICAgIHRoaXMudm9pY2VTZXJ2LmZpbmlzaFRhbGsoKTtcbiAgICB0aGlzLm1vZGFsPy5kaXNtaXNzKG51bGwsXCJzZW5kXCIpXG4gIH1cbiAgY2xlYXIoKXtcbiAgICB0aGlzLnRpbWVySW50JiZjbGVhckludGVydmFsKHRoaXMudGltZXJJbnQpO1xuICAgIHRoaXMubm93ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuaXNSZWNvcmRpbmcgPSBmYWxzZTtcbiAgfVxufVxuIiwiPCEtLSA8ZGl2IHN0eWxlPVwiYmFja2dyb3VuZDojRkZGRkZGO2NvbG9yOiMwMDAwMDA7d2lkdGg6MTAwJVwiPlxuICAgIHt7dGhpcy5jaGF0LnVzZXJJbnB1dH19XG48L2Rpdj4gLS0+XG48ZGl2IGNsYXNzPVwibW9kYWwtYXJlYVwiPlxuXG4gICAgPCEtLSDliqDovb1XZWJTb2NrZXRz5Yqo55S7IC0tPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNSZWNvcmRpbmdcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInJvd1wiPlxuICAgICAgICAgICAgPGlvbi1zcGlubmVyIG5hbWU9XCJjcmVzY2VudFwiIGNvbG9yPVwic3VjY2Vzc1wiIHN0eWxlPVwid2lkdGg6ODBweDtoZWlnaHQ6ODBweDtcIj48L2lvbi1zcGlubmVyPlxuICAgICAgICA8L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8IS0tIOW9lemfs+S4reWKqOeUuyAtLT5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaXNSZWNvcmRpbmdcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aXBzIHJvd1wiPlxuICAgICAgICAgICAgICAgIOivt+aCqOiusuivne+8jEFJ5Lya6K+G5Yir77yBXG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aW1lciByb3dcIj5cbiAgICAgICAgICAgICAgICB7e2Nsb2NrU3RyIHx8IFwiMDowMFwifX1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImF1ZGlvLXdhdmUgcm93XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYXVkaW9cIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwid2F2ZVwiPjwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3YXZlXCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIndhdmVcIj48L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwid2F2ZVwiPjwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3YXZlXCI+PC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpb25zIHJvd1wiPlxuICAgICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cImNhbmNlbCgpXCIgc2l6ZT1cImxhcmdlXCIgc2hhcGU9XCJyb3VuZFwiIGNvbG9yPVwibGlnaHRcIj5cbiAgICAgICAgICAgICAgICA8aW9uLWljb24gbmFtZT1cImNsb3NlLW91dGxpbmVcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cInNlbmQoKVwiIHNpemU9XCJsYXJnZVwiIHNoYXBlPVwicm91bmRcIiBjb2xvcj1cInN1Y2Nlc3NcIj5cbiAgICAgICAgICAgICAgICA8aW9uLWljb24gbmFtZT1cInNlbmQtb3V0bGluZVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuPC9kaXY+Il19
|