Skip to content

Commit

Permalink
ref #737 update UI, loading, speech reco for AI Chat
Browse files Browse the repository at this point in the history
DONE:
 - add user input in chat + fake server pending response on submit
 - add vocal input (like form create)

TODO:
 - check user right for the Chat api (owner or collaborator)
 - prevents to use actions
  • Loading branch information
nicolas-albert committed Nov 4, 2024
1 parent 968ecf7 commit 41ea396
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 97 deletions.
2 changes: 1 addition & 1 deletion _c8oProject/mobileApplication.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2281,7 +2281,7 @@ useClickForTap: true
.aichat {
justify-content: end;
align-items: end;
--width: 400px;
--width: 500px;
}
fieldset{
Expand Down
224 changes: 177 additions & 47 deletions _c8oProject/mobilePages/aiChat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ scriptContent:
/*Begin_c8o_PageDeclaration*/
/*End_c8o_PageDeclaration*/
/*Begin_c8o_PageConstructor*/
try {
const Speech = window["SpeechRecognition"] || window["webkitSpeechRecognition"];
this.local.speechReco = new Speech();
this.local.speechReco.continuous = true;
this.local.speechReco.interimResults = true;
this.local.speechReco.onresult = (evt) => {
this.local.inputModel = [...evt.results].map((r) => r[0]?.transcript.trim()).join(' ');
this.ref.detectChanges();
};
} catch(e){
}
/*End_c8o_PageConstructor*/
/*Begin_c8o_PageFunction*/
/*End_c8o_PageFunction*/
Expand Down Expand Up @@ -121,7 +133,16 @@ title: Title for aiChat
textValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: source:{"filter":"Iteration","project":"C8Oforms","input":"","model":{"data":[{"priority":1730196159139}],"path":"","prefix":"","suffix":"?.content","custom":"","useCustom":false}}
- MobileSmartSourceType: source:{"filter":"Iteration","project":"C8Oforms","input":"","model":{"data":[{"priority":1730196159139}],"path":"","prefix":"","suffix":"?.content ?? ''","custom":"","useCustom":false}}
↓Directive [ngx.components.UIControlDirective-1730731945805]:
directiveName: If
directiveSource:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: source:{"filter":"Iteration","project":"C8Oforms","input":"","model":{"data":[{"priority":1730196159139}],"path":"","prefix":"","suffix":"?.waiting == true","custom":"","useCustom":false}}
↓SkeletonText [ngx.components.UIDynamicElement-1730732038567]:
beanData: '{"ionBean":"SkeletonText","Animated":"plain:true"}'
tagName: ion-skeleton-text
↓Directive1 [ngx.components.UIControlDirective-1730196159184]:
directiveName: If
directiveSource:
Expand Down Expand Up @@ -157,7 +178,7 @@ title: Title for aiChat
textValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: source:{"filter":"Iteration","project":"C8Oforms","input":"","model":{"data":[{"priority":1730196159139}],"path":"","prefix":"","suffix":"?.content","custom":"","useCustom":false}}
- MobileSmartSourceType: source:{"filter":"Iteration","project":"C8Oforms","input":"","model":{"data":[{"priority":1730196159139}],"path":"","prefix":"","suffix":"?.content ?? ''","custom":"","useCustom":false}}
↓Footer [ngx.components.UIDynamicElement-1730128363989]:
beanData: '{"ionBean":"Footer"}'
tagName: ion-footer
Expand All @@ -175,6 +196,63 @@ title: Title for aiChat
"Required": "plain:true"
}'
tagName: ion-input
↓attr [ngx.components.UIAttribute-1730737006280]:
attrName: '[(ngModel)]'
attrValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: script:this.local.inputModel
↓Mic [ngx.components.UIDynamicElement-1730735186273]:
beanData: '{"ionBean":"Button","IonFill":"plain:clear"}'
tagName: ion-button
↓attr [ngx.components.UIControlEvent-1730735186276]:
↓activateSpeech [ngx.components.UICustomAsyncAction-1730735186279]:
actionValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.common.FormatedContent
- com.twinsoft.convertigo.beans.common.FormatedContent:
: |
try {
if (!this.local.isRecording) {
this.local.speechReco.start();
} else {
this.local.speechReco.stop();
}
this.local.isRecording = !this.local.isRecording;
} catch (e) {
} finally {
return;
}
page_ts_imports:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.common.XMLVector
- com.twinsoft.convertigo.beans.common.XMLVector:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.common.XMLVector
- com.twinsoft.convertigo.beans.common.XMLVector:
- java.lang.String:
- ↑value: LoadingController
- java.lang.String:
- ↑value: '@ionic/angular'
↓Icon [ngx.components.UIDynamicElement-1730735186285]:
beanData: |
'{
"ionBean": "Icon",
"IonColor": "script:this.local.isRecording ? ''danger'' : ''primary''",
"IconName": "source:{\"filter\":\"Icon\",\"project\":\"C8Oforms\",\"input\":\"\",\"model\":{\"data\":[{\"icon\":\"''mic-outline''\"}],\"path\":\"\",\"prefix\":\"\",\"suffix\":\"\",\"custom\":\"\",\"useCustom\":false}}",
"IconIosName": "plain:",
"IonSize": "plain:large"
}'
tagName: ion-icon
↓attr1 [ngx.components.UIAttribute-1730736011639]:
attrName: '*ngIf'
attrValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: plain:this.local.speechReco != undefined
↓SubmitButton [ngx.components.UIDynamicElement-1730195566682]:
beanData: '{"ionBean":"SubmitButton","IonFill":"plain:clear"}'
tagName: ion-button
Expand All @@ -199,45 +277,17 @@ title: Title for aiChat
}'
↓callChat [ngx.components.UIEventSubscriber-1730200487383]:
topic: callChat
↓CallSequence [ngx.components.UIDynamicAction-1730198395692]:
beanData: '{"ionBean":"CallSequenceAction","requestable":"plain:lib_C8Oforms_AI.Chat"}'
↓form_id [ngx.components.UIControlVariable-1730200694043]:
comment: new variable
varValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: script:this.navParams?.data?.form_id ?? ""
↓message [ngx.components.UIControlVariable-1730200694045]:
comment: new variable
varValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: source:{"filter":"Action","project":"C8Oforms","input":"","model":{"data":[{"priority":1730200487383,"rootEvent":true,"pageLocals":false}],"path":"?.out","prefix":"","suffix":"?.message ?? \"\"","custom":"","useCustom":false}}
↓reset [ngx.components.UIControlVariable-1730219893805]:
comment: new variable
varValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: source:{"filter":"Action","project":"C8Oforms","input":"","model":{"data":[{"priority":1730200487383,"rootEvent":true,"pageLocals":false}],"path":"?.out","prefix":"","suffix":"?.reset ?? \"false\"","custom":"","useCustom":false}}
↓SetLocal [ngx.components.UIDynamicAction-1730280605676]:
beanData: |
'{
"ionBean": "SetLocalAction",
"Property": "plain:chat",
"Value": "source:{\"filter\":\"Action\",\"project\":\"C8Oforms\",\"input\":\"\",\"model\":{\"data\":[{\"priority\":1730198395692,\"rootEvent\":false,\"pageLocals\":false},{\"priority\":1730200487383,\"rootEvent\":true,\"pageLocals\":false}],\"path\":\"?.out?.form\",\"prefix\":\"\",\"suffix\":\"\",\"custom\":\"\",\"useCustom\":false}}"
}'
↓ScrollBottom [ngx.components.UICustomAction-1730201121737]:
actionValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.common.FormatedContent
- com.twinsoft.convertigo.beans.common.FormatedContent:
: |
' page.c8o.log.debug(''[MB] ''+ props.actionFunction +'': ''+ props.actionName);
window.setTimeout(() => {
page.content.scrollToBottom(200);
},200);
resolve();
'
↓Show_Loading [ngx.components.UIDynamicAction-1730732820232]:
beanData: |
'{
"ionBean": "ShowLoadingAction",
"message": "plain:",
"duration": "plain",
"spinner": "plain:bubbles",
"cssClass": "plain:aiLoadingMessage",
"backdropDismiss": "plain:false",
"keyboardClose": "plain:false"
}'
↓ResetForm [ngx.components.UICustomAction-1730199862999]:
actionValue:
- xmlizable:
Expand All @@ -246,14 +296,84 @@ title: Title for aiChat
: |
' page.c8o.log.debug(''[MB] ''+ props.actionFunction +'': ''+ props.actionName);
page.formAiChat.reset();
try {
if (this.local.isRecording) {
this.local.speechReco.stop();
this.local.isRecording = false;
}
} catch (e) {}
const interval = window.setInterval(() => {
const loading = window.document.querySelector(''.aiLoadingMessage .loading-content'');
if (loading) {
loading.textContent = page.translate.instant(''chatgpt_loading_ai'' + (Math.floor(Math.random() * 10) + 1));
} else {
window.clearInterval(interval);
}
}, 5000);
const content = props.out?.message ?? false;
if (content && page.local.chat?.messages) {
page.local.chat.messages.push({ role: ''user'', content });
page.local.chat.messages.push({ role: ''assistant'', content: '''', waiting: true });
window.setTimeout(() => {
page.content.scrollToBottom(200);
},200);
}
resolve();
'
↓language [ngx.components.UIControlVariable-1730385215158]:
comment: new variable
varValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: script:this.global?.settings?.language
↓CallSequence [ngx.components.UIDynamicAction-1730198395692]:
beanData: |
'{
"ionBean": "CallSequenceAction",
"requestable": "plain:lib_C8Oforms_AI.Chat",
"noLoading": "plain:true"
}'
↓form_id [ngx.components.UIControlVariable-1730200694043]:
comment: new variable
varValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: script:this.navParams?.data?.form_id ?? ""
↓message [ngx.components.UIControlVariable-1730200694045]:
comment: new variable
varValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: source:{"filter":"Action","project":"C8Oforms","input":"","model":{"data":[{"priority":1730200487383,"rootEvent":true,"pageLocals":false}],"path":"?.out","prefix":"","suffix":"?.message ?? \"\"","custom":"","useCustom":false}}
↓reset [ngx.components.UIControlVariable-1730219893805]:
comment: new variable
varValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: source:{"filter":"Action","project":"C8Oforms","input":"","model":{"data":[{"priority":1730200487383,"rootEvent":true,"pageLocals":false}],"path":"?.out","prefix":"","suffix":"?.reset ?? \"false\"","custom":"","useCustom":false}}
↓SetLocal [ngx.components.UIDynamicAction-1730280605676]:
beanData: |
'{
"ionBean": "SetLocalAction",
"Property": "plain:chat",
"Value": "source:{\"filter\":\"Action\",\"project\":\"C8Oforms\",\"input\":\"\",\"model\":{\"data\":[{\"priority\":1730198395692,\"rootEvent\":false,\"pageLocals\":false},{\"priority\":1730200487383,\"rootEvent\":true,\"pageLocals\":false}],\"path\":\"?.out?.form\",\"prefix\":\"\",\"suffix\":\"\",\"custom\":\"\",\"useCustom\":false}}"
}'
↓ScrollBottom [ngx.components.UICustomAction-1730201121737]:
actionValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.common.FormatedContent
- com.twinsoft.convertigo.beans.common.FormatedContent:
: |
' page.c8o.log.debug(''[MB] ''+ props.actionFunction +'': ''+ props.actionName);
window.setTimeout(() => {
page.content.scrollToBottom(200);
},200);
resolve();
'
↓Close_Loading [ngx.components.UIDynamicAction-1730732860615]:
beanData: '{"ionBean":"CloseLoadingAction"}'
↓language [ngx.components.UIControlVariable-1730385215158]:
comment: new variable
varValue:
- xmlizable:
- ↑classname: com.twinsoft.convertigo.beans.ngx.components.MobileSmartSourceType
- MobileSmartSourceType: script:this.global?.settings?.language
↓PageEvent1 [ngx.components.UIPageEvent-1730721387130]:
viewEvent: onWillLeave
↓CustomAsyncAction [ngx.components.UICustomAsyncAction-1730721390390]:
Expand All @@ -269,4 +389,14 @@ title: Title for aiChat
} finally {
return;
}
try {
if (this.local.isRecording) {
this.local.speechReco.stop();
this.local.isRecording = false;
}
} catch (e) {
} finally {
return;
}
Loading

0 comments on commit 41ea396

Please sign in to comment.