Video chat windows is not display /reactjs with twillio - reactjs

I have developed a video chat using Reactjs with twillio. In my project I have to develop two sides ,for one side the chat application run smoothly, but in other one the camera is powered on but video stream does not display(local-media not updating and remote-media), i have used the following code from twilio,
import React, { Component } from "react";
import axios from "axios";
import Video from "twilio-video";
export default class VideoComponent extends Component {
constructor(props) {
super(props);
this.activeRoom = null;
this.previewTracks = null;
this.identity = null;
this.roomName = null;
this.roomJoined = this.roomJoined.bind(this);
}
componentDidMount() {
window.addEventListener("beforeunload", this.leaveRoomIfJoined);
this.refs.buttonPreview.onclick = ()=> {
var localTracksPromise = this.previewTracks
? Promise.resolve(this.previewTracks)
: Video.createLocalTracks();
localTracksPromise.then(
(tracks)=> {
window.previewTracks = this.previewTracks = tracks;
var previewContainer = document.getElementById("local-media");
if (!previewContainer.querySelector("video")) {
this.attachTracks(tracks, previewContainer);
}
},
(error)=> {
this.log("Unable to access Camera and Microphon");
}
);
};
axios.get("/token").then(results => {
this.identity = results.data.identity;
this.refs.roomControls.style.display = "block";
// Bind button to join Room.
this.refs.buttonJoin.onclick = ()=>{
this.roomName = this.refs.roomName.value;
if (!this.roomName) {
alert("Please enter a room name.");
return;
}
this.log("Joining room '" + this.roomName + "'...");
var connectOptions = {
name: this.roomName,
logLevel: "debug"
};
if (this.previewTracks) {
connectOptions.tracks = this.previewTracks;
}
// Join the Room with the token from the server and the
// LocalParticipant's Tracks.
Video.connect(results.data.token, connectOptions).then(this.roomJoined, (error)=> {
this.log("Could not connect to Twilio: " + error.message);
});
};
// Bind button to leave Room.
this.refs.buttonLeave.onclick = ()=> {
this.log("Leaving room...");
this.activeRoom.disconnect();
};
});
}
attachTracks(tracks, container) {
tracks.forEach((track)=> {
container.appendChild(track.attach());
});
}
attachParticipantTracks(participant, container) {
var tracks = Array.from(participant.tracks.values());
this.attachTracks(tracks, container);
}
detachTracks(tracks) {
tracks.forEach((track)=> {
track.detach().forEach((detachedElement)=> {
detachedElement.remove();
});
});
}
detachParticipantTracks(participant) {
var tracks = Array.from(participant.tracks.values());
this.detachTracks(tracks);
}
log(message) {
var logDiv = this.refs.log;
logDiv.innerHTML += "<p>> " + message + "</p>";
logDiv.scrollTop = logDiv.scrollHeight;
}
roomJoined(room) {
this.activeRoom = room;
window.room = room.name;
this.log("Joined as '" + this.identity + "'");
this.refs.buttonJoin.style.display = "none";
this.refs.buttonLeave.style.display = "inline";
// Attach LocalParticipant's Tracks, if not already attached.
var previewContainer = this.refs.localMedia;
if (!previewContainer.querySelector("video")) {
this.attachParticipantTracks(room.localParticipant, previewContainer);
}
// Attach the Tracks of the Room's Participants.
room.participants.forEach((participant)=> {
this.log("Already in Room: '" + participant.identity + "'");
var previewContainer = document.getElementById("remote-media");
this.attachParticipantTracks(participant, previewContainer);
});
// When a Participant joins the Room, log the event.
room.on("participantConnected", (participant)=> {
this.log("Joining: '" + participant.identity + "'");
});
// When a Participant adds a Track, attach it to the DOM.
room.on("trackAdded", (track, participant)=> {
this.log(participant.identity + " added track: " + track.kind);
var previewContainer = document.getElementById("remote-media");
this.attachTracks([track], previewContainer);
});
// When a Participant removes a Track, detach it from the DOM.
room.on("trackRemoved", (track, participant)=> {
this.log(participant.identity + " removed track: " + track.kind);
this.detachTracks([track]);
});
// When a Participant leaves the Room, detach its Tracks.
room.on("participantDisconnected", (participant)=> {
this.log("Participant '" + participant.identity + "' left the room");
this.detachParticipantTracks(participant);
});
// Once the LocalParticipant leaves the room, detach the Tracks
// of all Participants, including that of the LocalParticipant.
room.on("disconnected", ()=> {
this.log("Left");
if (this.previewTracks) {
this.previewTracks.forEach((track)=> {
track.stop();
});
}
this.detachParticipantTracks(room.localParticipant);
room.participants.forEach(this.detachParticipantTracks);
this.activeRoom = null;
this.refs.buttonJoin.style.display = "inline";
document.getElementById("button-leave").style.display = "none";
});
}
leaveRoomIfJoined() {
if (this.activeRoom) {
this.activeRoom.disconnect();
}
}
render() {
return (
<div>
<div id="remote-media"></div>
<div id="controls">
<div id="preview">
<p className="instructions">Hello</p>
<div ref="localMedia" id="local-media"></div>
<button ref="buttonPreview" id="button-preview">Preview My Camera</button>
</div>
<div ref="roomControls">
<p className="instructions">Room Name:</p>
<input ref="roomName" id="room-name" type="text" placeholder="Enter a room name" />
<button ref="buttonJoin" id="button-join">Join Room</button>
<button ref="buttonLeave" id="button-leave">Leave Room</button>
</div>
<div ref="log" id="log"></div>
</div>
</div>
);
}
}

Related

web component after page load is getting destroyed

I created a custom element(web component) and using webpack will render without any issues but as I include on the working page(which is a wordpress) on render will show up and at the end of the request to hole rendered element is getting destroyed. I do not get any error in console.
the component looks as it follows
import moment from "moment";
import 'moment/min/moment-with-locales'
moment.locale('de');
export class ToursEvents extends HTMLElement {
constructor() {
super();
//this.attachShadow({mode: 'closed'});
}
connectedCallback() {
this.html = this.innerHTML;
}
get data() {
return this._data;
}
set data(tours) {
let times = tours[0]
this._data = tours[0];
this.vendors = tours[1];
let div = document.createElement("div");
div.innerHTML = `
${times.reduce((acc, item) => `${acc}
<div class="bk_day tours-list__slot">
<div class="bk_date tours-list__date">${moment(item.day).format("dddd")}, ${moment(item.day).format("DD.MM.YYYY")}</div>
<ul class="tours-list__vendors">${ this.makeList(item.times) }</ul>
</div>`
, ``)}`;
this.innerHTML = div.innerHTML
//this.shadowRoot.appendChild(div);
}
makeList(times) {
let list = '';
times.map( (time) => {
const eventId = time.event_id;
const vendor = this.vendors[eventId];
let percentageFree = 0, mark = "", availability ="", workload = typeof(WORKLOAD) !== 'undefined' ? WORKLOAD : 0.8;
let tips = '';
list += '<li data-date="' + time.date + '" data-event-id="' + eventId + '" class="' + mark + '">';
list += '<div class="tours-list__time">' + moment(time.date).format('HH.mm') + ' - ' + moment(time.date).format('HH.mm') +'</div>';
if(vendor.title.includes("Discount")) {
tips += '<div><span class="discount">Spar-tipp!</span></div>';
}
list += '<div class="tours-list__title">' + tips + vendor.title + '</div>';
if(time.available_slots != 0) {
list += '<div class=""><button class=""><span class="bk_info_text">Infos/Tickets</span> <span class="icon-down"></span></button></div>'
} else {
list += '<div class="bk_info"><span>Booked</span></div>'
}
list += '</li>';
});
return list
}
showDetails() {
}
}
customElements.define('tours-events', ToursEvents);
How should I debug this issue?
If you run customElements.define('tours-events', class{}); in the console
and you get undefined you know (WordPress?) redirected you to another page.
If you get a DOM exception the Element IS defined
If your Element is not in the DOM (if that is what you mean with 'destroyed')
you have to step through the console-debugger to find the reason when/why it was removed.
Put a debugger; statement in your element's Constructor and take it from there.

React-share. Throws error TypeError: Super expression must either be null or a function, not undefined when trying to use it in require

I am new in ReactJs and trying to learn it. I installed a package of react-share. Since i am trying to edit someone else's code i am not able to import the package due to webpack I believe. Every time i try to import a package I receive an error saying the import should always be on top of the script. I tried using require and I get this error in Console
TypeError: Super expression must either be null or a function, not undefined
My code looks like this:
"use strict";
require('./../../../assets/styles/components/thread.less');
var reactShare = require('react-share');
var React = require('react');
var ReactDOM = require('react-dom');
var Fluxxor = require('fluxxor');
var _ = require("lodash");
var FluxMixin = Fluxxor.FluxMixin(React);
var StoreWatchMixin = Fluxxor.StoreWatchMixin;
var routerShape = require('react-router').routerShape;
var MicroAudioViews = require('./../../constants/MicroAudioViews');
var AudioModes = require("./../../constants/AudioModes");
var i18n = require("i18next-client");
//components
var AudioVisualizer = require('../elements/AudioVisualizer');
var ReviewOverlay = require('../elements/ReviewOverlay');
var ReviewShare = require('../elements/ReviewShare');
var Menu = require('../elements/Menu');
I have to use react-share's
<FacebookShareButton url={shareLink} quote={title} className="social-media-icon">
<FacebookIcon size={32} round />
</FacebookShareButton>`
Component to share the shareLink on facebook.
Here the full code.
/*import {
FacebookShareButton,
GooglePlusShareButton,
TwitterShareButton,
WhatsappShareButton,
FacebookIcon,
TwitterIcon,
WhatsappIcon
} from 'react-share';*/
"use strict";
require('./../../../assets/styles/components/thread.less');
var reactShare = require('react-share');
var React = require('react');
var ReactDOM = require('react-dom');
var Fluxxor = require('fluxxor');
var _ = require("lodash");
var FluxMixin = Fluxxor.FluxMixin(React);
var StoreWatchMixin = Fluxxor.StoreWatchMixin;
var routerShape = require('react-router').routerShape;
var MicroAudioViews = require('./../../constants/MicroAudioViews');
var AudioModes = require("./../../constants/AudioModes");
var i18n = require("i18next-client");
//components
var AudioVisualizer = require('../elements/AudioVisualizer');
var ReviewOverlay = require('../elements/ReviewOverlay');
var ReviewShare = require('../elements/ReviewShare');
var Menu = require('../elements/Menu');
var Review = React.createClass({
mixins:[
FluxMixin,
StoreWatchMixin("ThreadStore", "RecordStore", "ReviewStore", "ApplicationStore", "SyncStore", "DemoStore", "ShareStore")
],
contextTypes: {
router: routerShape.isRequired
},
/* react interface*/
getInitialState: function() {
var selectedThreads = [];
var shareType = 'thread';
if(this.props.location.state && this.props.location.state.type == "thread") {
selectedThreads.push(this.props.location.state.threadId);
} else if(this.props.location.state && this.props.location.state.type == "share") {
shareType = 'facebook';
} else if (this.props.location.state && this.props.location.state.type == 'sharereply') {
shareType = 'sharereply';
}
return {
threadUserId: this.props.params.id,
activeShareType: shareType,
selectedThreads: selectedThreads
};
},
getStateFromFlux: function() {
var flux = this.getFlux();
var recordStoreState = flux.store('RecordStore').getState();
var threadStoreState = flux.store('ThreadStore').getState();
var appStoreState = flux.store('ApplicationStore').getState();
var reviewStoreState = flux.store('ReviewStore').getState();
var shareStoreState = flux.store('ShareStore').getState();
var demoState = flux.store('DemoStore').getState();
var activeRecord = recordStoreState.activeRecord || null;
var activeThread = threadStoreState.activeThread;
var activeRecordUser = null;
var authenticatedUser = appStoreState.demoMode? demoState.user : appStoreState.user;
var state = {
demoMode: appStoreState.demoMode,
playing: recordStoreState.playing,
recording: recordStoreState.recording,
activeThread: activeThread,
threads: threadStoreState.threads,
authenticatedUser: authenticatedUser,
activeRecord: activeRecord,
activeShareUser: shareStoreState.user,
shareId: shareStoreState.shareId
};
return state;
},
render: function() {
var threadClass = "thread";
var fbClass = "facebook";
var explanationText, usageContent;
var finishButtonClass = 'finish-button';
if(this.state.activeShareType == "thread") {
threadClass += ' active';
explanationText = i18n.t('content:review.reviewDoneExpl', {
count: this.state.selectedThreads.length,
context: this.state.selectedThreads.length == 0 ? 'doselect' : undefined
});
finishButtonClass += this.state.selectedThreads.length == 0 ? ' inactive' : '';
var threadCards = [];
var self = this;
_.each(this.state.threads, function(thread){
var threadUser = thread.user;
var threadUserPicture = threadUser.pictures[0].source;
var userName = threadUser.firstName + ' ' + threadUser.lastName;
var styleProps = {
backgroundImage : threadUserPicture ? 'url(' + threadUserPicture + ')': 'none'
};
var cls = "thread card" + (self.state.selectedThreads.indexOf(thread.id) != -1? " selected" : "");
threadCards.push(<div key={thread.id} className={cls} onClick={self.onThreadCardSelected} data-thread-id={thread.id}>
<div className='pic' style={styleProps}></div>
<div className='name'>{userName}</div>
<div className='checked micro-audio-icon-check'></div>
</div>);
});
//if thread cards array is null then we are displaying the required text
if(threadCards.length==0){
var text= "Du hast noch keine Freunde in audiyoh hinzugefugt (gehe dafur zur Suche).";
//displaying the content
usageContent = (
<div className="usage-target-container">
<p className="chat-text">{text} <br/>Uber <img className="share-icon" src={require('./../../../assets/images/share-active.png')} /> Teilen kannst du deine Aufnahme in aderen Kanale teilen.</p>
</div>);
//displaying the button
var finishContainer = <div className="finish-container">
<div className={finishButtonClass} >Fertige</div>
<div className="finish-text"><p className="chat-underbtn-text">Mindestens <b> ein Gesprach <br/> wahlen,</b> dem die Aufnahme <br/> hinzugefugt werden soll</p></div>
</div>;
}else{
usageContent = (
<div className="usage-target-container">
{threadCards}
</div>);
}
} else {
fbClass += ' active';
finishButtonClass += ' facebook';
explanationText = i18n.t('content:review.facebookExplanation');
//displaying the input box with the link and copy button
console.log("THe shareStoreState is " + this.state.shareId);
//the shareId is generate asynchroneously, so this.state.shareId can be null
if(typeof this.state.shareId === "string") {
//the link can be created like this:
var shareLink = window.location.origin + '/shared/' + this.state.shareId;
}
var usageContent = (
<div className="usage-target-container">
<div className="socialLinkContainer">
<p> Link zum Teilen </p>
<input className="copylink" type="text" value={shareLink} id="shareLink" /><br/>
<input className="copybtn" type="button" onClick={this.copytoclipboard} value="Link kopieren" />
</div>
</div>);
var finishContainer = <div className="finish-container">
<div className="social-media">
/*<img className="social-media-icon" src={require('./../../../assets/images/facebook.png')} />*/
<FacebookShareButton
url={shareLink}
quote={title}
className="social-media-icon">
<FacebookIcon
size={32}
round />
</FacebookShareButton>
<img className="social-media-icon" src={require('./../../../assets/images/whatsapp.png')} />
<img className="social-media-icon" src={require('./../../../assets/images/twitter.png')} />
<img className="social-media-icon" src={require('./../../../assets/images/instagram.png')} />
</div>
</div>;
}
var targetSwitchElements = [
<div title={i18n.t('content:review.sharethread')}
key="thread"
className={threadClass}
onClick={this.activateThreadShareType}><span>audiyoh-chat</span></div>,<br/>,
<div title={i18n.t('content:review.sharefb')}
key="facebook"
className={fbClass}
onClick={this.activateFBShareType}><span>Teilen</span></div>
];
//we either want to save a profile record a share response, so we dont need the fb/thread switch and thread cards
if(this.props.location.state && ["profile", "sharereply"].indexOf(this.props.location.state.type) != -1) {
var buttonText = i18n.t('content:review.profile');
if(this.props.location.state.type == "sharereply"){
buttonText = i18n.t('content:review.share', {name: this.state.activeShareUser.firstName});
}
targetSwitchElements = <div className="profile-record" onClick={this.onFinishRecord}>{buttonText}</div>;
usageContent = null;
finishContainer = null;
}
return (
<div className="ma-reviewing">
<div className="review-controls">
<div className="row">
<div className="col-3">
<a title={i18n.t('content:review.delete')} className="delete" onClick={this.deleteRecording}></a>
<a title={i18n.t('content:review.redo')} className="record" onClick={this.onRecordButtonClick}></a>
</div>
<div className="col-6">
<div className="review-container">
<ReviewOverlay
activeRecordUser={this.state.authenticatedUser}
record={this.state.activeRecord}
/>
</div>
</div>
{finishContainer}
<div className="col-3">
<div className="target-switch">
<p>Weiter mit der Aufnahme</p>
{targetSwitchElements}
</div>
</div>
</div>
</div>
<div className="upper" ref="upper">
<Menu location={this.props.location} />
<div className="menu">
</div>
</div>
<div className="upperguard" ref="upperguard"></div>
<div className="lower" ref="lower">
<div className="sizing-wrapper">
{usageContent}
</div>
</div>
</div>
);
},
deleteRecording: function(e) {
e.preventDefault();
if(this.props.location && this.props.location.state.userId) {
this.context.router.push({
pathname: "/thread/" + this.props.location.state.userId,
state: this.props.location.state
});
}
else {
this.context.router.push({
pathname: "/profile",
state: this.props.location.state
});
}
},
onRecordButtonClick: function(e) {
e.preventDefault();
this.context.router.push({
pathname: "/record",
state: this.props.location.state
});
},
onThreadCardSelected: function(syntheticEvent, reactId, e) {
var target = syntheticEvent.target.parentNode;
var threadId = target.getAttribute("data-thread-id");
var idx = this.state.selectedThreads.indexOf(threadId);
if(idx != -1) {
this.state.selectedThreads.splice(idx, 1);
this.setState({
selectedThreads: [].concat(this.state.selectedThreads)
});
}
else {
this.setState({
selectedThreads: [threadId].concat(this.state.selectedThreads)
});
}
},
activateThreadShareType: function() {
if(this.state.activeShareType == "thread") {
return;
}
this.setState({
activeShareType: 'thread'
});
},
activateFBShareType: function() {
if(this.state.activeShareType == "facebook") {
return;
}
this.setState({
activeShareType: 'facebook'
});
//this will store the record and generate a shareId
this.getFlux().actions.record.local.saveRecording({
type: "share"
});
/*var state1 = this.context.router.push({
pathname: '/review',
state: {
type: "profile",
role: "main"
}
});*/
//console.log("the state1 is " + state1);
//this.getFlux().actions.record.local.saveRecording(state1);
},
copytoclipboard: function(){
var copyText = document.getElementById("shareLink");
copyText.select();
document.execCommand("copy");
console.log("Copied the text: " + copyText.value);
},
onFinishRecord: function(e) {
if(e.target.classList.contains('inactive')) {
return;
}
if(this.props.location.state && ["profile", "sharereply"].indexOf(this.props.location.state.type) != -1) {
console.log(this.props.location.state);
this.getFlux().actions.record.local.saveRecording(this.props.location.state);
}
else if(this.state.activeShareType == "facebook") {
this.getFlux().actions.record.local.saveRecording({
type: "share"
});
}
else {
var data = {
type: "thread",
threadIds: this.state.selectedThreads
};
//we started recording from a thread, so we pass the userId to be able to return to this thread
//after saving
if(this.props.location.state && this.props.location.state.type == "thread") {
data.userId = this.props.location.state.userId;
}
this.getFlux().actions.record.local.saveRecording(data);
}
}
});
module.exports = Review;
I found my error!
The problem was that I initialized the require('react-share') in a variable reactShare and was using the component as
<FacebookShareButton url={shareLink} quote={title} className="social-media-icon">
<FacebookIcon size={32} round />
</FacebookShareButton>`
Instead, I should have initialized the require statement as
var FacebookShareButton = require('react-share');
Because of not declaring it properly React was yelling on me.
I hope this will save someones precious time. Cheers!

How to get the file duration using Ionic File, Media and Media Object?

I am using Ionic 3 and I used the native plugin called Ionic Native - Media and the Ionic File. I am successfully recording an audio using my mobile devices in android and the play button is working perfectly. However I wanted to get the duration of the file of the audio and display the total length of the duration. I also want to display the current duration when the button is click.
Here is my code in my home.html
<ion-header>
<ion-navbar>
<ion-title>
Sound Recorder & Player
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-card>
<ion-card-content>
<ion-card-title>
<button ion-button primary (click)="stopRecord()" *ngIf="recording"><ion-icon name="mic-off"></ion-icon> Stop Record</button>
<button ion-button primary (click)="startRecord()" *ngIf="!recording"><ion-icon name="mic"></ion-icon> Start Record</button>
</ion-card-title>
</ion-card-content>
</ion-card>
<ion-list>
<ion-item *ngFor="let audio of audioList; index as i;">
<p>{{audio.filename}}</p>
<button ion-button clear item-end large (click)="playAudio(audio.filename, i)"><ion-icon name="play"></ion-icon></button>
</ion-item>
</ion-list>
</ion-content>
and here is the code in my home.ts
import { Component } from '#angular/core';
import { NavController, Platform } from 'ionic-angular';
import { Media, MediaObject } from '#ionic-native/media';
import { File } from '#ionic-native/file';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
recording: boolean = false;
filePath: string;
fileName: string;
audio: MediaObject;
audioList: any[] = [];
constructor(
public navCtrl: NavController,
private media: Media,
private file: File,
public platform: Platform
) {
}
ionViewWillEnter() {
this.getAudioList();
}
getAudioList() {
if(localStorage.getItem("audiolist")) {
this.audioList = JSON.parse(localStorage.getItem("audiolist"));
console.log(this.audioList);
}
}
startRecord() {
if (this.platform.is('ios')) {
this.fileName = 'record'+new Date().getDate()+new Date().getMonth()+new Date().getFullYear()+new Date().getHours()+new Date().getMinutes()+new Date().getSeconds()+'.3gp';
this.filePath = this.file.documentsDirectory.replace(/file:\/\//g, '') + this.fileName;
this.audio = this.media.create(this.filePath);
} else if (this.platform.is('android')) {
this.fileName = 'record'+new Date().getDate()+new Date().getMonth()+new Date().getFullYear()+new Date().getHours()+new Date().getMinutes()+new Date().getSeconds()+'.3gp';
this.filePath = this.file.externalDataDirectory.replace(/file:\/\//g, '') + this.fileName;
this.audio = this.media.create(this.filePath);
let duration = this.audio.getDuration();
console.log(duration)
}
this.audio.startRecord();
this.recording = true;
}
stopRecord() {
this.audio.stopRecord();
let duration = this.audio.getDuration()
console.log(duration)
let data = { filename: this.fileName };
this.audioList.push(data);
localStorage.setItem("audiolist", JSON.stringify(this.audioList));
this.recording = false;
this.getAudioList();
}
playAudio(file,idx) {
if (this.platform.is('ios')) {
this.filePath = this.file.documentsDirectory.replace(/file:\/\//g, '') + file;
this.audio = this.media.create(this.filePath);
} else if (this.platform.is('android')) {
this.filePath = this.file.externalDataDirectory.replace(/file:\/\//g, '') + file;
this.audio = this.media.create(this.filePath);
let duration = this.audio.getDuration()
console.log('Duration:', duration)
}
this.audio.play();
this.audio.setVolume(1.0);
}
}
I tried to console.log the getDuration() function that is written in the docs of Media. However it always return me -1
Any thoughts here?
Appreciate if someone could help.
Thanks in advance.
You are using:
let duration = this.audio.getDuration();
console.log(duration)
Before you start recording:
if (this.platform.is('ios')) {
this.fileName = 'record'+new Date().getDate()+new Date().getMonth()+new Date().getFullYear()+new Date().getHours()+new Date().getMinutes()+new Date().getSeconds()+'.3gp';
this.filePath = this.file.documentsDirectory.replace(/file:\/\//g, '') + this.fileName;
this.audio = this.media.create(this.filePath);
} else if (this.platform.is('android')) {
this.fileName = 'record'+new Date().getDate()+new Date().getMonth()+new Date().getFullYear()+new Date().getHours()+new Date().getMinutes()+new Date().getSeconds()+'.3gp';
this.filePath = this.file.externalDataDirectory.replace(/file:\/\//g, '') + this.fileName;
this.audio = this.media.create(this.filePath);
------>let duration = this.audio.getDuration();<-----
console.log(duration)
}
------>this.audio.startRecord();<-----
this.recording = true;
Are you sure you are looking the correct console.log()?, try to delete the first console.log().
if file.getDuration() give -1, use videoEditor
import { VideoEditor } from '#ionic-native/video-editor/ngx';
getvideoinfo(fileUri) {
this.videoEditor.getVideoInfo({ fileUri: fileUri }).then((videoInfo) => {
alert(videoInfo.duration);
this.mediaduration = videoInfo.duration;
}).catch((error) => {
alert(error);
});
}

How to Keep track of all clicks on page in ionic application?

I have created simple page which contains check boxes. On this page user can check and uncheck boxes multiple times. I want to keep track of all these events? How Can I do that?
here is my code.
app.js
var pmApp = angular.module('pmApp', ['ionic']);
pmApp.controller('CheckboxController', function($scope) {
$scope.devList = [
{ text: "Device & app history", details : "Allows the app to view one or more of: information about activity on the device, which apps are running, browsing history and bookmarks" ,checked: true },
{ text: "Identity", details: "Uses one or more of: accounts on the device, profile data", checked: false },
{ text: "Calendar", details: "Uses calendar information", checked: false },
{ text: "Contact", details: "Uses contact information", checked: false },
{ text: "Location", details: "Uses the device's location", checked: false },
{ text: "SMS", details: "Uses one or more of: SMS, MMS. Charges may apply.", checked: false }
];
$scope.selection=[];
// toggle selection for a given employee by name
$scope.toggleSelection = function toggleSelection(item) {
var idx = $scope.selection.indexOf(item);
// is currently selected
if (idx > -1) {
$scope.selection.splice(idx, 1);
}
// is newly selected
else {
$scope.selection.push(item);
}
};
});
index.html
<div class="list" ng-controller="CheckboxController">
<ion-checkbox ng-repeat="item in devList"
ng-model="item.checked"
ng-checked="selection.indexOf(item) > -1"
ng-click="toggleSelection(item)"
>
{{ item.text }}
<h3 class="item-text-wrap"> {{ item.details }}</h3>
</ion-checkbox>
<div class="item">
<pre ng-bind="selection | json"></pre>
</div>
</div>
Thanks in advance, any help would be appreciated.
Regards
You can use https://docs.angularjs.org/api/ng/directive/ngMouseover to make a counter for mouse hovers on all your elements: and then use
https://docs.angularjs.org/api/ng/directive/ngClick to record clicks and https://docs.angularjs.org/api/ng/directive/ngMousemove to record the mouse being moved and get the position:
Everything Used:
ng-click
ng-dblclick
ng-mousedown
ng-mouseup
ng-mouseenter
ng-mouseleave
ng-mousemove
ng-mouseover
Here is some example code:
HTML:
<body ng-app="mainModule">
<div ng-controller="mainController">
<h3>1. Click</h3>
<button id="firstBtn" ng-click="onFirstBtnClick()">Click me</button>
<strong>RESULT:</strong> {{onFirstBtnClickResult}}<br />
<br />
<h3>2. Click with Dependency Injection</h3>
<label>Type something: <input type="text" ng-model="secondBtnInput"></label>
<button id="secondBtn" ng-click="onSecondBtnClick(secondBtnInput)">Click me</button><br />
<strong>RESULT:</strong> {{onSecondBtnClickResult}}<br />
<br />
<h3>3. Double click</h3>
Double-click the square<br />
<img src="images/square.png" ng-dblclick="onDblClick()" /><br />
<strong>RESULT:</strong> {{onDblClickResult}}<br />
<h3>4. Mouse down, up, enter, leave, move, over</h3>
Move the mouse on the square<br />
<img src="images/square.png"
ng-mousedown="onMouseDown($event)"
ng-mouseup="onMouseUp($event)"
ng-mouseenter="onMouseEnter($event)"
ng-mouseleave="onMouseLeave($event)"
ng-mousemove="onMouseMove($event)"
ng-mouseover="onMouseOver($event)" /><br />
<strong>MOUSE DOWN RESULT:</strong> {{onMouseDownResult}}<br />
<strong>MOUSE UP RESULT:</strong> {{onMouseUpResult}}<br />
<strong>MOUSE ENTER RESULT:</strong> {{onMouseEnterResult}}<br />
<strong>MOUSE LEAVE RESULT:</strong> {{onMouseLeaveResult}}<br />
<strong>MOUSE MOVE RESULT:</strong> {{onMouseMoveResult}}<br />
<strong>MOUSE OVER RESULT:</strong> {{onMouseOverResult}}
</div>
</body>
</html>
JS
angular.module("mainModule", [])
.controller("mainController", function ($scope)
{
// Initialization
$scope.onFirstBtnClickResult = "";
$scope.secondBtnInput = "";
$scope.onDblClickResult = "";
$scope.onMouseDownResult = "";
$scope.onMouseUpResult = "";
$scope.onMouseEnterResult = "";
$scope.onMouseLeaveResult = "";
$scope.onMouseMoveResult = "";
$scope.onMouseOverResult = "";
// Utility functions
// Accepts a MouseEvent as input and returns the x and y
// coordinates relative to the target element.
var getCrossBrowserElementCoords = function (mouseEvent)
{
var result = {
x: 0,
y: 0
};
if (!mouseEvent)
{
mouseEvent = window.event;
}
if (mouseEvent.pageX || mouseEvent.pageY)
{
result.x = mouseEvent.pageX;
result.y = mouseEvent.pageY;
}
else if (mouseEvent.clientX || mouseEvent.clientY)
{
result.x = mouseEvent.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft;
result.y = mouseEvent.clientY + document.body.scrollTop +
document.documentElement.scrollTop;
}
if (mouseEvent.target)
{
var offEl = mouseEvent.target;
var offX = 0;
var offY = 0;
if (typeof(offEl.offsetParent) != "undefined")
{
while (offEl)
{
offX += offEl.offsetLeft;
offY += offEl.offsetTop;
offEl = offEl.offsetParent;
}
}
else
{
offX = offEl.x;
offY = offEl.y;
}
result.x -= offX;
result.y -= offY;
}
return result;
};
var getMouseEventResult = function (mouseEvent, mouseEventDesc)
{
var coords = getCrossBrowserElementCoords(mouseEvent);
return mouseEventDesc + " at (" + coords.x + ", " + coords.y + ")";
};
// Event handlers
$scope.onFirstBtnClick = function () {
$scope.onFirstBtnClickResult = "CLICKED";
};
$scope.onSecondBtnClick = function (value) {
$scope.onSecondBtnClickResult = "you typed '" + value + "'";
};
$scope.onDblClick = function () {
$scope.onDblClickResult = "DOUBLE-CLICKED";
};
$scope.onMouseDown = function ($event) {
$scope.onMouseDownResult = getMouseEventResult($event, "Mouse down");
};
$scope.onMouseUp = function ($event) {
$scope.onMouseUpResult = getMouseEventResult($event, "Mouse up");
};
$scope.onMouseEnter = function ($event) {
$scope.onMouseEnterResult = getMouseEventResult($event, "Mouse enter");
};
$scope.onMouseLeave = function ($event) {
$scope.onMouseLeaveResult = getMouseEventResult($event, "Mouse leave");
};
$scope.onMouseMove = function ($event) {
$scope.onMouseMoveResult = getMouseEventResult($event, "Mouse move");
};
$scope.onMouseOver = function ($event) {
$scope.onMouseOverResult = getMouseEventResult($event, "Mouse over");
};
});
You could try with the newest Ionic Analytics, if that will suit your needs. More info on their official blog post: http://docs.ionic.io/v1.0/docs/analytics-from-scratch.
Usage is pretty straight forward (from the additional docs):
.controller('MyCtrl', function($ionicAnalytics) {
$ionicAnalytics.track('Purchase Item', {
item_id: 'lpdsx,
item_name: 'Leopard Socks'
});
});

How to do the Logic behind the next button in angularjs wizard

I have a customers.create.html partial bound to the WizardController.
Then I have 3 customers.create1,2,3.html partial files bound to WizardController1,2,3
Each WizardController1,2 or 3 has an isValid() function. This function determines wether the user can proceed to the next step.
The next button at the bottom of the pasted html should be disabed if ALL ? isValid() functions are false...
Thats my question but the same time that seems not correct to me.
I guess I am not doing the Wizard correctly...
Can someone please guide me how I should proceed with the architecture that the bottom next button is disabled when the current step isValid function returns false, please.
How can I make a connection from the WizardController to any of the WizardController1,2 or 3 ?
Is Firing an event like broadcast a good direction?
<div class="btn-group">
<button class="btn" ng-class="{'btn-primary':isCurrentStep(0)}" ng-click="setCurrentStep(0)">One</button>
<button class="btn" ng-class="{'btn-primary':isCurrentStep(1)}" ng-click="setCurrentStep(1)">Two</button>
<button class="btn" ng-class="{'btn-primary':isCurrentStep(2)}" ng-click="setCurrentStep(2)">Three</button>
</div>
<div ng-switch="getCurrentStep()" ng-animate="'slide'" class="slide-frame">
<div ng-switch-when="one">
<div ng-controller="WizardController1" ng-include src="'../views/customers.create1.html'"></div>
</div>
<div ng-switch-when="two">
<div ng-controller="WizardController2" ng-include src="'../views/customers.create2.html'"></div>
</div>
<div ng-switch-when="three">
<div ng-controller="WizardController3" ng-include src="'../views/customers.create3.html'"></div>
</div>
</div>
<a class="btn" ng-click="handlePrevious()" ng-show="!isFirstStep()">Back</a>
<a class="btn btn-primary" ng-disabled="" ng-click="handleNext(dismiss)">{{getNextLabel()}}</a>
'use strict';
angular.module('myApp').controller('WizardController', function($scope) {
$scope.steps = ['one', 'two', 'three'];
$scope.step = 0;
$scope.wizard = { tacos: 2 };
$scope.isFirstStep = function() {
return $scope.step === 0;
};
$scope.isLastStep = function() {
return $scope.step === ($scope.steps.length - 1);
};
$scope.isCurrentStep = function(step) {
return $scope.step === step;
};
$scope.setCurrentStep = function(step) {
$scope.step = step;
};
$scope.getCurrentStep = function() {
return $scope.steps[$scope.step];
};
$scope.getNextLabel = function() {
return ($scope.isLastStep()) ? 'Submit' : 'Next';
};
$scope.handlePrevious = function() {
$scope.step -= ($scope.isFirstStep()) ? 0 : 1;
};
$scope.handleNext = function(dismiss) {
if($scope.isLastStep()) {
dismiss();
} else {
$scope.step += 1;
}
};
});
durandalJS wizard sample code which could be used to rewrite a wizard for angularJS:
define(['durandal/activator', 'viewmodels/step1', 'viewmodels/step2', 'knockout', 'plugins/dialog', 'durandal/app', 'services/dataservice'],
function (activator, Step1, Step2, ko, dialog, app, service) {
var ctor = function (viewMode, schoolyearId) {
debugger;
if (viewMode === 'edit') {
service.editSchoolyear(schoolyearId);
}
else if (viewMode === 'create') {
service.createSchoolyear();
}
var self = this;
var steps = [new Step1(), new Step2()];
var step = ko.observable(0); // Start with first step
self.activeStep = activator.create();
var stepsLength = steps.length;
this.hasPrevious = ko.computed(function () {
return step() > 0;
});
self.caption = ko.observable();
this.activeStep(steps[step()]);
this.hasNext = ko.computed(function () {
if ((step() === stepsLength - 1) && self.activeStep().isValid()) {
// save
self.caption('save');
return true;
} else if ((step() < stepsLength - 1) && self.activeStep().isValid()) {
self.caption('next');
return true;
}
});
this.isLastStep = function() {
return step() === stepsLength - 1;
}
this.next = function() {
if (this.isLastStep()) {
$.when(service.createTimeTable())
.done(function () {
app.trigger('savedTimeTable', { isSuccess: true });
})
.fail(function () {
app.trigger('savedTimeTable', { isSuccess: false });
});
}
else if (step() < stepsLength) {
step(step() + 1);
self.activeStep(steps[step()]);
}
}
this.previous = function() {
if (step() > 0) {
step(step() - 1);
self.activeStep(steps[step()]);
}
}
}
return ctor;
});

Resources