Skip to content

Commit

Permalink
Merge pull request #1494 from RADAR-base/fix/next-button
Browse files Browse the repository at this point in the history
Allow going to the next question with keyboard 'enter'
  • Loading branch information
mpgxvii authored Jul 12, 2022
2 parents c472200 + ee73902 commit 7f3a890
Show file tree
Hide file tree
Showing 17 changed files with 180 additions and 94 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
uses: android-actions/setup-android@v2

- name: Fix Android directories
run: rm -R /usr/local/lib/android/sdk/build-tools/31.0.0/ && rm -R /usr/local/lib/android/sdk/build-tools/32.0.0/
run: rm -R /usr/local/lib/android/sdk/build-tools/31.0.0/ && rm -R /usr/local/lib/android/sdk/build-tools/32.0.0/ && rm -R /usr/local/lib/android/sdk/build-tools/33.0.0/

- name: Setup Node
uses: actions/setup-node@v2
Expand Down
2 changes: 1 addition & 1 deletion config.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<widget android-versionCode="565" id="org.phidatalab.radar_armt" ios-CFBundleIdentifier="org.phidatalab.radar-armt" ios-CFBundleVersion="1" version="2.4.0-alpha" xmlns:android="http://schemas.android.com/apk/res/android">
<widget android-versionCode="566" id="org.phidatalab.radar_armt" ios-CFBundleIdentifier="org.phidatalab.radar-armt" ios-CFBundleVersion="1" version="2.5.0-alpha" xmlns:android="http://schemas.android.com/apk/res/android">
<name>RADAR Questionnaire</name>
<description>An application that collects active data for research.</description>
<author email="[email protected]" href="http://radar-base.org/">RADAR-Base</author>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ introduction {
.icons-big {
width: 30%;
}

h2 {
font-size: 15px !important;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import { AudioRecordService } from '../../../services/audio-record.service'
export class AudioInputComponent implements OnDestroy, OnInit {
@Output()
valueChange: EventEmitter<any> = new EventEmitter<any>()
@Output()
onRecordStart: EventEmitter<any> = new EventEmitter<any>()
@Input()
text: string
@Input()
Expand Down Expand Up @@ -77,6 +79,7 @@ export class AudioInputComponent implements OnDestroy, OnInit {
this.startRecording().catch(e => this.showTaskInterruptedAlert())
} else {
this.stopRecording()
this.onRecordStart.emit(false)
if (this.recordAttempts == DefaultMaxAudioAttemptsAllowed)
this.finishRecording().catch(e => this.showTaskInterruptedAlert())
else this.showAfterAttemptAlert()
Expand All @@ -95,6 +98,7 @@ export class AudioInputComponent implements OnDestroy, OnInit {
this.permissionUtil.getRecordAudio_Permission(),
this.permissionUtil.getWriteExternalStorage_permission()
]).then(res => {
this.onRecordStart.emit(true)
this.usage.sendGeneralEvent(UsageEventType.RECORDING_STARTED, true)
return res[0] && res[1]
? this.audioRecordService.startAudioRecording()
Expand Down
27 changes: 14 additions & 13 deletions src/app/pages/questions/components/question/question.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@
<radio-input
*ngSwitchCase="'radio'"
[responses]="question.select_choices_or_calculations"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
>
</radio-input>

<checkbox-input
*ngSwitchCase="'checkbox'"
[responses]="question.select_choices_or_calculations"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
>
</checkbox-input>

Expand All @@ -64,7 +64,7 @@
[max]="question.range.max"
[labelLeft]="question.range.labelLeft"
[labelRight]="question.range.labelRight"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
>
</range-input>

Expand All @@ -73,7 +73,7 @@
[min]="question.range.min"
[max]="question.range.max"
[responses]="question.select_choices_or_calculations"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
>
</range-info-input>

Expand All @@ -84,7 +84,7 @@
[step]="question.range.step"
[labelLeft]="question.range.labelLeft"
[labelRight]="question.range.labelRight"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
>
</slider-input>

Expand All @@ -93,7 +93,7 @@
[sections]="question.select_choices_or_calculations"
[hasFieldLabel]="question.field_label.length > 0"
[image]="question.field_annotation?.image"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
[currentlyShown]="currentlyShown"
>
</info-screen>
Expand All @@ -102,7 +102,8 @@
*ngSwitchCase="'audio'"
[text]="question.field_label"
[currentlyShown]="currentlyShown"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
(onRecordStart)="onAudioRecordStart($event)"
>
</audio-input>

Expand All @@ -112,14 +113,14 @@
[image]="question.field_annotation.image"
[timer]="question.field_annotation.timer"
[currentlyShown]="currentlyShown"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
>
</timed-test>

<text-input
*ngSwitchCase="'text'"
(valueChange)="onValueChange($event)"
(textInputFocus)="onTextInputFocus($event)"
(valueChange)="emitAnswer($event)"
(keyboardEvent)="onKeyboardEvent($event)"
[type]="question.text_validation_type_or_show_slider_number"
[currentlyShown]="currentlyShown"
></text-input>
Expand All @@ -130,14 +131,14 @@
{ code: '1', label: 'Yes' },
{ code: '0', label: 'No' }
]"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
>
</radio-input>

<descriptive-input
*ngSwitchCase="'descriptive'"
[text]="question.field_label"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
[currentlyShown]="currentlyShown"
>
</descriptive-input>
Expand All @@ -147,7 +148,7 @@
[responses]="question.select_choices_or_calculations"
[currentlyShown]="currentlyShown"
[previouslyShown]="previouslyShown"
(valueChange)="onValueChange($event)"
(valueChange)="emitAnswer($event)"
>
</matrix-radio-input>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@ question {

.input-scroll {
overflow-y: auto !important;
mask-image: linear-gradient(to top, transparent 3%, black 7%),
linear-gradient(to bottom, transparent 0%, black 7%);
mask-size: 100% 25%, 100% 80%;
mask-position: bottom, top;
mask-repeat: no-repeat, no-repeat;
}

.spinner-container {
Expand Down
98 changes: 54 additions & 44 deletions src/app/pages/questions/components/question/question.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import {
} from '@angular/core'
import { Dialogs } from '@ionic-native/dialogs/ngx'
import { Vibration } from '@ionic-native/vibration/ngx'
import { Content, Keyboard } from 'ionic-angular'
import * as smoothscroll from 'smoothscroll-polyfill'

import {
KeyboardEventType,
NextButtonEventType
} from '../../../../shared/enums/events'
import { Answer } from '../../../../shared/models/answer'
import { Question, QuestionType } from '../../../../shared/models/question'
import { Task } from '../../../../shared/models/task'
Expand All @@ -34,8 +37,13 @@ export class QuestionComponent implements OnInit, OnChanges {
task: Task
@Input()
isSectionHeaderHidden: boolean
// isNextAutomatic: automatically slide to next upon answer
@Input()
isNextAutomatic: boolean
@Output()
answer: EventEmitter<Answer> = new EventEmitter<Answer>()
@Output()
nextAction: EventEmitter<any> = new EventEmitter<any>()

value: any
currentlyShown = false
Expand Down Expand Up @@ -79,11 +87,7 @@ export class QuestionComponent implements OnInit, OnChanges {
QuestionType.checkbox
])

constructor(
private vibration: Vibration,
private dialogs: Dialogs,
private keyboard: Keyboard
) {
constructor(private vibration: Vibration, private dialogs: Dialogs) {
smoothscroll.polyfill()
this.value = null
}
Expand Down Expand Up @@ -118,31 +122,20 @@ export class QuestionComponent implements OnInit, OnChanges {
else this.previouslyShown = false
this.currentlyShown = false
}
// this.evalBeep()
}

emitAnswer() {
this.answer.emit({
id: this.question.field_name,
value: this.value,
type: this.question.field_type
})
}

onValueChange(event: any) {
emitAnswer(event: any) {
// NOTE: On init the component fires the event once
if (event === undefined) {
return
}
this.value = event
this.emitAnswer()
}

evalBeep() {
if (this.currentlyShown && this.question.field_label.includes('beep')) {
console.log('Beep!')
this.dialogs.beep(1)
this.vibration.vibrate(600)
if (event && event !== undefined) {
this.value = event
this.answer.emit({
id: this.question.field_name,
value: this.value,
type: this.question.field_type
})
if (this.question.isAutoNext)
this.nextAction.emit(NextButtonEventType.AUTO)
else this.nextAction.emit(NextButtonEventType.ENABLE)
}
}

Expand All @@ -153,12 +146,14 @@ export class QuestionComponent implements OnInit, OnChanges {
) {
const min = this.question.select_choices_or_calculations[0].code
const minLabel = this.question.select_choices_or_calculations[0].label
const max = this.question.select_choices_or_calculations[
this.question.select_choices_or_calculations.length - 1
].code
const maxLabel = this.question.select_choices_or_calculations[
this.question.select_choices_or_calculations.length - 1
].label
const max =
this.question.select_choices_or_calculations[
this.question.select_choices_or_calculations.length - 1
].code
const maxLabel =
this.question.select_choices_or_calculations[
this.question.select_choices_or_calculations.length - 1
].label
this.question.range = {
min: parseInt(min.trim()),
max: parseInt(max.trim()),
Expand All @@ -168,16 +163,26 @@ export class QuestionComponent implements OnInit, OnChanges {
}
}

onTextInputFocus(value) {
if (value) {
// Add delay for keyboard to show up
setTimeout(() => {
this.content.nativeElement.style = `padding-bottom:${this.keyboardInputOffset}px;`
this.content.nativeElement.scrollTop = this.keyboardInputOffset
}, 100)
} else {
this.content.nativeElement.style = ''
this.content.nativeElement.scrollTop = 0
onKeyboardEvent(value) {
switch (value) {
case KeyboardEventType.FOCUS:
// Add delay for keyboard to show up
setTimeout(() => {
this.content.nativeElement.style = `padding-bottom:${this.keyboardInputOffset}px;`
this.content.nativeElement.scrollTop = this.keyboardInputOffset
}, 100)
break
case KeyboardEventType.BLUR: {
this.content.nativeElement.style = ''
this.content.nativeElement.scrollTop = 0
break
}
case KeyboardEventType.ENTER: {
this.nextAction.emit(NextButtonEventType.AUTO)
break
}
default:
break
}
}

Expand Down Expand Up @@ -210,4 +215,9 @@ export class QuestionComponent implements OnInit, OnChanges {
behavior: 'smooth'
})
}

onAudioRecordStart(start: boolean) {
if (start) this.nextAction.emit(NextButtonEventType.DISABLE)
else this.nextAction.emit(NextButtonEventType.ENABLE)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@
<ion-item>
<ion-input
type="text"
enterkeyhint="next"
placeholder="{{ 'PLACEHOLDER_TEXT_INPUT' | translate }}"
(ionChange)="emitAnswer($event.value)"
(ionFocus)="emitTextInputFocus(true)"
(ionBlur)="emitTextInputFocus(false)"
(ionFocus)="emitKeyboardEvent('focus')"
(ionBlur)="emitKeyboardEvent('blur')"
(keyup.enter)="emitKeyboardEvent('enter')"
></ion-input>
</ion-item>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ import {
Output,
ViewChild
} from '@angular/core'
import { IonicFormInput } from 'ionic-angular'
import { Keyboard } from '@ionic-native/keyboard/ngx'

import { LocalizationService } from '../../../../../core/services/misc/localization.service'
import { KeyboardEventType } from '../../../../../shared/enums/events'

@Component({
selector: 'text-input',
templateUrl: 'text-input.component.html',
templateUrl: 'text-input.component.html'
})
export class TextInputComponent implements OnInit {
@ViewChild('content') content

@Output()
valueChange: EventEmitter<string> = new EventEmitter<string>()
@Output()
textInputFocus: EventEmitter<string> = new EventEmitter<string>()
keyboardEvent: EventEmitter<string> = new EventEmitter<string>()
@Input()
type: string
@Input()
Expand All @@ -45,12 +46,15 @@ export class TextInputComponent implements OnInit {
hour: 'Hour',
minute: 'Minute',
second: 'Second',
ampm: 'AM/PM',
ampm: 'AM/PM'
}

value = {}

constructor(private localization: LocalizationService) {}
constructor(
private localization: LocalizationService,
private keyboard: Keyboard
) {}

ngOnInit() {
if (this.type.length) {
Expand Down Expand Up @@ -112,13 +116,16 @@ export class TextInputComponent implements OnInit {
}

emitAnswer(value) {
if (!value) return
if (typeof value !== 'string') {
this.value = Object.assign(this.value, value)
this.valueChange.emit(JSON.stringify(this.value))
} else this.valueChange.emit(value)
}

emitTextInputFocus(value) {
this.textInputFocus.emit(value)
emitKeyboardEvent(value) {
if (value == KeyboardEventType.ENTER) this.keyboard.hide()

this.keyboardEvent.emit(value)
}
}
Loading

0 comments on commit 7f3a890

Please sign in to comment.