<commit_before>/*
 * Primary app code
 */

// Global app settings

APP_DATA = null;
APP_EVENTS= {};
APP_UTIL = {
    parseBoolOption: function(val, def) {
        if (val == null) {
            if (def === undefined)
                return true;
            else
                return def == true;
        }

        var str = (val + '').toLowerCase();
        return str == '' || str == 'true' || str == '1' || str == 'yes' || str == 'on';
    },

    isValidBoolOption: function(val) {
        if (val == null)
            return true;

        var t = (val + '').toLowerCase();
        return val == '' || t == '1' || t == 'true' || t == 'on' || t == 'yes' || t == '0' || t == 'false' || t == 'off' || t == 'no';
    },

    parseOptionStrings: function(val, dict, validateCallback) {
        dict = dict || {};
        var lines = val.replace('\r', '\n').split('\n');
        for(var i in lines) {
            var line = lines[i].trim();
            if (line != '' && line[0] != '#') {
                if (line.indexOf('--') == 0) {
                    line = line.substr(2);
                }

                var eqpos = line.indexOf('=');
                var key = line;
                var value = true;
                if (eqpos > 0) {
                    key = line.substr(0, eqpos).trim();
                    value = line.substr(eqpos + 1).trim();
                    if (value == '')
                        value = true;
                }

                if (validateCallback)
                    if (!validateCallback(dict, key, value))
                        return null;

                dict['--' + key] = value;
            }
        }

        return dict;
    },

    fill_form: function(form, data, map, extra) {
        map = map || {};
        data = data || {};

        for(var k in data) {
            var key = k;
            var m = map[key];
            var v = data[k];

            if (m !== false) {
                if (m && typeof(m) == typeof(''))
                    key = m;

                if (m && typeof(m) == typeof(function() {})) {
                    m(data, key, v, extra);
                } else {                    
                    var n = form.find('#' + key);
                    if (n.attr('type') == 'checkbox') {
                        n.attr('checked', APP_UTIL.parseBoolOption(v));
                    } else {
                        n.val(v);
                    }

                    n.change();
                }
            }
        }
    },

    read_form: function(form, map, values, extra) {
        values = values || {};
        map = map || {};

        form.find('select').each(function(i, e) {
            var key = e.id;
            var m = map[e.id];

            if (m !== false) {
                if (m && typeof(m) == typeof(function() {})) {
                    m(values, key, e, extra);
                } else {
                    if (m && typeof(m) == typeof(''))
                        key = m;

                    values[key] = $(e).val();
                }
            }
        });

        form.find('input').each(function(i, e) { 
            var key = e.id;
            var m = map[e.id];

            if (m !== false) {
                if (m && typeof(m) == typeof(function() {})) {
                    m(values, key, e, extra);
                } else {
                    if (m && typeof(m) == typeof(''))
                        key = m;

                if (e.type == 'checkbox')
                    values[key] = $(e).is(':checked');
                else
                    values[key] = $(e).val();
                }
            }
        });

        return values;
    }
};

$(document).ready(function() {

    // Flag as loaded in case we have plugins
    APP_DATA = {
        plugins: {
            backend: {},
            compression: {},
            encryption: {},
            primary: {}

        }
    };

    var PRIVATE_DATA = {};

    $('#main-appname').text(APP_CONFIG.branded_name);

    if ((APP_CONFIG.branded_subtitle || '').length > 0) {
        var subdiv = $('<div id="main-appname-subtitle">');
        subdiv.text(APP_CONFIG.branded_subtitle);
        $('#main-appname').append(subdiv);
        $('#main-appname').addClass('has-subtitle');
    }

    $('.button').button();

    $('#main-list-container > div.main-backup-entry').remove();
    $('#loading-dialog').dialog({modal: true}).show();

    // Register a global function for password strength
    $.passwordStrength = function(password, callback) {
        if (callback == null)
            return;

        var onUpdate = function(res) {
            try { callback(res); }
            catch (e) { }
        };

        try { onUpdate(zxcvbn(password)); }
        catch (e) { 
            // Not loaded, try this:
            $.getScript('/scripts/zxcvbn.js', function() {
                try {
                    onUpdate(zxcvbn(password));
                }
                catch (e) {
                    onUpdate(null);
                }
            });
        }
    };

    var serverWithCallback = function(data, callback, errorhandler, refreshMethod) {
        if (typeof(data) == typeof(''))
            data = { action: data };

        var method = 'GET';
        if (data.HTTP_METHOD) {
            method = data.HTTP_METHOD;
            delete data.HTTP_METHOD;
        }

        $.ajax({
            url: APP_CONFIG.server_url,
            type: method,
            dataType: 'json',
            data: data
        })
        .done(function(data) {
            if (refreshMethod)
                refreshMethod(data, true, null);

            if (callback != null)
                callback(data, true, null);
        })
        .fail(function(data, status) {
            if (refreshMethod)
                refreshMethod(data, false, data.statusText);

            if (errorhandler)
                errorhandler(data, false, data.statusText);
        });
    };

    PRIVATE_DATA.server_state = {
        polling: false,
        eventId: -1,
        state: null,
        failed: false,
        dataEventId: -1,

        retryTimer: null,
        pauseUpdateTimer: null,
        activeTask: null,
        scheduled: []
    };

    PRIVATE_DATA.progress_state_text = {
        'Backup_Begin': 'Starting ...',
        'Backup_PreBackupVerify': 'Verifying backend data ...',
        'Backup_PostBackupTest': 'Verifying remote data ...',
        'Backup_PreviousBackupFinalize': 'Completing previous backup ...',
        'Backup_ProcessingFiles': null,
        'Backup_Finalize': 'Completing backup ...',
        'Backup_WaitForUpload': 'Waiting for upload ...',
        'Backup_Delete': 'Deleting unwanted files ...',
        'Backup_Compact': 'Compacting remote data ...',
        'Backup_VerificationUpload': 'Verifying upload ...',
        'Backup_PostBackupVerify': 'Verifying backend data ...',
        'Backup_Complete': 'Finished!',
        'Restore_Begin': 'Starting ...',
        'Restore_RecreateDatabase': 'Rebuilding local database ...',
        'Restore_PreRestoreVerify': 'Verifying remote data ...',
        'Restore_CreateFileList': 'Building list of files to restore ...',
        'Restore_CreateTargetFolders': 'Creating target folders ...',
        'Restore_ScanForExistingFiles': 'Scanning existing files ...',
        'Restore_ScanForLocalBlocks': 'Scanning for local blocks ...',
        'Restore_PatchWithLocalBlocks': 'Patching files with local blocks ...',
        'Restore_DownloadingRemoteFiles': 'Downloading files ...',
        'Restore_PostRestoreVerify': 'Verifying restored files ...',
        'Restore_Complete': 'Finished!',
        'Error': 'Error!'
    };

    PRIVATE_DATA.update_progress_and_schedules = function() {
        var scheduledMap = {};
        var backupMap = {};
        var state = PRIVATE_DATA.server_state;
        var current = state.activeTask == null ? false : 'backup-' + state.activeTask;

        for(var n in state.scheduled)
            scheduledMap['backup-' + state.scheduled[n]] = n + 1;

        for(var n in PRIVATE_DATA.backup_list)
            backupMap['backup-' + PRIVATE_DATA.backup_list[n].Backup.ID] = PRIVATE_DATA.backup_list[n];

        $('#main-list').find('.main-backup-entry').each(function(i, e) {
            var el = $(e);
            if (scheduledMap[e.id]) {
                el.find('.backup-progress-overall').css('width', '0px');
                el.find('.main-progress-text').removeClass('in-progress').text('#' + parseInt(scheduledMap[e.id]) + ' in queue');
                el.find('.backup-state-icon').addClass('main-icon-hourglass').removeClass('main-icon-clock');
            } else if (e.id == current) {
                var txt = 'Running ...';
                var pg = 0;
                if (PRIVATE_DATA.server_progress.lastEvent != null) {
                    var filesleft = PRIVATE_DATA.server_progress.lastEvent.TotalFileCount - PRIVATE_DATA.server_progress.lastEvent.ProcessedFileCount;
                    var sizeleft = PRIVATE_DATA.server_progress.lastEvent.TotalFileSize - PRIVATE_DATA.server_progress.lastEvent.ProcessedFileSize;
                    pg = PRIVATE_DATA.server_progress.lastEvent.ProcessedFileSize / PRIVATE_DATA.server_progress.lastEvent.TotalFileSize;

                    if (PRIVATE_DATA.server_progress.lastEvent.Phase == 'Backup_ProcessingFiles') {
                        el.find('.backup-progress-overall').removeClass('backup-progress-indeterminate');
                        txt = filesleft + ' files remaining';
                        
                        if (PRIVATE_DATA.server_progress.lastEvent.ProcessedFileCount == 0)
                            pg = 0;

                        if (PRIVATE_DATA.server_progress.lastEvent.StillCounting)<commit_msg>Quick-fix to prevent the progess bar from jumping to full when there are no changes<commit_after>/*
 * Primary app code
 */

// Global app settings

APP_DATA = null;
APP_EVENTS= {};
APP_UTIL = {
    parseBoolOption: function(val, def) {
        if (val == null) {
            if (def === undefined)
                return true;
            else
                return def == true;
        }

        var str = (val + '').toLowerCase();
        return str == '' || str == 'true' || str == '1' || str == 'yes' || str == 'on';
    },

    isValidBoolOption: function(val) {
        if (val == null)
            return true;

        var t = (val + '').toLowerCase();
        return val == '' || t == '1' || t == 'true' || t == 'on' || t == 'yes' || t == '0' || t == 'false' || t == 'off' || t == 'no';
    },

    parseOptionStrings: function(val, dict, validateCallback) {
        dict = dict || {};
        var lines = val.replace('\r', '\n').split('\n');
        for(var i in lines) {
            var line = lines[i].trim();
            if (line != '' && line[0] != '#') {
                if (line.indexOf('--') == 0) {
                    line = line.substr(2);
                }

                var eqpos = line.indexOf('=');
                var key = line;
                var value = true;
                if (eqpos > 0) {
                    key = line.substr(0, eqpos).trim();
                    value = line.substr(eqpos + 1).trim();
                    if (value == '')
                        value = true;
                }

                if (validateCallback)
                    if (!validateCallback(dict, key, value))
                        return null;

                dict['--' + key] = value;
            }
        }

        return dict;
    },

    fill_form: function(form, data, map, extra) {
        map = map || {};
        data = data || {};

        for(var k in data) {
            var key = k;
            var m = map[key];
            var v = data[k];

            if (m !== false) {
                if (m && typeof(m) == typeof(''))
                    key = m;

                if (m && typeof(m) == typeof(function() {})) {
                    m(data, key, v, extra);
                } else {                    
                    var n = form.find('#' + key);
                    if (n.attr('type') == 'checkbox') {
                        n.attr('checked', APP_UTIL.parseBoolOption(v));
                    } else {
                        n.val(v);
                    }

                    n.change();
                }
            }
        }
    },

    read_form: function(form, map, values, extra) {
        values = values || {};
        map = map || {};

        form.find('select').each(function(i, e) {
            var key = e.id;
            var m = map[e.id];

            if (m !== false) {
                if (m && typeof(m) == typeof(function() {})) {
                    m(values, key, e, extra);
                } else {
                    if (m && typeof(m) == typeof(''))
                        key = m;

                    values[key] = $(e).val();
                }
            }
        });

        form.find('input').each(function(i, e) { 
            var key = e.id;
            var m = map[e.id];

            if (m !== false) {
                if (m && typeof(m) == typeof(function() {})) {
                    m(values, key, e, extra);
                } else {
                    if (m && typeof(m) == typeof(''))
                        key = m;

                if (e.type == 'checkbox')
                    values[key] = $(e).is(':checked');
                else
                    values[key] = $(e).val();
                }
            }
        });

        return values;
    }
};

$(document).ready(function() {

    // Flag as loaded in case we have plugins
    APP_DATA = {
        plugins: {
            backend: {},
            compression: {},
            encryption: {},
            primary: {}

        }
    };

    var PRIVATE_DATA = {};

    $('#main-appname').text(APP_CONFIG.branded_name);

    if ((APP_CONFIG.branded_subtitle || '').length > 0) {
        var subdiv = $('<div id="main-appname-subtitle">');
        subdiv.text(APP_CONFIG.branded_subtitle);
        $('#main-appname').append(subdiv);
        $('#main-appname').addClass('has-subtitle');
    }

    $('.button').button();

    $('#main-list-container > div.main-backup-entry').remove();
    $('#loading-dialog').dialog({modal: true}).show();

    // Register a global function for password strength
    $.passwordStrength = function(password, callback) {
        if (callback == null)
            return;

        var onUpdate = function(res) {
            try { callback(res); }
            catch (e) { }
        };

        try { onUpdate(zxcvbn(password)); }
        catch (e) { 
            // Not loaded, try this:
            $.getScript('/scripts/zxcvbn.js', function() {
                try {
                    onUpdate(zxcvbn(password));
                }
                catch (e) {
                    onUpdate(null);
                }
            });
        }
    };

    var serverWithCallback = function(data, callback, errorhandler, refreshMethod) {
        if (typeof(data) == typeof(''))
            data = { action: data };

        var method = 'GET';
        if (data.HTTP_METHOD) {
            method = data.HTTP_METHOD;
            delete data.HTTP_METHOD;
        }

        $.ajax({
            url: APP_CONFIG.server_url,
            type: method,
            dataType: 'json',
            data: data
        })
        .done(function(data) {
            if (refreshMethod)
                refreshMethod(data, true, null);

            if (callback != null)
                callback(data, true, null);
        })
        .fail(function(data, status) {
            if (refreshMethod)
                refreshMethod(data, false, data.statusText);

            if (errorhandler)
                errorhandler(data, false, data.statusText);
        });
    };

    PRIVATE_DATA.server_state = {
        polling: false,
        eventId: -1,
        state: null,
        failed: false,
        dataEventId: -1,

        retryTimer: null,
        pauseUpdateTimer: null,
        activeTask: null,
        scheduled: []
    };

    PRIVATE_DATA.progress_state_text = {
        'Backup_Begin': 'Starting ...',
        'Backup_PreBackupVerify': 'Verifying backend data ...',
        'Backup_PostBackupTest': 'Verifying remote data ...',
        'Backup_PreviousBackupFinalize': 'Completing previous backup ...',
        'Backup_ProcessingFiles': null,
        'Backup_Finalize': 'Completing backup ...',
        'Backup_WaitForUpload': 'Waiting for upload ...',
        'Backup_Delete': 'Deleting unwanted files ...',
        'Backup_Compact': 'Compacting remote data ...',
        'Backup_VerificationUpload': 'Verifying upload ...',
        'Backup_PostBackupVerify': 'Verifying backend data ...',
        'Backup_Complete': 'Finished!',
        'Restore_Begin': 'Starting ...',
        'Restore_RecreateDatabase': 'Rebuilding local database ...',
        'Restore_PreRestoreVerify': 'Verifying remote data ...',
        'Restore_CreateFileList': 'Building list of files to restore ...',
        'Restore_CreateTargetFolders': 'Creating target folders ...',
        'Restore_ScanForExistingFiles': 'Scanning existing files ...',
        'Restore_ScanForLocalBlocks': 'Scanning for local blocks ...',
        'Restore_PatchWithLocalBlocks': 'Patching files with local blocks ...',
        'Restore_DownloadingRemoteFiles': 'Downloading files ...',
        'Restore_PostRestoreVerify': 'Verifying restored files ...',
        'Restore_Complete': 'Finished!',
        'Error': 'Error!'
    };

    PRIVATE_DATA.update_progress_and_schedules = function() {
        var scheduledMap = {};
        var backupMap = {};
        var state = PRIVATE_DATA.server_state;
        var current = state.activeTask == null ? false : 'backup-' + state.activeTask;

        for(var n in state.scheduled)
            scheduledMap['backup-' + state.scheduled[n]] = n + 1;

        for(var n in PRIVATE_DATA.backup_list)
            backupMap['backup-' + PRIVATE_DATA.backup_list[n].Backup.ID] = PRIVATE_DATA.backup_list[n];

        $('#main-list').find('.main-backup-entry').each(function(i, e) {
            var el = $(e);
            if (scheduledMap[e.id]) {
                el.find('.backup-progress-overall').css('width', '0px');
                el.find('.main-progress-text').removeClass('in-progress').text('#' + parseInt(scheduledMap[e.id]) + ' in queue');
                el.find('.backup-state-icon').addClass('main-icon-hourglass').removeClass('main-icon-clock');
            } else if (e.id == current) {
                var txt = 'Running ...';
                var pg = 0;
                if (PRIVATE_DATA.server_progress.lastEvent != null) {
                    var filesleft = PRIVATE_DATA.server_progress.lastEvent.TotalFileCount - PRIVATE_DATA.server_progress.lastEvent.ProcessedFileCount;
                    var sizeleft = PRIVATE_DATA.server_progress.lastEvent.TotalFileSize - PRIVATE_DATA.server_progress.lastEvent.ProcessedFileSize;
                    pg = PRIVATE_DATA.server_progress.lastEvent.ProcessedFileSize / PRIVATE_DATA.server_progress.lastEvent.TotalFileSize;

                    if (PRIVATE_DATA.server_progress.lastEvent.Phase == 'Backup_ProcessingFiles') {
                        el.find('.backup-progress-overall').removeClass('backup-progress-indeterminate');
                        txt = filesleft + ' files remaining';
                        
                        if (PRIVATE_DATA.server_progress.lastEvent.ProcessedFileCount == 0)
                            pg = 0;
                        else if (pg == 1)
                            pg = 0.95;

                        if (PRIVATE_DATA.server_progress.lastEvent.StillCounting)
{'fraction_non_alphanumeric': 0.1456020278833967, 'fraction_numerical': 0.001926489226869455, 'mean_word_length': 1.5074361255878987, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1545070', 'n_tokens_mistral': 5623, 'n_tokens_neox': 5380, 'n_words': 1155}