Search code examples
iphoneprogress-bartitaniumxmlhttprequestappcelerator-mobile

Multiple Titanium progress bars in a table view for simultaneous uploads?


I am trying to display the progress of multiple xhr sends in a table view. This is my first shot at a table view (which also is not scrolling for some reason), and I can't figure out the appropriate way to connect the bars to the onsendstream. I appreciate any comments on the rest of my code as well.

my window function


Solution

  • I don't claim that multiple simultaneous XHRs are stable, but it is working for me in the simulator. This question was more about the specific UI task whether or not the XHRs are asynchronously queued, but I appreciate any feedback about code quality or best practices. Here is the solution that I arrived at.

    // a namespace for the UI code
    myApp.ui = {};
    
    // a function for this window
    myApp.ui.createCameraWindow = function() {
        var win = Ti.UI.createWindow({
            // I have my own custom header
            title:'',
        });
    
        var containerView = Ti.UI.createView({
            backgroundColor:'#85AAD7',
        });
    
        var tableQueue = Ti.UI.createTableView({
            backgroundColor:'#85AAD7',
            separatorColor:'#85AAD7',
            data:photosQueue, // photosQueue is an empty global array
            width:320
        });
    
        containerView.add(tableQueue);
    
        // device stores the candidate file on the system and sends data
        Ti.App.addEventListener('photoReady',function(candidate) {
            // here we an add a caption if we please
            var captionView = Ti.UI.createView({
                backgroundColor:'#FFF'
            });
    
            var candidateIMG = Ti.UI.createImageView({
                // the candidate file was stored with a uniqie identifier called fileStamp
                // don't forget to change resourcesDirectory to tempDirectory for use on the device
                image:Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory,candidate.fileStamp + '-thumb320.png'),
                height:367,
                width:320,
                top:0,
                opacity:0.5
            });
    
            var captionLabel = Ti.UI.createLabel({
                text:'caption',
                color:'#000',
                top:-180,
                textAlign:'center',
                font:{fontSize:50,fontWeight:'bold',fontStyle:'italic',fontFamily:'Cochin'},
                opacity:0.5
            });
    
            var captionBox = Ti.UI.createTextField({
                height:35,
                width:270,
                textAlign:'center',
                borderStyle:Titanium.UI.INPUT_BORDERSTYLE_ROUNDED
            });
    
            var submitButton = Ti.UI.createButton({
                title:'Submit',
                color:'#000',
                selectedColor:'#FFF',
                top:220,
                width:130,
                height:35
            });
    
            captionView.add(candidateIMG);
            captionView.add(captionLabel);
            captionView.add(captionBox);
            captionView.add(submitButton);
    
            // cover the table view with the temporary caption prompt
            containerView.add(captionView);
    
            submitButton.addEventListener('click',function(){
                candidate.caption = captionBox.value;
                // start the xhr send from another function
                myApp.remote.createPhoto(candidate);
                // go back to the table view
                containerView.remove(captionView);
    
                var tempFile = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory,candidate.fileStamp + '-thumb75.png');
    
                var progressBar = Ti.UI.createProgressBar({
                    width:205,
                    height:50,
                    right:20,
                    min:0,
                    max:1,
                    value:0,
                    style:Titanium.UI.iPhone.ProgressBarStyle.PLAIN,
                    color:'#FFF'
                });
    
                var thisRow = Ti.UI.createTableViewRow({
                    backgroundColor:'#FFF',
                    layout:"vertical",
                    height:75,
                    fileStamp:candidate.fileStamp
                });
    
                // apparently the progress bar needs to be inside a view to align correctly
                var nestedView = Ti.UI.createView({
                    height:75,
                    width:320
                });
    
                var tinyThumb = Ti.UI.createImageView({
                    image:tempFile,
                    height:75,
                    width:75,
                    left:0
                });
    
                nestedView.add(tinyThumb);
                progressBar.show();
                nestedView.add(progressBar);
                thisRow.add(nestedView);
                photosQueue.push(thisRow);
                tableQueue.setData(photosQueue);
            });
        });
    
        // the xhr.onsendstream will repeatedly fire this function and send an object containing an id and e.progress
        Ti.App.addEventListener('streamProgress',function(upload) {
            // loop through the global queue
            for (i=0;i<photosQueue.length;i++) {
                // find the the array object that corresponds to the upload object
                if (photosQueue[i].fileStamp == upload.id) {
                    // identifiy this object as the tableRow in the UI
                    thisRow = photosQueue[i];
                    // find its progress bar by knowing the view hierarchy
                    var bar = thisRow.children[0].children[1];
                    // update the progress bar's value
                    bar.value = upload.progress;
                    // update the entire tableView with new data
                    tableQueue.setData(photosQueue);
                }
            }
        });
    
        // the xhr.onload will fire this function and send an object containing an id and a status code
        Ti.App.addEventListener('confirmation',function(upload) {
            // loop through the global queue
            for (i=0;i<photosQueue.length;i++) {
                // find the the array object that corresponds to the upload object
                if (photosQueue[i].fileStamp == upload.id) {
                    // identifiy this object as the tableRow in the UI
                    thisRow = photosQueue[i];
                    // if the POST was successful
                    if (upload.status == '201') {
                        // then make the entire row pleasing
                        thisRow.backgroundColor = 'green';
                    } else {
                        // otherwise make it ugly
                        thisRow.backgroundColor = 'red';
                    }
                    // identify the full progress bar in the view hierarchy
                    var bar = thisRow.children[0].children[1];
                    // remove it regardless
                    thisRow.children[0].remove(bar);
                    // update the entire tableView with new data
                    tableQueue.setData(photosQueue);
                }
            }
        });
    
        win.add(containerView);
    
        return win;
    };