<commit_before>'use strict';
var Promise = require('bluebird');
var models = require('../../models');
var _ = require('lodash');
var security = require('../../core/utils/security');

var proto = module.exports = function (){
  function AppManager() {

  }
  AppManager.__proto__ = proto;
  return AppManager;
};

proto.findAppByName = function (uid, appName) {
  return models.Apps.findOne({where: {name: appName, uid: uid}});
};

proto.addApp = function (uid, appName, identical) {
  return models.sequelize.transaction(function (t) {
    return models.Apps.create({
      name: appName,
      uid: uid
    },{
      transaction: t
    })
    .then(function (apps) {
      var appId = apps.id;
      var deployments = [];
      var deploymentKey = security.randToken(28) + identical;
      deployments.push({
        appid: appId,
        name: 'Production',
        last_deployment_version_id: 0,
        label_id: 0,
        deployment_key: deploymentKey
      });
      deploymentKey = security.randToken(28) + identical;
      deployments.push({
        appid: appId,
        name: 'Staging',
        last_deployment_version_id: 0,
        label_id: 0,
        deployment_key: deploymentKey
      });
      return Promise.all([
        models.Collaborators.create({appid: appId, uid: uid, roles: "Owner"}, {transaction: t}),
        models.Deployments.bulkCreate(deployments, {transaction: t})
      ]);
    });
  });
};

proto.deleteApp = function (appId) {
  return models.sequelize.transaction(function (t) {
    return Promise.all([
      models.Apps.destroy({where: {id: appId}, transaction: t}),
      models.Collaborators.destroy({where: {appid: appId}, transaction: t}),
      models.Deployments.destroy({where: {appid: appId}, transaction: t})
    ]);
  });
};

proto.modifyApp = function (appId, params) {
  return models.Apps.update(params, {where: {id:appId}})
  .spread(function (affectedCount, affectedRows) {
    if (!_.gt(affectedCount, 0)) {
      throw Error('modify errors');
    }
    return affectedCount;
  });
};

proto.transferApp = function (appId, fromUid, toUid) {
  return models.sequelize.transaction(function (t) {
    return Promise.all([
      models.Apps.update({uid: toUid}, {where: {id: appId}, transaction: t}),
      models.Collaborators.destroy({where: {appid: appId, uid: fromUid}, transaction: t}),
      models.Collaborators.destroy({where: {appid: appId, uid: toUid}, transaction: t}),
      models.Collaborators.create({appid: appId, uid: toUid, roles: "Owner"}, {transaction: t})
    ]);
  });
};

proto.listApps = function (uid) {
  return models.Collaborators.findAll({where : {uid: uid}})
  .then(function(data){
    if (_.isEmpty(data)){
      throw new Error('You are not Collaborator in any apps.');
    }else {
      return [data, data.map(function(v){ return v.appid })];
    }
  })
  .spread(function (collaboratorInfos, appids) {
    return models.Apps.findAll({where: {id: {in: appids}}})
    .then(function(appInfos) {
      if (_.isEmpty(appInfos)) {
        throw new Error(`can't find apps info.`);
      }else {
        var appInfos = _.reduce(appInfos, function(result, value, key) {
          result[value.id] = value;
          return result;
        }, {});
        return [collaboratorInfos, appInfos];
      }
    });
  })
  .spread(function (collaboratorInfos, appInfos) {
    var ownerIds = _.map(appInfos, function (v) {
      return v.uid;
    });
    return models.Users.findAll({where: {id: {in: ownerIds}}})
    .then(function (data) {
      var userInfos = _.reduce(data, function(result, value, key) {
        result[value.id] = value;
        return result;
      }, {});
      return userInfos;
    })
    .then(function (userInfos) {
      var rs = Promise.map(_.values(appInfos), function(v){
        var appId = v.get('id');
        var email = userInfos[v.uid] ? userInfos[v.uid].email : req.users.email;
        var isCurrentAccount = false;
        if (_.eq(v.uid, uid)) {
          isCurrentAccount = true;
        }
        return models.Deployments.findAll({where: {appid: appId}})
        .then(function (deploymentInfos) {
          return {
            collaborators: {[email]: {permission: 'Owner', isCurrentAccount: isCurrentAccount}},
            deployments: _.map(deploymentInfos, function (item) {
              return _.get(item, 'name');
            }),
            name: v.name
          };
        });
      });
      return rs;
    })
  });
};
<commit_msg>fix list app;<commit_after>'use strict';
var Promise = require('bluebird');
var models = require('../../models');
var _ = require('lodash');
var security = require('../../core/utils/security');

var proto = module.exports = function (){
  function AppManager() {

  }
  AppManager.__proto__ = proto;
  return AppManager;
};

proto.findAppByName = function (uid, appName) {
  return models.Apps.findOne({where: {name: appName, uid: uid}});
};

proto.addApp = function (uid, appName, identical) {
  return models.sequelize.transaction(function (t) {
    return models.Apps.create({
      name: appName,
      uid: uid
    },{
      transaction: t
    })
    .then(function (apps) {
      var appId = apps.id;
      var deployments = [];
      var deploymentKey = security.randToken(28) + identical;
      deployments.push({
        appid: appId,
        name: 'Production',
        last_deployment_version_id: 0,
        label_id: 0,
        deployment_key: deploymentKey
      });
      deploymentKey = security.randToken(28) + identical;
      deployments.push({
        appid: appId,
        name: 'Staging',
        last_deployment_version_id: 0,
        label_id: 0,
        deployment_key: deploymentKey
      });
      return Promise.all([
        models.Collaborators.create({appid: appId, uid: uid, roles: "Owner"}, {transaction: t}),
        models.Deployments.bulkCreate(deployments, {transaction: t})
      ]);
    });
  });
};

proto.deleteApp = function (appId) {
  return models.sequelize.transaction(function (t) {
    return Promise.all([
      models.Apps.destroy({where: {id: appId}, transaction: t}),
      models.Collaborators.destroy({where: {appid: appId}, transaction: t}),
      models.Deployments.destroy({where: {appid: appId}, transaction: t})
    ]);
  });
};

proto.modifyApp = function (appId, params) {
  return models.Apps.update(params, {where: {id:appId}})
  .spread(function (affectedCount, affectedRows) {
    if (!_.gt(affectedCount, 0)) {
      throw Error('modify errors');
    }
    return affectedCount;
  });
};

proto.transferApp = function (appId, fromUid, toUid) {
  return models.sequelize.transaction(function (t) {
    return Promise.all([
      models.Apps.update({uid: toUid}, {where: {id: appId}, transaction: t}),
      models.Collaborators.destroy({where: {appid: appId, uid: fromUid}, transaction: t}),
      models.Collaborators.destroy({where: {appid: appId, uid: toUid}, transaction: t}),
      models.Collaborators.create({appid: appId, uid: toUid, roles: "Owner"}, {transaction: t})
    ]);
  });
};

proto.listApps = function (uid) {
  let self = this;
  return models.Collaborators.findAll({where : {uid: uid}})
  .then(function(data){
    if (_.isEmpty(data)){
      return [];
    } else {
      var appIds = _.map(data, function(v){ return v.appid });
      return models.Apps.findAll({where: {id: {in: appIds}}});
    }
  })
  .then(function (appInfos) {
    var rs = Promise.map(_.values(appInfos), function(v){
      return self.getAppDetailInfo(v, uid)
      .then(function (info) {
        return info;
      });
    });
    return rs;
  });
};

proto.getAppDetailInfo  = function (appInfo, currentUid) {
  var appId = appInfo.get('id');
  return Promise.all([
      models.Deployments.findAll({where: {appid: appId}}),
      models.Collaborators.findAll({where: {appid: appId}}),
  ])
  .spread(function (deploymentInfos, collaboratorInfos) {
    return Promise.props({
      collaborators: Promise.reduce(collaboratorInfos, function (allCol, collaborator) {
        return models.Users.findOne({where: {id: collaborator.get('uid')}})
        .then(function (u) {
          var isCurrentAccount = false;
          if (_.eq(u.get('id'), currentUid)) {
            isCurrentAccount = true;
          }
          allCol[u.get('email')] = {permission: collaborator.get('roles'), isCurrentAccount: isCurrentAccount};
          return allCol;
        });
      }, {}),

      deployments: _.map(deploymentInfos, function (item) {
        return _.get(item, 'name');
      }),

      name: appInfo.get('name')
    });
  });
};
<|endoftext|>


<commit_before>import {
  BaseModel, identifiedBy, field, hasMany,
} from './base';
import { find, startsWith } from 'lodash';
import { action, computed, observable } from 'mobx';
import UiSettings from 'shared/src/model/ui-settings';
import Courses from './courses-map';
import { UserTerms } from './user/terms';
import Annotations from './annotations';
import lazyGetter from '../helpers/lazy-getter';
import ViewedTourStat from './user/viewed-tour-stat';
import DOM from '../helpers/dom';

@identifiedBy('user')
export class User extends BaseModel {

  @action.bound
  bootstrap(data) {
    this.update(data);
    this.csrf_token = DOM.read_csrf();
  }

  @observable csrf_token;

  @field account_uuid;

  @field name;
  @field self_reported_role;
  @field account_uuid;

  @field faculty_status;
  @field profile_url;

  @field is_admin;
  @field is_content_analyst;
  @field is_customer_service;
  @field terms_signatures_needed;

  @hasMany({ model: ViewedTourStat }) viewed_tour_stats;

  @computed get firstName() {
    return this.first_name || this.name ? this.name.replace(/ .*/, '') : '';
  }

  @computed get canAnnotate() {
    return !!find(Courses.nonPreview.active.array, { canAnnotate: true });
  }

  @computed get hasPreviewed() {
    return Courses.teaching.preview.isEmpty || Courses.teaching.preview.isViewed.any;
  }

  @computed get shouldPreview() {
    const exploreViewStats = this.viewed_tour_stats.find((stat) => stat.id === 'explore-a-preview');
    if (exploreViewStats) {
      return exploreViewStats.view_count < 4;
    }
    return true;
  }

  @lazyGetter annotations = new Annotations();

  @action removeCourse(course) {
    return Courses.delete(course.id);
  }

  @action refreshCourses() {
    return Courses.fetch();
  }

  @computed get isConfirmedFaculty() {
    return this.faculty_status === 'confirmed_faculty';
  }

  @computed get isProbablyTeacher() {
    return Boolean(this.isConfirmedFaculty || this.self_reported_role === 'instructor' || Courses.teaching.any);
  }

  @computed get terms() {
    return this.terms_signatures_needed ? new UserTerms({ user: this }) : null;
  }

  @computed get unsignedTerms() {
    return this.terms ? this.terms.unsigned : [];
  }

  @computed get tourAudienceTags() {
    let tags = [];
    if (
      (Courses.active.isEmpty && this.isConfirmedFaculty) ||
      Courses.active.teaching.nonPreview.any
    ) {
      tags.push('teacher');
    } else if (Courses.active.teaching.any) {
      tags.push('teacher-preview');
    }

    if (
      Courses.active.teaching.any &&
      this.hasPreviewed &&
      Courses.active.teaching.nonPreview.isEmpty
    ) {
      // Teacher has previewed a course but has no active real course.
      // This means the teacher needs a reminder about how to create a course.
      tags.push('teacher-need-real');
    } else if (find(tags, tag => startsWith(tag, 'teacher'))) {
      if (this.shouldPreview && !this.hasPreviewed) {
        // Otherwise, the teacher may need to preview a course
        tags.push('teacher-not-previewed');
      }
    }

    return tags;
  }

  resetTours() {
    this.viewed_tour_stats.clear();
  }

  replayTour(tour) {
    this.viewed_tour_stats.remove(find(this.viewed_tour_stats, { id: tour.id }));
  }

  viewedTour(tour, options) {
    let stats = this.viewed_tour_stats.find((stat) => stat.id === tour.id);

    if (stats) {
      stats.view_count ++;
    } else {
      stats = new ViewedTourStat({ id: tour.id });
      this.viewed_tour_stats.push(stats);
    }

    this.saveTourView(tour, options);
  }

  verifiedRoleForCourse(course) {
    return course.primaryRole && this.isConfirmedFaculty ? course.primaryRole.type : 'student';
  }

  saveTourView(tour, options) {
    return { data: options };
  }

  @computed get isUnverifiedInstructor() {
    return !this.isConfirmedFaculty && this.self_reported_role === 'instructor';
  }

  recordSessionStart() {
    UiSettings.set('sessionCount', this.sessionCount + 1);
  }

  get sessionCount() {
    return UiSettings.get('sessionCount') || 0;
  }

  logEvent({ category, code, data }) {
    // students do not track events
    if (this.self_reported_role === 'student') { return 'ABORT'; }
    return { category, code, data };
  }

}

const currentUser = new User;

export default currentUser;
<commit_msg>created courses do not need to be active to bypass create course tour<commit_after>import {
  BaseModel, identifiedBy, field, hasMany,
} from './base';
import { find, startsWith } from 'lodash';
import { action, computed, observable } from 'mobx';
import UiSettings from 'shared/src/model/ui-settings';
import Courses from './courses-map';
import { UserTerms } from './user/terms';
import Annotations from './annotations';
import lazyGetter from '../helpers/lazy-getter';
import ViewedTourStat from './user/viewed-tour-stat';
import DOM from '../helpers/dom';

@identifiedBy('user')
export class User extends BaseModel {

  @action.bound
  bootstrap(data) {
    this.update(data);
    this.csrf_token = DOM.read_csrf();
  }

  @observable csrf_token;

  @field account_uuid;

  @field name;
  @field self_reported_role;
  @field account_uuid;

  @field faculty_status;
  @field profile_url;

  @field is_admin;
  @field is_content_analyst;
  @field is_customer_service;
  @field terms_signatures_needed;

  @hasMany({ model: ViewedTourStat }) viewed_tour_stats;

  @computed get firstName() {
    return this.first_name || this.name ? this.name.replace(/ .*/, '') : '';
  }

  @computed get canAnnotate() {
    return !!find(Courses.nonPreview.active.array, { canAnnotate: true });
  }

  @computed get hasPreviewed() {
    return Courses.teaching.preview.isEmpty || Courses.teaching.preview.isViewed.any;
  }

  @computed get shouldPreview() {
    const exploreViewStats = this.viewed_tour_stats.find((stat) => stat.id === 'explore-a-preview');
    if (exploreViewStats) {
      return exploreViewStats.view_count < 4;
    }
    return true;
  }

  @lazyGetter annotations = new Annotations();

  @action removeCourse(course) {
    return Courses.delete(course.id);
  }

  @action refreshCourses() {
    return Courses.fetch();
  }

  @computed get isConfirmedFaculty() {
    return this.faculty_status === 'confirmed_faculty';
  }

  @computed get isProbablyTeacher() {
    return Boolean(this.isConfirmedFaculty || this.self_reported_role === 'instructor' || Courses.teaching.any);
  }

  @computed get terms() {
    return this.terms_signatures_needed ? new UserTerms({ user: this }) : null;
  }

  @computed get unsignedTerms() {
    return this.terms ? this.terms.unsigned : [];
  }

  @computed get tourAudienceTags() {
    let tags = [];
    if (
      (Courses.active.isEmpty && this.isConfirmedFaculty) ||
      Courses.active.teaching.nonPreview.any
    ) {
      tags.push('teacher');
    } else if (Courses.active.teaching.any) {
      tags.push('teacher-preview');
    }

    if (
      Courses.teaching.any &&
      this.hasPreviewed &&
      Courses.teaching.nonPreview.isEmpty
    ) {
      // Teacher has previewed a course but has no active real course.
      // This means the teacher needs a reminder about how to create a course.
      tags.push('teacher-need-real');
    } else if (find(tags, tag => startsWith(tag, 'teacher'))) {
      if (this.shouldPreview && !this.hasPreviewed) {
        // Otherwise, the teacher may need to preview a course
        tags.push('teacher-not-previewed');
      }
    }

    return tags;
  }

  resetTours() {
    this.viewed_tour_stats.clear();
  }

  replayTour(tour) {
    this.viewed_tour_stats.remove(find(this.viewed_tour_stats, { id: tour.id }));
  }

  viewedTour(tour, options) {
    let stats = this.viewed_tour_stats.find((stat) => stat.id === tour.id);

    if (stats) {
      stats.view_count ++;
    } else {
      stats = new ViewedTourStat({ id: tour.id });
      this.viewed_tour_stats.push(stats);
    }

    this.saveTourView(tour, options);
  }

  verifiedRoleForCourse(course) {
    return course.primaryRole && this.isConfirmedFaculty ? course.primaryRole.type : 'student';
  }

  saveTourView(tour, options) {
    return { data: options };
  }

  @computed get isUnverifiedInstructor() {
    return !this.isConfirmedFaculty && this.self_reported_role === 'instructor';
  }

  recordSessionStart() {
    UiSettings.set('sessionCount', this.sessionCount + 1);
  }

  get sessionCount() {
    return UiSettings.get('sessionCount') || 0;
  }

  logEvent({ category, code, data }) {
    // students do not track events
    if (this.self_reported_role === 'student') { return 'ABORT'; }
    return { category, code, data };
  }

}

const currentUser = new User;

export default currentUser;
<|endoftext|>


<commit_before>import * as types from 'constants/action_types'
import lbry from 'lbry'
import lbryio from 'lbryio'
import lbryuri from 'lbryuri'
import rewards from 'rewards'
import {
  selectBalance,
} from 'selectors/wallet'
import {
  selectFileInfoForUri,
  selectUrisDownloading,
} from 'selectors/file_info'
import {
  selectResolvingUris
} from 'selectors/content'
import {
  selectCostInfoForUri,
} from 'selectors/cost_info'
import {
  selectClaimsByUri,
} from 'selectors/claims'
import {
  doOpenModal,
} from 'actions/app'

export function doResolveUri(uri) {
  return function(dispatch, getState) {

    uri = lbryuri.normalize(uri)

    const state = getState()
    const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1

    if (!alreadyResolving) {
      dispatch({
        type: types.RESOLVE_URI_STARTED,
        data: { uri }
      })

      lbry.resolve({ uri }).then((resolutionInfo) => {
        const {
          claim,
          certificate,
        } = resolutionInfo ? resolutionInfo : { claim : null, certificate: null }

        dispatch({
          type: types.RESOLVE_URI_COMPLETED,
          data: {
            uri,
            claim,
            certificate,
          }
        })
      })
    }
  }
}

export function doCancelResolveUri(uri) {
  return function(dispatch, getState) {
    lbry.cancelResolve({ uri })
    dispatch({
      type: types.RESOLVE_URI_CANCELED,
      data: { uri }
    })
  }
}

export function doFetchFeaturedUris() {
  return function(dispatch, getState) {
    const state = getState()

    dispatch({
      type: types.FETCH_FEATURED_CONTENT_STARTED,
    })

    const success = ({ Categories, Uris }) => {

      let featuredUris = {}

      Categories.forEach((category) => {
        if (Uris[category] && Uris[category].length) {
          featuredUris[category] = Uris[category]
        }
      })

      dispatch({
        type: types.FETCH_FEATURED_CONTENT_COMPLETED,
        data: {
          categories: Categories,
          uris: featuredUris,
        }
      })
    }

    const failure = () => {
      dispatch({
        type: types.FETCH_FEATURED_CONTENT_COMPLETED,
        data: {
          categories: [],
          uris: {}
        }
      })
    }

    lbryio.call('discover', 'list', { version: "early-access" } )
      .then(success, failure)
  }
}

export function doUpdateLoadStatus(uri, outpoint) {
  return function(dispatch, getState) {
    const state = getState()

    lbry.file_list({
      outpoint: outpoint,
      full_status: true,
    }).then(([fileInfo]) => {
      if(!fileInfo || fileInfo.written_bytes == 0) {
        // download hasn't started yet
        setTimeout(() => { dispatch(doUpdateLoadStatus(uri, outpoint)) }, 250)
      } else if (fileInfo.completed) {
        // TODO this isn't going to get called if they reload the client before
        // the download finished
        dispatch({
          type: types.DOWNLOADING_COMPLETED,
          data: {
            uri,
            outpoint,
            fileInfo,
          }
        })
      } else {
        // ready to play
        const {
          total_bytes,
          written_bytes,
        } = fileInfo
        const progress = (written_bytes / total_bytes) * 100

        dispatch({
          type: types.DOWNLOADING_PROGRESSED,
          data: {
            uri,
            outpoint,
            fileInfo,
            progress,
          }
        })
        setTimeout(() => { dispatch(doUpdateLoadStatus(uri, outpoint)) }, 250)
      }
    })
  }
}

export function doDownloadFile(uri, streamInfo) {
  return function(dispatch, getState) {
    const state = getState()

    lbry.file_list({ outpoint: streamInfo.outpoint, full_status: true }).then(([fileInfo]) => {
      dispatch({
        type: types.DOWNLOADING_STARTED,
        data: {
          uri,
          outpoint: streamInfo.outpoint,
          fileInfo,
        }
      })
    })

    lbryio.call('file', 'view', {
      uri: uri,
      outpoint: streamInfo.outpoint,
      claimId: streamInfo.claim_id,
    }).catch(() => {})

    rewards.claimEligiblePurchaseRewards()

    dispatch(doUpdateLoadStatus(uri, streamInfo.outpoint))
  }
}

export function doLoadVideo(uri) {
  return function(dispatch, getState) {
    const state = getState()

    dispatch({
      type: types.LOADING_VIDEO_STARTED,
      data: {
        uri
      }
    })

    lbry.get({ uri }).then(streamInfo => {
      const timeout = streamInfo === null ||
        typeof streamInfo !== 'object' ||
        streamInfo.error == 'Timeout'

      if(timeout) {
        dispatch({
          type: types.LOADING_VIDEO_FAILED,
          data: { uri }
        })
        dispatch(doOpenModal('timedOut'))
      } else {
        dispatch(doDownloadFile(uri, streamInfo))
      }
    })
  }
}

export function doPurchaseUri(uri) {
  return function(dispatch, getState) {
    const state = getState()
    const balance = selectBalance(state)
    const fileInfo = selectFileInfoForUri(state, { uri })
    const costInfo = selectCostInfoForUri(state, { uri })
    const downloadingByUri = selectUrisDownloading(state)
    const alreadyDownloading = !!downloadingByUri[uri]
    const { cost } = costInfo

    // BUG if you delete a file from the file system system you're going to be
    // asked to pay for it again. We need to check if the file is in the blobs
    // here and then dispatch doLoadVideo() which will reconstruct it again from
    // the blobs. Or perhaps there's another way to see if a file was already
    // purchased?

    // we already fully downloaded the file. If completed is true but
    // writtenBytes is false then we downloaded it before but deleted it again,
    // which means it needs to be reconstructed from the blobs by dispatching
    // doLoadVideo.
    if (fileInfo && fileInfo.completed && !!fileInfo.writtenBytes) {
      return Promise.resolve()
    }

    // we are already downloading the file
    if (alreadyDownloading) {
      return Promise.resolve()
    }

    // the file is free or we have partially downloaded it
    if (cost <= 0.01 || (fileInfo && fileInfo.download_directory)) {
      dispatch(doLoadVideo(uri))
      return Promise.resolve()
    }

    if (cost > balance) {
      dispatch(doOpenModal('notEnoughCredits'))
    } else {
      dispatch(doOpenModal('affirmPurchase'))
    }

    return Promise.resolve()
  }
}

export function doFetchClaimsByChannel(uri) {
  return function(dispatch, getState) {
    dispatch({
      type: types.FETCH_CHANNEL_CLAIMS_STARTED,
      data: { uri }
    })

    lbry.resolve({ uri }).then((resolutionInfo) => {
      const {
        claims_in_channel,
      } = resolutionInfo ? resolutionInfo : { claims_in_channel: [] }

      dispatch({
        type: types.FETCH_CHANNEL_CLAIMS_COMPLETED,
        data: {
          uri,
          claims: claims_in_channel
        }
      })
    })
  }
}

export function doClaimListMine() {
  return function(dispatch, getState) {
    dispatch({
      type: types.CLAIM_LIST_MINE_STARTED
    })

    lbry.claim_list_mine().then((claims) => {
      dispatch({
        type: types.CLAIM_LIST_MINE_COMPLETED,
        data: {
          claims
        }
      })
    })
  }
}<commit_msg>fix claim id parameter<commit_after>import * as types from 'constants/action_types'
import lbry from 'lbry'
import lbryio from 'lbryio'
import lbryuri from 'lbryuri'
import rewards from 'rewards'
import {
  selectBalance,
} from 'selectors/wallet'
import {
  selectFileInfoForUri,
  selectUrisDownloading,
} from 'selectors/file_info'
import {
  selectResolvingUris
} from 'selectors/content'
import {
  selectCostInfoForUri,
} from 'selectors/cost_info'
import {
  selectClaimsByUri,
} from 'selectors/claims'
import {
  doOpenModal,
} from 'actions/app'

export function doResolveUri(uri) {
  return function(dispatch, getState) {

    uri = lbryuri.normalize(uri)

    const state = getState()
    const alreadyResolving = selectResolvingUris(state).indexOf(uri) !== -1

    if (!alreadyResolving) {
      dispatch({
        type: types.RESOLVE_URI_STARTED,
        data: { uri }
      })

      lbry.resolve({ uri }).then((resolutionInfo) => {
        const {
          claim,
          certificate,
        } = resolutionInfo ? resolutionInfo : { claim : null, certificate: null }

        dispatch({
          type: types.RESOLVE_URI_COMPLETED,
          data: {
            uri,
            claim,
            certificate,
          }
        })
      })
    }
  }
}

export function doCancelResolveUri(uri) {
  return function(dispatch, getState) {
    lbry.cancelResolve({ uri })
    dispatch({
      type: types.RESOLVE_URI_CANCELED,
      data: { uri }
    })
  }
}

export function doFetchFeaturedUris() {
  return function(dispatch, getState) {
    const state = getState()

    dispatch({
      type: types.FETCH_FEATURED_CONTENT_STARTED,
    })

    const success = ({ Categories, Uris }) => {

      let featuredUris = {}

      Categories.forEach((category) => {
        if (Uris[category] && Uris[category].length) {
          featuredUris[category] = Uris[category]
        }
      })

      dispatch({
        type: types.FETCH_FEATURED_CONTENT_COMPLETED,
        data: {
          categories: Categories,
          uris: featuredUris,
        }
      })
    }

    const failure = () => {
      dispatch({
        type: types.FETCH_FEATURED_CONTENT_COMPLETED,
        data: {
          categories: [],
          uris: {}
        }
      })
    }

    lbryio.call('discover', 'list', { version: "early-access" } )
      .then(success, failure)
  }
}

export function doUpdateLoadStatus(uri, outpoint) {
  return function(dispatch, getState) {
    const state = getState()

    lbry.file_list({
      outpoint: outpoint,
      full_status: true,
    }).then(([fileInfo]) => {
      if(!fileInfo || fileInfo.written_bytes == 0) {
        // download hasn't started yet
        setTimeout(() => { dispatch(doUpdateLoadStatus(uri, outpoint)) }, 250)
      } else if (fileInfo.completed) {
        // TODO this isn't going to get called if they reload the client before
        // the download finished
        dispatch({
          type: types.DOWNLOADING_COMPLETED,
          data: {
            uri,
            outpoint,
            fileInfo,
          }
        })
      } else {
        // ready to play
        const {
          total_bytes,
          written_bytes,
        } = fileInfo
        const progress = (written_bytes / total_bytes) * 100

        dispatch({
          type: types.DOWNLOADING_PROGRESSED,
          data: {
            uri,
            outpoint,
            fileInfo,
            progress,
          }
        })
        setTimeout(() => { dispatch(doUpdateLoadStatus(uri, outpoint)) }, 250)
      }
    })
  }
}

export function doDownloadFile(uri, streamInfo) {
  return function(dispatch, getState) {
    const state = getState()

    lbry.file_list({ outpoint: streamInfo.outpoint, full_status: true }).then(([fileInfo]) => {
      dispatch({
        type: types.DOWNLOADING_STARTED,
        data: {
          uri,
          outpoint: streamInfo.outpoint,
          fileInfo,
        }
      })
    })

    lbryio.call('file', 'view', {
      uri: uri,
      outpoint: streamInfo.outpoint,
      claim_id: streamInfo.claim_id,
    }).catch(() => {})

    rewards.claimEligiblePurchaseRewards()

    dispatch(doUpdateLoadStatus(uri, streamInfo.outpoint))
  }
}

export function doLoadVideo(uri) {
  return function(dispatch, getState) {
    const state = getState()

    dispatch({
      type: types.LOADING_VIDEO_STARTED,
      data: {
        uri
      }
    })

    lbry.get({ uri }).then(streamInfo => {
      const timeout = streamInfo === null ||
        typeof streamInfo !== 'object' ||
        streamInfo.error == 'Timeout'

      if(timeout) {
        dispatch({
          type: types.LOADING_VIDEO_FAILED,
          data: { uri }
        })
        dispatch(doOpenModal('timedOut'))
      } else {
        dispatch(doDownloadFile(uri, streamInfo))
      }
    })
  }
}

export function doPurchaseUri(uri) {
  return function(dispatch, getState) {
    const state = getState()
    const balance = selectBalance(state)
    const fileInfo = selectFileInfoForUri(state, { uri })
    const costInfo = selectCostInfoForUri(state, { uri })
    const downloadingByUri = selectUrisDownloading(state)
    const alreadyDownloading = !!downloadingByUri[uri]
    const { cost } = costInfo

    // BUG if you delete a file from the file system system you're going to be
    // asked to pay for it again. We need to check if the file is in the blobs
    // here and then dispatch doLoadVideo() which will reconstruct it again from
    // the blobs. Or perhaps there's another way to see if a file was already
    // purchased?

    // we already fully downloaded the file. If completed is true but
    // writtenBytes is false then we downloaded it before but deleted it again,
    // which means it needs to be reconstructed from the blobs by dispatching
    // doLoadVideo.
    if (fileInfo && fileInfo.completed && !!fileInfo.writtenBytes) {
      return Promise.resolve()
    }

    // we are already downloading the file
    if (alreadyDownloading) {
      return Promise.resolve()
    }

    // the file is free or we have partially downloaded it
    if (cost <= 0.01 || (fileInfo && fileInfo.download_directory)) {
      dispatch(doLoadVideo(uri))
      return Promise.resolve()
    }

    if (cost > balance) {
      dispatch(doOpenModal('notEnoughCredits'))
    } else {
      dispatch(doOpenModal('affirmPurchase'))
    }

    return Promise.resolve()
  }
}

export function doFetchClaimsByChannel(uri) {
  return function(dispatch, getState) {
    dispatch({
      type: types.FETCH_CHANNEL_CLAIMS_STARTED,
      data: { uri }
    })

    lbry.resolve({ uri }).then((resolutionInfo) => {
      const {
        claims_in_channel,
      } = resolutionInfo ? resolutionInfo : { claims_in_channel: [] }

      dispatch({
        type: types.FETCH_CHANNEL_CLAIMS_COMPLETED,
        data: {
          uri,
          claims: claims_in_channel
        }
      })
    })
  }
}

export function doClaimListMine() {
  return function(dispatch, getState) {
    dispatch({
      type: types.CLAIM_LIST_MINE_STARTED
    })

    lbry.claim_list_mine().then((claims) => {
      dispatch({
        type: types.CLAIM_LIST_MINE_COMPLETED,
        data: {
          claims
        }
      })
    })
  }
}<|endoftext|>


<commit_before>'use strict';

import React, {
  Component,
  ListView,
  StyleSheet,
  Text,
  Image,
  RefreshControl,
  TouchableHighlight,
  ActivityIndicatorIOS,
  View,
  NativeAppEventEmitter
} from 'react-native';

var Style = require('./Style.js');
var UserViewController = require('react-native').NativeModules.LDTUserViewController;
var Bridge = require('react-native').NativeModules.LDTReactBridge;
var ReportbackItemView = require('./ReportbackItemView.js');

var UserView = React.createClass({
  getInitialState: function() {
    var getSectionData = (dataBlob, sectionID) => {
      return dataBlob[sectionID];
    }
    var getRowData = (dataBlob, sectionID, rowID) => {
      return dataBlob[sectionID + ':' + rowID];
    }
    return {
      dataSource : new ListView.DataSource({
        getSectionData          : getSectionData,
        getRowData              : getRowData,
        rowHasChanged           : (row1, row2) => row1 !== row2,
        sectionHeaderHasChanged : (s1, s2) => s1 !== s2
      }),
      isRefreshing: false,
      loaded: false,
      error: null,
    };
  },
  componentDidMount: function() {
    if (this.props.isSelfProfile) {
      this.subscription = NativeAppEventEmitter.addListener(
        'currentUserActivity',
        (signup) => this.handleEvent(signup),
      );
    }
    this.fetchData();
  },
  componentWillUnmount: function() {
    if (typeof this.subscription != "undefined") {
      this.subscription.remove();
    }
  },
  handleEvent: function(campaignActivity) {
    this.fetchData();
  },
  fetchData: function() {
    var options = {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Session': this.props.sessionToken,
        'X-DS-REST-API-Key': this.props.apiKey,
      },
    };
    fetch(this.props.url, options)
      .then((response) => response.json())
      .then((responseData) => {
        this.loadSignups(responseData.data);
      })
      .catch((error) => this.catchError(error))
      .done();
  },
  loadSignups: function(signups) {
    var dataBlob = {},
      sectionIDs = [],
      rowIDs = [],
      i;
    sectionIDs.push(0);
    dataBlob[0] = "Actions I'm doing";
    rowIDs[0] = [];
    sectionIDs.push(1);
    dataBlob[1] = "Actions I've done";
    rowIDs[1] = [];
    for (i = 0; i < signups.length; i++) {
      var signup = signups[i];
      var sectionNumber = 0;
      if (signup.reportback) {
        sectionNumber = 1;
        signup.reportbackItem = signup.reportback.reportback_items.data[0];
      }
      else {
        if (!signup.campaign_run.current) {
          continue;
        }
        if (signup.campaign.status != 'active') {
          continue;
        }
        if (signup.campaign.type != 'campaign') {
          continue;
        }
      }
      rowIDs[sectionNumber].push(signup.id);
      dataBlob[sectionNumber + ':' + signup.id] = signup;
    }
    this.setState({
      dataSource : this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs),
      loaded: true,
      error: null,
    });
  },
  _onRefresh: function () {
    this.setState({isRefreshing: true});
    setTimeout(() => {
      this.fetchData();
      this.setState({
        isRefreshing: false,
      });
    }, 1000);
  },
  catchError: function(error) {
    console.log(error);
    this.setState({
      error: error,
    });
  },
  renderLoadingView: function() {
    // @todo DRY LoadingView ReactComponent
    return (
      <View style={styles.loadingContainer}>
        <ActivityIndicatorIOS animating={this.state.animating} style={[{height: 80}]} size="small" />
        <Text style={Style.textBody}>
          Loading profile...
        </Text>
      </View>
    );
  },
  renderError: function() {
    return (
      <View style={styles.loadingContainer}>
        <Text style={Style.textBody}>
          Epic Fail
        </Text>
      </View>
    );
  },
  render: function() {
    if (this.state.error) {
      return this.renderError();
    }
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }
    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderRow}
        renderHeader={this.renderHeader}
        renderSectionHeader = {this.renderSectionHeader}
        refreshControl={
          <RefreshControl
            refreshing={this.state.isRefreshing}
            onRefresh={this._onRefresh}
            tintColor="#ccc"
            colors={['#ff0000', '#00ff00', '#0000ff']}
            progressBackgroundColor="#ffff00"
          />
        }
      />
    );
  },
  renderHeader: function() {
    if (this.props.user.photo.length == 0) {
      this.props.user.photo = 'https://placekitten.com/g/600/600';
    }
    var headerText = null;
    if (this.props.user.country.length > 0) {
      headerText = this.props.user.country.toUpperCase();
    }
    return (
      <View>
        <Image
          style={styles.headerBackgroundImage}
          source={require('image!Gradient Background')}>
          <View style={styles.headerContainer}>
             <Image
               style={styles.avatar}
               source={{uri: this.props.user.photo}}
             />
             <Text style={[Style.textHeading, styles.headerText]}>
               {headerText}
             </Text>
          </View>
        </Image>
      </View>
    );
  },
  renderSectionHeader(sectionData, sectionID) {
    return (
      <View style={Style.sectionHeader}>
        <Text style={Style.sectionHeaderText}>
          {sectionData.toUpperCase()}
        </Text>
      </View>
    );
  },
  renderRow: function(rowData) {
    if (rowData.reportback) {
      return this.renderDoneRow(rowData);
    }
    else {
      return this.renderDoingRow(rowData);
    }
  },
  renderDoingRow: function(signup) {
    return (
      <TouchableHighlight onPress={() => this._onPressRow(signup)}>
        <View style={styles.row}>
          <Text style={[Style.textHeading, Style.textColorCtaBlue]}>
            {signup.campaign.title}
          </Text>
          <Text style={Style.textBody}>
            {signup.campaign.tagline}
          </Text>
        </View>
      </TouchableHighlight>
    );
  },
  renderDoneRow: function(rowData) {
    return (
      <TouchableHighlight onPress={() => this._onPressRow(rowData)}>
        <View>
          <ReportbackItemView
            key={rowData.reportbackItem.id}
            reportbackItem={rowData.reportbackItem}
            reportback={rowData.reportback}
            campaign={rowData.campaign}
            user={this.props.user}
            share={this.props.isSelfProfile}
          />
        </View>
      </TouchableHighlight>
    );
  },
  _onPressRow(rowData) {
    Bridge.pushCampaign(Number(rowData.campaign.id));
  },
});

var styles = React.StyleSheet.create({
  loadingContainer: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#EEE',
  },
  headerContainer: {
    alignItems: 'center',
    flex: 1,
    backgroundColor: 'transparent',
    paddingTop: 20,
  },
  headerBackgroundImage: {
    flex: 1,
    height: 160,
    alignItems: 'stretch',
  },
  avatar: {
    width: 100,
    height: 100,
    borderRadius: 50,
    borderColor: 'white',
    borderWidth: 2,
    alignItems: 'center',
  },
  headerText: {
    color: 'white',
    opacity: 0.50,
    flex: 1,
    textAlign: 'center',
    paddingTop: 4,
  },
  row: {
    backgroundColor: 'white',
    padding: 8,
  },
});

module.exports = UserView;<commit_msg>Adds renderEmptySelfProfile function to call when no rows on SelfProfile<commit_after>'use strict';

import React, {
  Component,
  ListView,
  StyleSheet,
  Text,
  Image,
  RefreshControl,
  TouchableHighlight,
  ActivityIndicatorIOS,
  View,
  NativeAppEventEmitter
} from 'react-native';

var Style = require('./Style.js');
var UserViewController = require('react-native').NativeModules.LDTUserViewController;
var Bridge = require('react-native').NativeModules.LDTReactBridge;
var ReportbackItemView = require('./ReportbackItemView.js');
var firstSectionHeaderText = "Actions I'm Doing";
var secondSectionHeaderText = "Actions I've Done";

var UserView = React.createClass({
  getInitialState: function() {
    var getSectionData = (dataBlob, sectionID) => {
      return dataBlob[sectionID];
    }
    var getRowData = (dataBlob, sectionID, rowID) => {
      return dataBlob[sectionID + ':' + rowID];
    }
    return {
      dataSource : new ListView.DataSource({
        getSectionData          : getSectionData,
        getRowData              : getRowData,
        rowHasChanged           : (row1, row2) => row1 !== row2,
        sectionHeaderHasChanged : (s1, s2) => s1 !== s2
      }),
      isRefreshing: false,
      loaded: false,
      error: null,
    };
  },
  componentDidMount: function() {
    if (this.props.isSelfProfile) {
      this.subscription = NativeAppEventEmitter.addListener(
        'currentUserActivity',
        (signup) => this.handleEvent(signup),
      );
    }
    this.fetchData();
  },
  componentWillUnmount: function() {
    if (typeof this.subscription != "undefined") {
      this.subscription.remove();
    }
  },
  handleEvent: function(campaignActivity) {
    this.fetchData();
  },
  fetchData: function() {
    var options = {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Session': this.props.sessionToken,
        'X-DS-REST-API-Key': this.props.apiKey,
      },
    };
    fetch(this.props.url, options)
      .then((response) => response.json())
      .then((responseData) => {
        this.loadSignups(responseData.data);
      })
      .catch((error) => this.catchError(error))
      .done();
  },
  loadSignups: function(signups) {
    var dataBlob = {},
      sectionIDs = [],
      rowIDs = [],
      i;
    sectionIDs.push(0);
    dataBlob[0] = firstSectionHeaderText;
    rowIDs[0] = [];
    sectionIDs.push(1);
    dataBlob[1] = secondSectionHeaderText;
    rowIDs[1] = [];
    for (i = 0; i < signups.length; i++) {
      var signup = signups[i];
      var sectionNumber = 0;
      if (signup.reportback) {
        sectionNumber = 1;
        signup.reportbackItem = signup.reportback.reportback_items.data[0];
      }
      else {
        if (!signup.campaign_run.current) {
          continue;
        }
        if (signup.campaign.status != 'active') {
          continue;
        }
        if (signup.campaign.type != 'campaign') {
          continue;
        }
      }
      rowIDs[sectionNumber].push(signup.id);
      dataBlob[sectionNumber + ':' + signup.id] = signup;
    }
    this.setState({
      dataSource : this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs),
      loaded: true,
      error: null,
    });
  },
  _onRefresh: function () {
    this.setState({isRefreshing: true});
    setTimeout(() => {
      this.fetchData();
      this.setState({
        isRefreshing: false,
      });
    }, 1000);
  },
  catchError: function(error) {
    console.log(error);
    this.setState({
      error: error,
    });
  },
  renderLoadingView: function() {
    // @todo DRY LoadingView ReactComponent
    return (
      <View style={styles.loadingContainer}>
        <ActivityIndicatorIOS animating={this.state.animating} style={[{height: 80}]} size="small" />
        <Text style={Style.textBody}>
          Loading profile...
        </Text>
      </View>
    );
  },
  renderError: function() {
    return (
      <View style={styles.loadingContainer}>
        <Text style={Style.textBody}>
          Epic Fail
        </Text>
      </View>
    );
  },
  renderEmptySelfProfile: function() {
    return (
      <View>
        {this.renderHeader()}
        <View style={Style.sectionHeader}>
          <Text style={Style.sectionHeaderText}>
            {firstSectionHeaderText.toUpperCase()}
          </Text>
        </View>
        <View style={styles.noActionsContainer}>
          <Text style={Style.textHeading}>
            You haven’t started any actions yet.
          </Text>
          <Text style={[Style.textBody, {paddingTop: 8}]}>
            And you totally should! Shit is happening in the world -- find out how to do something about it.
          </Text>
        </View>
      </View>
    );
  },
  render: function() {
    if (this.state.error) {
      return this.renderError();
    }
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }
    if (this.state.dataSource.getRowCount() == 0 && this.props.isSelfProfile) {
      return this.renderEmptySelfProfile();
    }

    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderRow}
        renderHeader={this.renderHeader}
        renderSectionHeader = {this.renderSectionHeader}
        refreshControl={
          <RefreshControl
            refreshing={this.state.isRefreshing}
            onRefresh={this._onRefresh}
            tintColor="#ccc"
            colors={['#ff0000', '#00ff00', '#0000ff']}
            progressBackgroundColor="#ffff00"
          />
        }
      />
    );
  },
  renderHeader: function() {
    if (this.props.user.photo.length == 0) {
      this.props.user.photo = 'https://placekitten.com/g/600/600';
    }
    var headerText = null;
    if (this.props.user.country.length > 0) {
      headerText = this.props.user.country.toUpperCase();
    }
    return (
      <View>
        <Image
          style={styles.headerBackgroundImage}
          source={require('image!Gradient Background')}>
          <View style={styles.headerContainer}>
             <Image
               style={styles.avatar}
               source={{uri: this.props.user.photo}}
             />
             <Text style={[Style.textHeading, styles.headerText]}>
               {headerText}
             </Text>
          </View>
        </Image>
      </View>
    );
  },
  renderSectionHeader(sectionData, sectionID) {
    return (
      <View style={Style.sectionHeader}>
        <Text style={Style.sectionHeaderText}>
          {sectionData.toUpperCase()}
        </Text>
      </View>
    );
  },
  renderRow: function(rowData) {
    if (rowData.reportback) {
      return this.renderDoneRow(rowData);
    }
    else {
      return this.renderDoingRow(rowData);
    }
  },
  renderDoingRow: function(signup) {
    return (
      <TouchableHighlight onPress={() => this._onPressRow(signup)}>
        <View style={styles.row}>
          <Text style={[Style.textHeading, Style.textColorCtaBlue]}>
            {signup.campaign.title}
          </Text>
          <Text style={Style.textBody}>
            {signup.campaign.tagline}
          </Text>
        </View>
      </TouchableHighlight>
    );
  },
  renderDoneRow: function(rowData) {
    return (
      <TouchableHighlight onPress={() => this._onPressRow(rowData)}>
        <View>
          <ReportbackItemView
            key={rowData.reportbackItem.id}
            reportbackItem={rowData.reportbackItem}
            reportback={rowData.reportback}
            campaign={rowData.campaign}
            user={this.props.user}
            share={this.props.isSelfProfile}
          />
        </View>
      </TouchableHighlight>
    );
  },
  _onPressRow(rowData) {
    Bridge.pushCampaign(Number(rowData.campaign.id));
  },
});

var styles = React.StyleSheet.create({
  loadingContainer: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#EEE',
  },
  noActionsContainer : {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    paddingLeft: 33,
    paddingRight: 33,
    paddingTop: 18,
  },
  headerContainer: {
    alignItems: 'center',
    flex: 1,
    backgroundColor: 'transparent',
    paddingTop: 20,
  },
  headerBackgroundImage: {
    flex: 1,
    height: 160,
    alignItems: 'stretch',
  },
  avatar: {
    width: 100,
    height: 100,
    borderRadius: 50,
    borderColor: 'white',
    borderWidth: 2,
    alignItems: 'center',
  },
  headerText: {
    color: 'white',
    opacity: 0.50,
    flex: 1,
    textAlign: 'center',
    paddingTop: 4,
  },
  row: {
    backgroundColor: 'white',
    padding: 8,
  },
});

module.exports = UserView;<|endoftext|>


<commit_before>$(document).ready(function() {
    //Initialize a loader
    if (window.loader == undefined) {
        window.loader = '

';
    }
    if (window.loaderOverlay == undefined) {
        window.loaderOverlay = '

';
    }
    $loader = $(window.loader);
    $loaderOverlay = $(window.loader);
    $('body').prepend($loader);
    $('body').prepend(loaderOverlay);

    /**
     * The clicked link or button is tagged with data-trigger=true. When a form is submitted,
     * we find the tagged element in case it has some data to submit.
     */
    $(document).on('click', 'form[data-toggle="ajax"] *[type="submit"]', function (event) {
        $(this).parents('form[data-toggle="ajax"]').first().children('*[type="submit"]').each(function () {
            $(this).attr('data-trigger', false);
        });
        $(this).attr('data-trigger', true);
    });

    $(document).trigger('ajax_button_listener_initialized');
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });
});

/**
 * Keep scroll position after replacing content
 */
$(document).ajaxStart(function() {
    scrollTop = $(document).scrollTop();
});

$(document).ajaxSuccess(function() {
    if (typeof scrollTop != 'undefined') {
        $(document).scrollTop(scrollTop);
    }
});

$(document).ajaxComplete(function() {
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });
});
    $(document).on('submit', 'form[data-toggle="ajax"]', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $($loader).fadeIn();
        $($loaderOverlay).fadeIn();
        event.preventDefault();
        $(this).trigger('ajax.form.initialize');
        //Guess what is the target to update
        if ($(this).attr('data-target')) {
            var update = $(this).attr('data-target');
        } else if ($(this).data('update')) {
            console.info('The use of data-update will be deprecated in next version, please use data-target instead.');
            var update = $(this).data('update');
        }
        var updateStrategy = $(this).data('update-strategy') ? $(this).data('update-strategy') : 'html';
        var form = $(this);
        var effect = guessEffect(this, "#" + update);
        ajaxFormSubmit(form, $(form).attr('action'), update, updateStrategy, effect);

        return false;
    }).on('click', 'a[data-toggle="ajax"]', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $($loader).fadeIn();
        $($loaderOverlay).fadeIn();
        event.preventDefault();

        //is the link linked ot a form
        var formSelector = $(this).data('form');

        $(this).trigger('ajax.link.initialize');
        //Guess what is the target to update
        if ($(this).attr('data-target')) {
            var update = $(this).attr('data-target');
        } else if ($(this).data('update')) {
            console.info('The use of data-update will be deprecated in next version, please use data-target instead.');
            var update = $(this).data('update');
        }
        var updateStrategy = $(this).data('update-strategy') ? $(this).data('update-strategy') : 'html';
        var link = $(this).attr('href');
        var effect = guessEffect(this, "#" + update);

        //if there is a form we submit this one with the href of the link
        if (formSelector === undefined) {
            ajaxLink(link, update, updateStrategy);
        } else {
            var form = $(formSelector);
            ajaxFormSubmit(form, link, update, updateStrategy, effect);
        }

        return false;
    });

function ajaxFormSubmit(form, action, update, updateStrategy, effect) {
    $(form).trigger('ajax.ajaxFormSubmit.before');
    var button = $('[type="submit"][data-trigger=true]');
    //grab all form data
    var formData = $(form).serializeArray();
    var formCache = $(form).attr('data-cache') != 'undefined' ? true : false;
    if (button.length) {
        formData.push({ name: button.attr('name'), value: button.attr('value') });
    }
    formData = $.param(formData);
    var contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
    if ($(form).attr('enctype') == 'multipart/form-data') {
        var formData = new FormData($(form)[0]);
        formData.append(button.attr('name'), button.val());
        var contentType = false;
    }

    $.ajax({
        url         : action,
        context     : document.body,
        data        : formData,
        type        : $(form).attr('method'),
        contentType : contentType,
        processData : false,
        async       : true,
        cache       : formCache,
        success     : function(jsonResponse) {
            ajaxify(jsonResponse, update, updateStrategy, effect);
        }
    });

    $(form).trigger('ajax.ajaxFormSubmit.after');
}

function ajaxLink(link,update, updateStrategy, effect) {
    $.ajax({
        url     : link,
        context : document.body,
        type    : "GET",
        success : function(jsonResponse) {
            ajaxify(jsonResponse, update, updateStrategy, effect);
        },
        error: function(jsonResponse) {
            if (typeof toastr === 'undefined') {
                alert("Il semble s'être produit une erreur");
            } else {
                toastr.options = {
                  "positionClass": "toast-bottom-left",
                }
                toastr.error("Il semble s'être produit une erreur");
            }
            $($loader).fadeOut();
            $($loaderOverlay).fadeOut();
        }
    });
}

function ajaxify(jsonResponse, update, updateStrategy, effect) {
    $(document).trigger('ajax.success.before', jsonResponse);

    if (typeof jsonResponse === 'object') {
        handleJson(jsonResponse, update, updateStrategy);
    } else {
        if (effect != undefined && effect != null){
            $("#" + update).hide();
        }
        //By default, the updateStrategy is html (a simple replace) but you can set your own function
        //for example, append, after etc or even a custom one.
        eval('$("#" + update).' + updateStrategy + '(jsonResponse)');

        if (effect != undefined && effect != null){
            eval('$("#" + update).' + effect + '()');
        }
    }

    $($loader).fadeOut();
    $($loaderOverlay).fadeOut();
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });

    $(document).trigger('ajax.success.after', jsonResponse);
}

function handleJson(json, update, updateStrategy, effect) {

    if (json.hasOwnProperty("update")) {
        update = json.update;
    }

    if (effect != undefined && effect != null){
        $("#" + update).hide();
    }

    // check if an ajax callback is given in the response, execute it
    if (json.hasOwnProperty("ajax-callback")) {
        $.post(json.callback,
        {
            params : json.data
        },
        function(data){
            eval('$("#" + update).' + updateStrategy + '(data)');
        });
    }
    // a callback is javascript code
    if (json.hasOwnProperty("callback")) {
        eval(json.callback);
    }
    // html is the html part to be inserted in the "update"
    if (json.hasOwnProperty("html")) {
        eval('$("#" + update).' + updateStrategy + '(json.html)');

        if (effect != undefined && effect != null){
            eval('$("#" + update).'+effect+'()');
        }
    }
    // redirect is an url
    if (json.hasOwnProperty("redirect")) {
        if (window.location == json.redirect) {
            location.reload(true);
        }
        window.location = json.redirect;
    }
}

function guessEffect(link, targetId) {
    var effect = "show";
    if ($(targetId).html() != undefined) {
        if ($(targetId).html() == "") {
            effect = "slideDown";
            if ($(link).attr('data-new-effect') != undefined && $(link).attr('data-new-effect') != "") {
                effect = $(link).attr('data-new-effect');
            } else if ($(targetId).attr('data-new-effect') != undefined && $(targetId).attr('data-new-effect') != "") {
                effect = $(targetId).attr('data-new-effect');
            }
        } else {
            effect = "fadeIn";
            if ($(link).attr('data-update-effect') != undefined && $(link).attr('data-update-effect') != "") {
                effect = $(link).attr('data-update-effect');
            } else if ($(targetId).attr('data-update-effect') != undefined && $(targetId).attr('data-update-effect') != "") {
                effect = $(targetId).attr('data-update-effect');
            }
        }
    } else if ($(link).data('no-effect')) {
        effect = null;
    }

    return effect;
}
<commit_msg>Fix overlay fadeIn/fadeOut<commit_after>$(document).ready(function() {
    //Initialize a loader
    if (window.loader == undefined) {
        window.loader = '

';
    }
    if (window.loaderOverlay == undefined) {
        window.loaderOverlay = '

';
    }

    $wrapper = $('

');
    $loader = $(window.loader);
    $loaderOverlay = $(window.loaderOverlay);
    $wrapper.prepend($loader).prepend(loaderOverlay);
    $('body').prepend($wrapper);

    /**
     * The clicked link or button is tagged with data-trigger=true. When a form is submitted,
     * we find the tagged element in case it has some data to submit.
     */
    $(document).on('click', 'form[data-toggle="ajax"] *[type="submit"]', function (event) {
        $(this).parents('form[data-toggle="ajax"]').first().children('*[type="submit"]').each(function () {
            $(this).attr('data-trigger', false);
        });
        $(this).attr('data-trigger', true);
    });

    $(document).trigger('ajax_button_listener_initialized');
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });
});

/**
 * Keep scroll position after replacing content
 */
$(document).ajaxStart(function() {
    scrollTop = $(document).scrollTop();
});

$(document).ajaxSuccess(function() {
    if (typeof scrollTop != 'undefined') {
        $(document).scrollTop(scrollTop);
    }
});

$(document).ajaxComplete(function() {
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });
});
$(document).on('submit', 'form[data-toggle="ajax"]', function(event) {
    if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
        return false;
    }
    $wrapper.fadeIn();
    event.preventDefault();
    $(this).trigger('ajax.form.initialize');
    //Guess what is the target to update
    if ($(this).attr('data-target')) {
        var update = $(this).attr('data-target');
    } else if ($(this).data('update')) {
        console.info('The use of data-update will be deprecated in next version, please use data-target instead.');
        var update = $(this).data('update');
    }
    var updateStrategy = $(this).data('update-strategy') ? $(this).data('update-strategy') : 'html';
    var form = $(this);
    var effect = guessEffect(this, "#" + update);
    ajaxFormSubmit(form, $(form).attr('action'), update, updateStrategy, effect);

    return false;
}).on('click', 'a[data-toggle="ajax"]', function(event) {
    if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
        return false;
    }
    $wrapper.fadeIn();
    event.preventDefault();

    //is the link linked ot a form
    var formSelector = $(this).data('form');

    $(this).trigger('ajax.link.initialize');
    //Guess what is the target to update
    if ($(this).attr('data-target')) {
        var update = $(this).attr('data-target');
    } else if ($(this).data('update')) {
        console.info('The use of data-update will be deprecated in next version, please use data-target instead.');
        var update = $(this).data('update');
    }
    var updateStrategy = $(this).data('update-strategy') ? $(this).data('update-strategy') : 'html';
    var link = $(this).attr('href');
    var effect = guessEffect(this, "#" + update);

    //if there is a form we submit this one with the href of the link
    if (formSelector === undefined) {
        ajaxLink(link, update, updateStrategy);
    } else {
        var form = $(formSelector);
        ajaxFormSubmit(form, link, update, updateStrategy, effect);
    }

    return false;
});

function ajaxFormSubmit(form, action, update, updateStrategy, effect) {
    $(form).trigger('ajax.ajaxFormSubmit.before');
    var button = $('[type="submit"][data-trigger=true]');
    //grab all form data
    var formData = $(form).serializeArray();
    var formCache = $(form).attr('data-cache') != 'undefined' ? true : false;
    if (button.length) {
        formData.push({ name: button.attr('name'), value: button.attr('value') });
    }
    formData = $.param(formData);
    var contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
    if ($(form).attr('enctype') == 'multipart/form-data') {
        var formData = new FormData($(form)[0]);
        formData.append(button.attr('name'), button.val());
        var contentType = false;
    }

    $.ajax({
        url         : action,
        context     : document.body,
        data        : formData,
        type        : $(form).attr('method'),
        contentType : contentType,
        processData : false,
        async       : true,
        cache       : formCache,
        success     : function(jsonResponse) {
            ajaxify(jsonResponse, update, updateStrategy, effect);
        }
    });

    $(form).trigger('ajax.ajaxFormSubmit.after');
}

function ajaxLink(link,update, updateStrategy, effect) {
    $.ajax({
        url     : link,
        context : document.body,
        type    : "GET",
        success : function(jsonResponse) {
            ajaxify(jsonResponse, update, updateStrategy, effect);
        },
        error: function(jsonResponse) {
            if (typeof toastr === 'undefined') {
                alert("Il semble s'être produit une erreur");
            } else {
                toastr.options = {
                    "positionClass": "toast-bottom-left",
                }
                toastr.error("Il semble s'être produit une erreur");
            }
            $wrapper.fadeOut();
        }
    });
}

function ajaxify(jsonResponse, update, updateStrategy, effect) {
    $(document).trigger('ajax.success.before', jsonResponse);

    if (typeof jsonResponse === 'object') {
        handleJson(jsonResponse, update, updateStrategy);
    } else {
        if (effect != undefined && effect != null){
            $("#" + update).hide();
        }
        //By default, the updateStrategy is html (a simple replace) but you can set your own function
        //for example, append, after etc or even a custom one.
        eval('$("#" + update).' + updateStrategy + '(jsonResponse)');

        if (effect != undefined && effect != null){
            eval('$("#" + update).' + effect + '()');
        }
    }

    $wrapper.fadeOut();
    $('*[data-toggle="ajax"]').each(function() {
        $(this).css({
            'pointer-events' : 'auto',
            'cursor' : 'auto'
        });
    });

    $(document).trigger('ajax.success.after', jsonResponse);
}

function handleJson(json, update, updateStrategy, effect) {

    if (json.hasOwnProperty("update")) {
        update = json.update;
    }

    if (effect != undefined && effect != null){
        $("#" + update).hide();
    }

    // check if an ajax callback is given in the response, execute it
    if (json.hasOwnProperty("ajax-callback")) {
        $.post(json.callback,
            {
                params : json.data
            },
            function(data){
                eval('$("#" + update).' + updateStrategy + '(data)');
            });
    }
    // a callback is javascript code
    if (json.hasOwnProperty("callback")) {
        eval(json.callback);
    }
    // html is the html part to be inserted in the "update"
    if (json.hasOwnProperty("html")) {
        eval('$("#" + update).' + updateStrategy + '(json.html)');

        if (effect != undefined && effect != null){
            eval('$("#" + update).'+effect+'()');
        }
    }
    // redirect is an url
    if (json.hasOwnProperty("redirect")) {
        if (window.location == json.redirect) {
            location.reload(true);
        }
        window.location = json.redirect;
    }
}

function guessEffect(link, targetId) {
    var effect = "show";
    if ($(targetId).html() != undefined) {
        if ($(targetId).html() == "") {
            effect = "slideDown";
            if ($(link).attr('data-new-effect') != undefined && $(link).attr('data-new-effect') != "") {
                effect = $(link).attr('data-new-effect');
            } else if ($(targetId).attr('data-new-effect') != undefined && $(targetId).attr('data-new-effect') != "") {
                effect = $(targetId).attr('data-new-effect');
            }
        } else {
            effect = "fadeIn";
            if ($(link).attr('data-update-effect') != undefined && $(link).attr('data-update-effect') != "") {
                effect = $(link).attr('data-update-effect');
            } else if ($(targetId).attr('data-update-effect') != undefined && $(targetId).attr('data-update-effect') != "") {
                effect = $(targetId).attr('data-update-effect');
            }
        }
    } else if ($(link).data('no-effect')) {
        effect = null;
    }

    return effect;
}
<|endoftext|>


<commit_before>(function ($) {
    "use strict";

    Mapbender.Digitizer.Toolset = function (schema) {

        var toolSet = this;
        toolSet.schema = schema;

        toolSet.buttons = schema.toolset;

        toolSet.controlFactory = new Mapbender.Digitizer.DigitizingControlFactory(schema.widget.map);

        toolSet.element = $("<div />").addClass('digitizing-tool-set').addClass('left');
        toolSet.createToolbar();

        schema.layer.getSource().on(ol.source.VectorEventType.ADDFEATURE, function (event) {
            var feature = event.feature;

            feature.on('Digitizer.ModifyFeature', function (event) {

                if (schema.deactivateControlAfterModification) {
                    toolSet.activeInteraction && schema.menu.toolSet.activeInteraction.setActive(false);
                    toolSet.activeInteraction = null;
                }

                feature.changed();

            });
        });

        $(schema).on("Digitizer.StartFeatureSave",function(event){
            toolSet.activeInteraction.setActive(false);
        });

        $(schema).on("Digitizer.EndFeatureSave",function(event){
            toolSet.activeInteraction.setActive(true);
        });

    };

    Mapbender.Digitizer.Toolset.prototype = {

        createPlainControlButton_: function (rawButton,interaction) {
            var toolSet = this;

            var schema = toolSet.schema;
            var geomType = schema.getGeomType();

            var $button = $("<button class='button' type='button'/>");

            $button.addClass(rawButton.type);

            $button.attr('title', interaction.title || Mapbender.DataManager.Translator.translate('toolset.' + geomType + '.' + rawButton.type));
            // add icon css class
            $button.addClass(interaction.className || "icon-" + rawButton.type.replace(/([A-Z])+/g, '-$1').toLowerCase());

            return $button;
        },

        /**
         * Build Navigation
         *
         */
        createToolbar: function () {
            var toolSet = this;
            var schema = toolSet.schema;
            var element = $(toolSet.element);
            var controlFactory = toolSet.controlFactory;
            var buttons = toolSet.buttons;

            buttons.forEach(function (rawButton) {

                var type = rawButton.type;

                var interaction = controlFactory[type] && controlFactory[type](schema.layer.getSource());
                if (!interaction) {
                    console.warn("interaction " + type + " does not exist");
                    return;
                }

                var $button = toolSet.createPlainControlButton_(rawButton,interaction);

                interaction.setActive(false);

                schema.widget.map.addInteraction(interaction);

                $button.on('click',null,function (e) {

                    if (interaction.getActive()) {
                        interaction.setActive(false);
                        toolSet.activeInteraction = null;
                    } else {
                        toolSet.activeInteraction && toolSet.activeInteraction.setActive(false);
                        interaction.setActive(true);
                        toolSet.activeInteraction = interaction;
                    }

                });

                // Keep activation status of buttons in sync with active control
                interaction.on('controlFactory.Activation', function (event) {
                    if (event.active) {
                        $button.addClass('active');
                        schema.selectControl.setActive(false);
                    } else {
                        $button.removeClass('active');
                        schema.selectControl.setActive(true);
                    }

                });

                element.append($button);
            });
        },

    };

})(jQuery);
<commit_msg>Remove access to always undefined interaction properties<commit_after>(function ($) {
    "use strict";

    Mapbender.Digitizer.Toolset = function (schema) {

        var toolSet = this;
        toolSet.schema = schema;

        toolSet.buttons = schema.toolset;

        toolSet.controlFactory = new Mapbender.Digitizer.DigitizingControlFactory(schema.widget.map);

        toolSet.element = $("<div />").addClass('digitizing-tool-set').addClass('left');
        toolSet.createToolbar();

        schema.layer.getSource().on(ol.source.VectorEventType.ADDFEATURE, function (event) {
            var feature = event.feature;

            feature.on('Digitizer.ModifyFeature', function (event) {

                if (schema.deactivateControlAfterModification) {
                    toolSet.activeInteraction && schema.menu.toolSet.activeInteraction.setActive(false);
                    toolSet.activeInteraction = null;
                }

                feature.changed();

            });
        });

        $(schema).on("Digitizer.StartFeatureSave",function(event){
            toolSet.activeInteraction.setActive(false);
        });

        $(schema).on("Digitizer.EndFeatureSave",function(event){
            toolSet.activeInteraction.setActive(true);
        });

    };

    Mapbender.Digitizer.Toolset.prototype = {

        createPlainControlButton_: function (rawButton,interaction) {
            var toolSet = this;

            var schema = toolSet.schema;
            var geomType = schema.getGeomType();

            var $button = $("<button class='button' type='button'/>");

            $button.addClass(rawButton.type);

            $button.attr('title', Mapbender.DataManager.Translator.translate('toolset.' + geomType + '.' + rawButton.type));
            // add icon css class
            $button.addClass("icon-" + rawButton.type.replace(/([A-Z])+/g, '-$1').toLowerCase());

            return $button;
        },

        /**
         * Build Navigation
         *
         */
        createToolbar: function () {
            var toolSet = this;
            var schema = toolSet.schema;
            var element = $(toolSet.element);
            var controlFactory = toolSet.controlFactory;
            var buttons = toolSet.buttons;

            buttons.forEach(function (rawButton) {

                var type = rawButton.type;

                var interaction = controlFactory[type] && controlFactory[type](schema.layer.getSource());
                if (!interaction) {
                    console.warn("interaction " + type + " does not exist");
                    return;
                }

                var $button = toolSet.createPlainControlButton_(rawButton,interaction);

                interaction.setActive(false);

                schema.widget.map.addInteraction(interaction);

                $button.on('click',null,function (e) {

                    if (interaction.getActive()) {
                        interaction.setActive(false);
                        toolSet.activeInteraction = null;
                    } else {
                        toolSet.activeInteraction && toolSet.activeInteraction.setActive(false);
                        interaction.setActive(true);
                        toolSet.activeInteraction = interaction;
                    }

                });

                // Keep activation status of buttons in sync with active control
                interaction.on('controlFactory.Activation', function (event) {
                    if (event.active) {
                        $button.addClass('active');
                        schema.selectControl.setActive(false);
                    } else {
                        $button.removeClass('active');
                        schema.selectControl.setActive(true);
                    }

                });

                element.append($button);
            });
        },

    };

})(jQuery);
<|endoftext|>


<commit_before>Modules.VERSION = '1.0.0';

this.__defineGetter__('omnisidebar', function() { return window.omnisidebar; });
this.__defineGetter__('leftSidebar', function() { return omnisidebar.leftSidebar; });
this.__defineGetter__('rightSidebar', function() { return omnisidebar.rightSidebar; });

this.osbLateralSidebarOpenListener = function() {
	if(typeof(lateralSidebarOpen) != 'undefined') {
		lateralSidebarOpen();
	}
};

this.osbIsSidebarOpen = function(e) {
	e.stopPropagation();

	var sidebar = (Prefs.lateral_placement == 'left') ? leftSidebar : rightSidebar;
	e.detail = !sidebar.closed && !sidebar.above;
};

// make sure OSB's side switcher triggers the lateral bar
this.osbSetSwitcher = function(sidebar, other, setup) {
	if(typeof(lateralBar) == 'undefined' || !lateralBar || !lateralBar._autohide) { return; }

	// the other (opposite) sidebar should never trigger the lateral bar to show
	if(other.switcher && lateralBar._autohide.indexOf(other.switcher) > -1) {
		autoHideNodeListeners(lateralBar, other.switcher, false);
		lateralBar._autohide.splice(lateralBar._autohide.indexOf(other.switcher), 1);
	}

	if(setup && Prefs.lateral_bar && Prefs.lateral_autohide) {
		if(sidebar.switcher && lateralBar._autohide.indexOf(sidebar.switcher) == -1) {
			autoHideNodeListeners(lateralBar, sidebar.switcher, true);
			lateralBar._autohide.push(sidebar.switcher);
		}
	}
	else {
		if(sidebar.switcher && lateralBar._autohide.indexOf(sidebar.switcher) > -1) {
			autoHideNodeListeners(lateralBar, sidebar.switcher, false);
			lateralBar._autohide.splice(lateralBar._autohide.indexOf(sidebar.switcher), 1);
		}
	}
};

this.osbLoadListener = function(e) {
	if(leftSidebar && leftSidebar.box == e.target) {
		var sidebar = leftSidebar;
		var other = rightSidebar;
		var check = 'left';
	} else {
		var sidebar = rightSidebar;
		var other = leftSidebar;
		var check = 'right';
	}

	if(Prefs.lateral_placement == check) {
		osbSetSwitcher(sidebar, other, e.detail);
	}
};

this.osbLateralAutoHideListener = function(e) {
	if(typeof(lateralBar) != 'undefined' && e.target == lateralBar) {
		if(Prefs.lateral_placement == 'left') {
			var sidebar = leftSidebar;
			var other = rightSidebar;
		} else {
			var sidebar = rightSidebar;
			var other = leftSidebar;
		}
		osbSetSwitcher(sidebar, other, true);
	}
};

this.osbLateralPlacementListener = function() {
	if(typeof(lateralBar) != 'undefined' && lateralBar) {
		osbLateralAutoHideListener({ target: lateralBar });
	}
};

// if both the sidebar and the lateral bar are set to autohide, we physically move the lateral bar inside the sidebar, so they behave as if they're the "same" interactive element
this.osbMoveLateral = function(e) {
	if(typeof(lateralBar) == 'undefined' || !lateralBar) { return; }

	var sidebar = (Prefs.lateral_placement == 'left') ? leftSidebar : rightSidebar;

	if(!customizing
	&&	(!e
		|| (e.type == 'LoadedAutoHidePuzzleBar' && e.target == lateralBar)
		|| (e.type == 'UnloadedAutoHidePuzzleBar' && e.target != lateralBar)
		|| (e.type != 'UnloadedAutoHidePuzzleBar' && e.type != 'beforecustomization' && e.type != 'sidebarDocked'))
	&& Prefs.lateral_bar && (Prefs.lateral_autohide || onFullScreen.hideBars) && !lateralBar.collapsed
	&& sidebar.resizeBox && !sidebar.closed && sidebar.above && sidebar.autoHide) {
		if(!isAncestor(lateralBar, sidebar.resizeBox)) {
			sidebar.resizeBox.insertBefore(lateralBar, sidebar.resizeBox.firstChild);
			sidebar.resizeBox.insertBefore(lateralPP, sidebar.resizeBox.firstChild);
			removeAttribute(lateralBar, 'flex');
			setAttribute(lateralBar, 'inSidebar');
		}
	}
	else if(!isAncestor(lateralBar, lateralContainer)) {
		lateralContainer.appendChild(lateralBar);
		$('browser').appendChild(lateralPP);
		setAttribute(lateralBar, 'flex', '1');
		removeAttribute(lateralBar, 'inSidebar');
		lateralMove();
	}
};

this.osbFixer = function(loaded) {
	if(loaded) {
		// we need to access and follow some of OSB's preferences
		Prefs.setDefaults({
			moveSidebars: false,
			twinSidebar: false,
			renderabove: false,
			renderaboveTwin: false,
			autoHide: true,
			autoHideTwin: true
		}, 'omnisidebar');

		// stuff for the appearance fixes
		Prefs.listen('moveSidebars', osbLateralSidebarOpenListener);
		Prefs.listen('twinSidebar', osbLateralSidebarOpenListener);
		Prefs.listen('renderabove', osbLateralSidebarOpenListener);
		Prefs.listen('renderaboveTwin', osbLateralSidebarOpenListener);
		Prefs.listen('lateral_placement', osbLateralPlacementListener);
		Prefs.listen('moveSidebars', osbLateralPlacementListener);
		Listeners.add(window, 'endToggleSidebar', osbLateralSidebarOpenListener);
		Listeners.add(window, 'IsSidebarOpen', osbIsSidebarOpen);
		Listeners.add(window, 'LoadedSidebar', osbLoadListener);
		Listeners.add(window, 'LoadedAutoHidePuzzleBar', osbLateralAutoHideListener);

		// stuff for moving the lateralBar into the sidebar
		Prefs.listen('lateral_bar', osbMoveLateral);
		Prefs.listen('lateral_autohide', osbMoveLateral);
		Prefs.listen('lateral_placement', osbMoveLateral);
		Prefs.listen('autoHide', osbMoveLateral);
		Prefs.listen('autoHideTwin', osbMoveLateral);
		Listeners.add(window, 'beforecustomization', osbMoveLateral);
		Listeners.add(window, 'aftercustomization', osbMoveLateral);
		Listeners.add(window, 'LoadedAutoHidePuzzleBar', osbMoveLateral);
		Listeners.add(window, 'UnloadedAutoHidePuzzleBar', osbMoveLateral);
		Listeners.add(window, 'endToggleSidebar', osbMoveLateral);
		Listeners.add(window, 'sidebarAbove', osbMoveLateral);
		Listeners.add(window, 'sidebarDocked', osbMoveLateral);
	} else {
		Prefs.unlisten('moveSidebars', osbLateralSidebarOpenListener);
		Prefs.unlisten('twinSidebar', osbLateralSidebarOpenListener);
		Prefs.unlisten('renderabove', osbLateralSidebarOpenListener);
		Prefs.unlisten('renderaboveTwin', osbLateralSidebarOpenListener);
		Prefs.unlisten('lateral_placement', osbLateralPlacementListener);
		Prefs.unlisten('moveSidebars', osbLateralPlacementListener);
		Listeners.remove(window, 'endToggleSidebar', osbLateralSidebarOpenListener);
		Listeners.remove(window, 'IsSidebarOpen', osbIsSidebarOpen);
		Listeners.remove(window, 'LoadedSidebar', osbLoadListener);
		Listeners.remove(window, 'LoadedAutoHidePuzzleBar', osbLateralAutoHideListener);

		Prefs.unlisten('lateral_bar', osbMoveLateral);
		Prefs.unlisten('lateral_autohide', osbMoveLateral);
		Prefs.unlisten('lateral_placement', osbMoveLateral);
		Prefs.unlisten('autoHide', osbMoveLateral);
		Prefs.unlisten('autoHideTwin', osbMoveLateral);
		Listeners.remove(window, 'beforecustomization', osbMoveLateral);
		Listeners.remove(window, 'aftercustomization', osbMoveLateral);
		Listeners.remove(window, 'LoadedAutoHidePuzzleBar', osbMoveLateral);
		Listeners.remove(window, 'UnloadedAutoHidePuzzleBar', osbMoveLateral);
		Listeners.remove(window, 'endToggleSidebar', osbMoveLateral);
		Listeners.remove(window, 'sidebarAbove', osbMoveLateral);
		Listeners.remove(window, 'sidebarDocked', osbMoveLateral);
	}
};

this.osbListener = {
	onEnabled: function(addon) {
		if(addon.id == 'osb@quicksaver') { osbFixer(true); }
	},
	onDisabled: function(addon) {
		if(addon.id == 'osb@quicksaver') { osbFixer(false); }
	}
};

Modules.LOADMODULE = function() {
	AddonManager.addAddonListener(osbListener);
	AddonManager.getAddonByID('osb@quicksaver', function(addon) {
		if(addon && addon.isActive) { osbFixer(true); }
	});
};

Modules.UNLOADMODULE = function() {
	AddonManager.removeAddonListener(osbListener);
	osbFixer(false);
};
<commit_msg>#56 toggling the lateral bar is not triggering the sidebar<commit_after>Modules.VERSION = '1.0.1';

this.__defineGetter__('omnisidebar', function() { return window.omnisidebar; });
this.__defineGetter__('leftSidebar', function() { return omnisidebar.leftSidebar; });
this.__defineGetter__('rightSidebar', function() { return omnisidebar.rightSidebar; });

this.osbLateralSidebarOpenListener = function() {
	if(typeof(lateralSidebarOpen) != 'undefined') {
		lateralSidebarOpen();
	}
};

this.osbIsSidebarOpen = function(e) {
	e.stopPropagation();

	var sidebar = (Prefs.lateral_placement == 'left') ? leftSidebar : rightSidebar;
	e.detail = !sidebar.closed && !sidebar.above;
};

// make sure OSB's side switcher triggers the lateral bar
this.osbSetSwitcher = function(sidebar, other, setup) {
	if(typeof(lateralBar) == 'undefined' || !lateralBar || !lateralBar._autohide) { return; }

	// the other (opposite) sidebar should never trigger the lateral bar to show
	if(other.switcher && lateralBar._autohide.indexOf(other.switcher) > -1) {
		autoHideNodeListeners(lateralBar, other.switcher, false);
		lateralBar._autohide.splice(lateralBar._autohide.indexOf(other.switcher), 1);
	}

	if(setup && Prefs.lateral_bar && Prefs.lateral_autohide) {
		if(sidebar.switcher && lateralBar._autohide.indexOf(sidebar.switcher) == -1) {
			autoHideNodeListeners(lateralBar, sidebar.switcher, true);
			lateralBar._autohide.push(sidebar.switcher);
		}
	}
	else {
		if(sidebar.switcher && lateralBar._autohide.indexOf(sidebar.switcher) > -1) {
			autoHideNodeListeners(lateralBar, sidebar.switcher, false);
			lateralBar._autohide.splice(lateralBar._autohide.indexOf(sidebar.switcher), 1);
		}
	}
};

this.osbLoadListener = function(e) {
	if(leftSidebar && leftSidebar.box == e.target) {
		var sidebar = leftSidebar;
		var other = rightSidebar;
		var check = 'left';
	} else {
		var sidebar = rightSidebar;
		var other = leftSidebar;
		var check = 'right';
	}

	if(Prefs.lateral_placement == check) {
		osbSetSwitcher(sidebar, other, e.detail);
	}
};

this.osbLateralAutoHideListener = function(e) {
	if(typeof(lateralBar) != 'undefined' && e.target == lateralBar) {
		if(Prefs.lateral_placement == 'left') {
			var sidebar = leftSidebar;
			var other = rightSidebar;
		} else {
			var sidebar = rightSidebar;
			var other = leftSidebar;
		}
		osbSetSwitcher(sidebar, other, true);
	}
};

this.osbLateralPlacementListener = function() {
	if(typeof(lateralBar) != 'undefined' && lateralBar) {
		osbLateralAutoHideListener({ target: lateralBar });
	}
};

// if both the sidebar and the lateral bar are set to autohide, we physically move the lateral bar inside the sidebar, so they behave as if they're the "same" interactive element
this.osbMoveLateral = function(e) {
	if(typeof(lateralBar) == 'undefined' || !lateralBar) { return; }

	var sidebar = (Prefs.lateral_placement == 'left') ? leftSidebar : rightSidebar;

	if(!customizing
	&&	(!e
		|| (e.type == 'ToggledPuzzleBar' && e.target == lateralBar && !lateralBar.collapsed)
		|| (e.type == 'LoadedAutoHidePuzzleBar' && e.target == lateralBar)
		|| (e.type == 'UnloadedAutoHidePuzzleBar' && e.target != lateralBar)
		|| (e.type != 'UnloadedAutoHidePuzzleBar' && e.type != 'beforecustomization' && e.type != 'sidebarDocked'))
	&& Prefs.lateral_bar && (Prefs.lateral_autohide || onFullScreen.hideBars) && !lateralBar.collapsed
	&& sidebar.resizeBox && !sidebar.closed && sidebar.above && sidebar.autoHide) {
		if(!isAncestor(lateralBar, sidebar.resizeBox)) {
			sidebar.resizeBox.insertBefore(lateralBar, sidebar.resizeBox.firstChild);
			sidebar.resizeBox.insertBefore(lateralPP, sidebar.resizeBox.firstChild);
			removeAttribute(lateralBar, 'flex');
			setAttribute(lateralBar, 'inSidebar', 'true');

			// if we're toggling the toolbar, we better show the sidebar
			if(e && e.type == 'ToggledPuzzleBar') {
				omnisidebar.initialShowBar(sidebar, 1500);
			}
		}
	}
	else if(!isAncestor(lateralBar, lateralContainer)) {
		lateralContainer.appendChild(lateralBar);
		$('browser').appendChild(lateralPP);
		setAttribute(lateralBar, 'flex', '1');
		removeAttribute(lateralBar, 'inSidebar');
		lateralMove();
	}
};

this.osbFixer = function(loaded) {
	if(loaded) {
		// we need to access and follow some of OSB's preferences
		Prefs.setDefaults({
			moveSidebars: false,
			twinSidebar: false,
			renderabove: false,
			renderaboveTwin: false,
			autoHide: true,
			autoHideTwin: true
		}, 'omnisidebar');

		// stuff for the appearance fixes
		Prefs.listen('moveSidebars', osbLateralSidebarOpenListener);
		Prefs.listen('twinSidebar', osbLateralSidebarOpenListener);
		Prefs.listen('renderabove', osbLateralSidebarOpenListener);
		Prefs.listen('renderaboveTwin', osbLateralSidebarOpenListener);
		Prefs.listen('lateral_placement', osbLateralPlacementListener);
		Prefs.listen('moveSidebars', osbLateralPlacementListener);
		Listeners.add(window, 'endToggleSidebar', osbLateralSidebarOpenListener);
		Listeners.add(window, 'IsSidebarOpen', osbIsSidebarOpen);
		Listeners.add(window, 'LoadedSidebar', osbLoadListener);
		Listeners.add(window, 'LoadedAutoHidePuzzleBar', osbLateralAutoHideListener);

		// stuff for moving the lateralBar into the sidebar
		Prefs.listen('lateral_bar', osbMoveLateral);
		Prefs.listen('lateral_autohide', osbMoveLateral);
		Prefs.listen('lateral_placement', osbMoveLateral);
		Prefs.listen('autoHide', osbMoveLateral);
		Prefs.listen('autoHideTwin', osbMoveLateral);
		Listeners.add(window, 'beforecustomization', osbMoveLateral);
		Listeners.add(window, 'aftercustomization', osbMoveLateral);
		Listeners.add(window, 'LoadedAutoHidePuzzleBar', osbMoveLateral);
		Listeners.add(window, 'UnloadedAutoHidePuzzleBar', osbMoveLateral);
		Listeners.add(window, 'endToggleSidebar', osbMoveLateral);
		Listeners.add(window, 'sidebarAbove', osbMoveLateral);
		Listeners.add(window, 'sidebarDocked', osbMoveLateral);
		Listeners.add(window, 'ToggledPuzzleBar', osbMoveLateral);
	} else {
		Prefs.unlisten('moveSidebars', osbLateralSidebarOpenListener);
		Prefs.unlisten('twinSidebar', osbLateralSidebarOpenListener);
		Prefs.unlisten('renderabove', osbLateralSidebarOpenListener);
		Prefs.unlisten('renderaboveTwin', osbLateralSidebarOpenListener);
		Prefs.unlisten('lateral_placement', osbLateralPlacementListener);
		Prefs.unlisten('moveSidebars', osbLateralPlacementListener);
		Listeners.remove(window, 'endToggleSidebar', osbLateralSidebarOpenListener);
		Listeners.remove(window, 'IsSidebarOpen', osbIsSidebarOpen);
		Listeners.remove(window, 'LoadedSidebar', osbLoadListener);
		Listeners.remove(window, 'LoadedAutoHidePuzzleBar', osbLateralAutoHideListener);

		Prefs.unlisten('lateral_bar', osbMoveLateral);
		Prefs.unlisten('lateral_autohide', osbMoveLateral);
		Prefs.unlisten('lateral_placement', osbMoveLateral);
		Prefs.unlisten('autoHide', osbMoveLateral);
		Prefs.unlisten('autoHideTwin', osbMoveLateral);
		Listeners.remove(window, 'beforecustomization', osbMoveLateral);
		Listeners.remove(window, 'aftercustomization', osbMoveLateral);
		Listeners.remove(window, 'LoadedAutoHidePuzzleBar', osbMoveLateral);
		Listeners.remove(window, 'UnloadedAutoHidePuzzleBar', osbMoveLateral);
		Listeners.remove(window, 'endToggleSidebar', osbMoveLateral);
		Listeners.remove(window, 'sidebarAbove', osbMoveLateral);
		Listeners.remove(window, 'sidebarDocked', osbMoveLateral);
		Listeners.remove(window, 'ToggledPuzzleBar', osbMoveLateral);
	}
};

this.osbListener = {
	onEnabled: function(addon) {
		if(addon.id == 'osb@quicksaver') { osbFixer(true); }
	},
	onDisabled: function(addon) {
		if(addon.id == 'osb@quicksaver') { osbFixer(false); }
	}
};

Modules.LOADMODULE = function() {
	AddonManager.addAddonListener(osbListener);
	AddonManager.getAddonByID('osb@quicksaver', function(addon) {
		if(addon && addon.isActive) { osbFixer(true); }
	});
};

Modules.UNLOADMODULE = function() {
	AddonManager.removeAddonListener(osbListener);
	osbFixer(false);
};
<|endoftext|>