Render animated hourglass when messages are expiring
This commit is contained in:
		
					parent
					
						
							
								1383dc141f
							
						
					
				
			
			
				commit
				
					
						5f92ccd524
					
				
			
		
					 9 changed files with 121 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -157,6 +157,7 @@
 | 
			
		|||
          <div class='meta'>
 | 
			
		||||
            <span class='timestamp' data-timestamp={{ timestamp }}></span>
 | 
			
		||||
            <span class='status hide'></span>
 | 
			
		||||
            <span class='timer hourglass'></span>
 | 
			
		||||
          </div>
 | 
			
		||||
      </div>
 | 
			
		||||
  </script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								images/hourglass_empty.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								images/hourglass_empty.svg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><path d="M12 5v10l9 9-9 9v10h24V33l-9-9 9-9V5H12zm20 29v5H16v-5l8-8 8 8zm-8-12l-8-8V9h16v5l-8 8z"/></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 188 B  | 
							
								
								
									
										1
									
								
								images/hourglass_full.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								images/hourglass_full.svg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><path d="M32 4H12v11h.02l-.02.02L20.98 24 12 32.98l.02.02H12v11h24V33h-.02l.02-.02L27.02 24 36 15.02l-.02-.02H36V4h-4z"/></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 210 B  | 
| 
						 | 
				
			
			@ -398,8 +398,13 @@
 | 
			
		|||
 | 
			
		||||
            this.getConversation().trigger('expired', this);
 | 
			
		||||
        },
 | 
			
		||||
        setToExpire: function() {
 | 
			
		||||
            if (this.get('expireTimer') && this.get('expirationStartTimestamp') && !this.expireTimer) {
 | 
			
		||||
        isExpiring: function() {
 | 
			
		||||
            return this.get('expireTimer') && this.get('expirationStartTimestamp');
 | 
			
		||||
        },
 | 
			
		||||
        msTilExpire: function() {
 | 
			
		||||
              if (!this.isExpiring()) {
 | 
			
		||||
                return Infinity;
 | 
			
		||||
              }
 | 
			
		||||
              var now = Date.now();
 | 
			
		||||
              var start = this.get('expirationStartTimestamp');
 | 
			
		||||
              var delta = this.get('expireTimer') * 1000;
 | 
			
		||||
| 
						 | 
				
			
			@ -407,6 +412,11 @@
 | 
			
		|||
              if (ms_from_now < 0) {
 | 
			
		||||
                  ms_from_now = 0;
 | 
			
		||||
              }
 | 
			
		||||
              return ms_from_now;
 | 
			
		||||
        },
 | 
			
		||||
        setToExpire: function() {
 | 
			
		||||
            if (this.isExpiring() && !this.expireTimer) {
 | 
			
		||||
                var ms_from_now = this.msTilExpire();
 | 
			
		||||
                console.log('message', this.get('sent_at'), 'expires in', ms_from_now, 'ms');
 | 
			
		||||
                this.expirationTimeout = setTimeout(this.markExpired.bind(this), ms_from_now);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,7 @@
 | 
			
		|||
            this.listenTo(this.model, 'change:errors', this.onErrorsChanged);
 | 
			
		||||
            this.listenTo(this.model, 'change:body', this.render);
 | 
			
		||||
            this.listenTo(this.model, 'change:delivered', this.renderDelivered);
 | 
			
		||||
            this.listenTo(this.model, 'change:expirationStartTimestamp', this.renderExpiring);
 | 
			
		||||
            this.listenTo(this.model, 'change', this.renderSent);
 | 
			
		||||
            this.listenTo(this.model, 'change:flags change:group_update', this.renderControl);
 | 
			
		||||
            this.listenTo(this.model, 'destroy', this.onDestroy);
 | 
			
		||||
| 
						 | 
				
			
			@ -65,8 +66,11 @@
 | 
			
		|||
        },
 | 
			
		||||
        onExpired: function() {
 | 
			
		||||
            this.$el.addClass('expired');
 | 
			
		||||
            this.$el.find('.bubble').one('webkitAnimationEnd animationend',
 | 
			
		||||
                this.remove.bind(this));
 | 
			
		||||
            this.$el.find('.bubble').one('webkitAnimationEnd animationend', function(e) {
 | 
			
		||||
                if (e.target === this.$('.bubble')[0]) {
 | 
			
		||||
                  this.remove();
 | 
			
		||||
                }
 | 
			
		||||
            }.bind(this));
 | 
			
		||||
        },
 | 
			
		||||
        onDestroy: function() {
 | 
			
		||||
            if (this.$el.hasClass('expired')) {
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +133,12 @@
 | 
			
		|||
                this.$el.removeClass('control');
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        renderExpiring: function() {
 | 
			
		||||
            if (this.model.isExpiring()) {
 | 
			
		||||
                this.$('.hourglass').css('animation-duration', this.model.msTilExpire()*0.001 + 's');
 | 
			
		||||
                this.$el.addClass('expiring');
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        render: function() {
 | 
			
		||||
            var contact = this.model.isIncoming() ? this.model.getContact() : null;
 | 
			
		||||
            this.$el.html(
 | 
			
		||||
| 
						 | 
				
			
			@ -156,6 +166,8 @@
 | 
			
		|||
            this.renderSent();
 | 
			
		||||
            this.renderDelivered();
 | 
			
		||||
            this.renderErrors();
 | 
			
		||||
            this.renderExpiring();
 | 
			
		||||
 | 
			
		||||
            this.loadAttachments();
 | 
			
		||||
 | 
			
		||||
            return this;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -395,6 +395,12 @@ li.entry .error-icon-container {
 | 
			
		|||
    animation: shake 0.2s linear 3;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .timer { display: none; }
 | 
			
		||||
  .expiring .timer {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    @include hourglass(13px, 11px, #999);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .control {
 | 
			
		||||
    .bubble {
 | 
			
		||||
      .content {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										36
									
								
								stylesheets/_hourglass.scss
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								stylesheets/_hourglass.scss
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
@mixin hourglass($width, $height, $color) {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  vertical-align: text-bottom;
 | 
			
		||||
  @include color-svg('/images/hourglass_full.svg', transparent);
 | 
			
		||||
  background-size: 100%;
 | 
			
		||||
 | 
			
		||||
  &, &:before, &:after {
 | 
			
		||||
    width: $width;
 | 
			
		||||
    height: $height;
 | 
			
		||||
  }
 | 
			
		||||
  &:before, &:after {
 | 
			
		||||
    content: '';
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
  }
 | 
			
		||||
  &:before {
 | 
			
		||||
    background: $color;
 | 
			
		||||
    animation: moveDown 5s linear;
 | 
			
		||||
    animation-duration: inherit;
 | 
			
		||||
    animation-fill-mode: forwards;
 | 
			
		||||
  }
 | 
			
		||||
  &:after {
 | 
			
		||||
    @include color-svg('/images/hourglass_empty.svg', $color);
 | 
			
		||||
  }
 | 
			
		||||
  @keyframes moveDown {
 | 
			
		||||
    from {
 | 
			
		||||
      transform: translateY(0);
 | 
			
		||||
    }
 | 
			
		||||
    to   {
 | 
			
		||||
      transform: translateY($height);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1221,6 +1221,49 @@ li.entry .error-icon-container {
 | 
			
		|||
  .message-container .expired .bubble,
 | 
			
		||||
  .message-list .expired .bubble {
 | 
			
		||||
    animation: shake 0.2s linear 3; }
 | 
			
		||||
  .message-container .timer,
 | 
			
		||||
  .message-list .timer {
 | 
			
		||||
    display: none; }
 | 
			
		||||
  .message-container .expiring .timer,
 | 
			
		||||
  .message-list .expiring .timer {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    vertical-align: text-bottom;
 | 
			
		||||
    -webkit-mask: url("/images/hourglass_full.svg") no-repeat center;
 | 
			
		||||
    -webkit-mask-size: 100%;
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
    background-size: 100%; }
 | 
			
		||||
    .message-container .expiring .timer, .message-container .expiring .timer:before, .message-container .expiring .timer:after,
 | 
			
		||||
    .message-list .expiring .timer,
 | 
			
		||||
    .message-list .expiring .timer:before,
 | 
			
		||||
    .message-list .expiring .timer:after {
 | 
			
		||||
      width: 13px;
 | 
			
		||||
      height: 11px; }
 | 
			
		||||
    .message-container .expiring .timer:before, .message-container .expiring .timer:after,
 | 
			
		||||
    .message-list .expiring .timer:before,
 | 
			
		||||
    .message-list .expiring .timer:after {
 | 
			
		||||
      content: '';
 | 
			
		||||
      display: inline-block;
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      left: 0; }
 | 
			
		||||
    .message-container .expiring .timer:before,
 | 
			
		||||
    .message-list .expiring .timer:before {
 | 
			
		||||
      background: #999;
 | 
			
		||||
      animation: moveDown 5s linear;
 | 
			
		||||
      animation-duration: inherit;
 | 
			
		||||
      animation-fill-mode: forwards; }
 | 
			
		||||
    .message-container .expiring .timer:after,
 | 
			
		||||
    .message-list .expiring .timer:after {
 | 
			
		||||
      -webkit-mask: url("/images/hourglass_empty.svg") no-repeat center;
 | 
			
		||||
      -webkit-mask-size: 100%;
 | 
			
		||||
      background-color: #999; }
 | 
			
		||||
@keyframes moveDown {
 | 
			
		||||
  from {
 | 
			
		||||
    transform: translateY(0); }
 | 
			
		||||
  to {
 | 
			
		||||
    transform: translateY(11px); } }
 | 
			
		||||
  .message-container .control .bubble .content,
 | 
			
		||||
  .message-list .control .bubble .content {
 | 
			
		||||
    font-style: italic; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@
 | 
			
		|||
 | 
			
		||||
// Components
 | 
			
		||||
  @import 'progress';
 | 
			
		||||
  @import 'hourglass';
 | 
			
		||||
  @import 'debugLog';
 | 
			
		||||
  @import 'lightbox';
 | 
			
		||||
  @import 'recorder';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue