Skip to content

Commit

Permalink
[NEW] lazy load image attachments (#10608)
Browse files Browse the repository at this point in the history
[NEW] Lazy load image attachments
  • Loading branch information
ggazzo authored and rodrigok committed May 18, 2018
1 parent e358a3c commit 107afcc
Show file tree
Hide file tree
Showing 18 changed files with 135 additions and 36 deletions.
1 change: 1 addition & 0 deletions .meteor/packages
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,4 @@ rocketchat:version-check

rocketchat:search
chatpal:search
rocketchat:lazy-load
1 change: 1 addition & 0 deletions .meteor/versions
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ rocketchat:internal-hubot@0.0.1
rocketchat:irc@0.0.2
rocketchat:issuelinks@0.0.1
rocketchat:katex@0.0.1
rocketchat:lazy-load@0.0.1
rocketchat:ldap@0.0.1
rocketchat:lib@0.0.1
rocketchat:livechat@0.0.1
Expand Down
58 changes: 58 additions & 0 deletions packages/rocketchat-lazy-load/client/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import _ from 'underscore';
import './lazyloadImage';
export const fixCordova = function(url) {
if (url && url.indexOf('data:image') === 0) {
return url;
}
if (Meteor.isCordova && (url && url[0] === '/')) {
url = Meteor.absoluteUrl().replace(/\/$/, '') + url;
const query = `rc_uid=${ Meteor.userId() }&rc_token=${ Meteor._localStorage.getItem(
'Meteor.loginToken'
) }`;
if (url.indexOf('?') === -1) {
url = `${ url }?${ query }`;
} else {
url = `${ url }&${ query }`;
}
}
if (Meteor.settings['public'].sandstorm || url.match(/^(https?:)?\/\//i)) {
return url;
} else if (navigator.userAgent.indexOf('Electron') > -1) {
return __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url;
} else {
return Meteor.absoluteUrl().replace(/\/$/, '') + url;
}
};

const loadImage = el => {
const img = new Image();
const src = el.getAttribute('data-src');
el.className = el.className.replace('lazy-img', '');
img.onload = function() {
el.src = src;
el.removeAttribute('data-src');
};
img.src = fixCordova(src);
};

const isVisible = el => {
requestAnimationFrame(() => {
const rect = el.getBoundingClientRect();
if (rect.top >= -100 && rect.left >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight)) {
return loadImage(el);
}
});

};

window.addEventListener('resize', window.lazyloadtick);

export const lazyloadtick = _.debounce(() => {
[...document.querySelectorAll('.lazy-img[data-src]')]

.forEach(isVisible);
}, 500);

window.lazyloadtick = lazyloadtick;

export const addImage = el => isVisible(el);
4 changes: 4 additions & 0 deletions packages/rocketchat-lazy-load/client/lazyloadImage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<template name="lazyloadImage">
<img data-src="{{src}}" src="{{lazy}}" height="{{height}}" class="{{class}}"
data-title="{{title}}" data-description="{{description}}">
</template>
21 changes: 21 additions & 0 deletions packages/rocketchat-lazy-load/client/lazyloadImage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import './lazyloadImage.html';
import { addImage, fixCordova } from './';

Template.lazyloadImage.helpers({
lazy() {
const { preview, src, placeholder } = this;

if (!preview && !placeholder) {
return fixCordova(src);
}
return `data:image/png;base64,${ preview || 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8+/u3PQAJJAM0dIyWdgAAAABJRU5ErkJggg==' }`;
}
});

Template.lazyloadImage.onCreated(function() {
const element = Template.instance().firstNode;
if (!element) {
return;
}
addImage(element);
});
16 changes: 16 additions & 0 deletions packages/rocketchat-lazy-load/package.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Package.describe({
name: 'rocketchat:lazy-load',
version: '0.0.1',
summary: 'Lazy load image',
git: ''
});

Package.onUse(function(api) {
api.use([
'ecmascript',
'templating',
'rocketchat:lib'
]);

api.mainModule('client/index.js', 'client');
});
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@
<div class="attachment-image">
{{#if loadImage}}
<figure>
<div class="inline-image" style="background-image: url('{{fixCordova image_url}}');">
<img src="{{fixCordova image_url}}" height="{{getImageHeight image_dimensions.height}}" class="gallery-item" data-title="{{title}}" data-description="{{description}}">
</div>
{{> lazyloadImage src=image_url preview=image_preview height=(getImageHeight image_dimensions.height) class="lazy-img gallery-item" title=title description=description}}
{{#if labels}}
<div class="image-labels">
{{#each labels}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,11 @@
import moment from 'moment';
import { fixCordova } from 'meteor/rocketchat:lazy-load';
const colors = {
good: '#35AC19',
warning: '#FCB316',
danger: '#D30230'
};
const fixCordova = function(url) {
if (url && url.indexOf('data:image') === 0) {
return url;
}
if (Meteor.isCordova && (url && url[0] === '/')) {
url = Meteor.absoluteUrl().replace(/\/$/, '') + url;
const query = `rc_uid=${ Meteor.userId() }&rc_token=${ Meteor._localStorage.getItem('Meteor.loginToken') }`;
if (url.indexOf('?') === -1) {
url = `${ url }?${ query }`;
} else {
url = `${ url }&${ query }`;
}
}
if (Meteor.settings['public'].sandstorm || url.match(/^(https?:)?\/\//i)) {
return url;
} else if (navigator.userAgent.indexOf('Electron') > -1) {
return __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url;
} else {
return Meteor.absoluteUrl().replace(/\/$/, '') + url;
}
};

/*globals renderMessageBody*/
Template.messageAttachment.helpers({
fixCordova,
Expand All @@ -34,8 +15,8 @@ Template.messageAttachment.helpers({
});
},
loadImage() {
const user = Meteor.user();
if (this.downloadImages !== true) {
const user = RocketChat.models.Users.findOne({_id: Meteor.userId()}, {fields: {'settings.autoImageLoad' : 1}});
if (RocketChat.getUserPreference(user, 'autoImageLoad') === false) {
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/rocketchat-message-attachments/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ Package.onUse(function(api) {
api.use([
'templating',
'ecmascript',
'rocketchat:lib'
'rocketchat:lib',
'rocketchat:lazy-load'
]);

api.addFiles('client/messageAttachment.html', 'client');
Expand Down
2 changes: 0 additions & 2 deletions packages/rocketchat-theme/client/imports/general/base_old.css
Original file line number Diff line number Diff line change
Expand Up @@ -3167,8 +3167,6 @@
max-height: 200px;

cursor: pointer;

opacity: 0;
}
}

Expand Down
6 changes: 5 additions & 1 deletion packages/rocketchat-ui-account/client/avatar/avatar.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<template name="avatar">
<div class="avatar">
<div class="avatar-image" style="{{imageUrl}}"></div>
{{# if lazy}}
{{> lazyloadImage src=src class="avatar-image lazy-img" placeholder=true}}
{{else}}
<img src="{{src}}" class="avatar-image"/>
{{/if}}
</div>
</template>
4 changes: 2 additions & 2 deletions packages/rocketchat-ui-account/client/avatar/avatar.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Template.avatar.helpers({
imageUrl() {
src() {
let {url} = Template.instance().data;
if (!url) {
let username = this.username;
Expand All @@ -18,6 +18,6 @@ Template.avatar.helpers({

url = getAvatarUrlFromUsername(username);
}
return `background-image:url(${ url });`;
return url;
}
});
3 changes: 2 additions & 1 deletion packages/rocketchat-ui-account/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Package.onUse(function(api) {
'ecmascript',
'templating',
'rocketchat:lib',
'sha'
'sha',
'rocketchat:lazy-load'
]);

api.addFiles('client/account.html', 'client');
Expand Down
5 changes: 4 additions & 1 deletion packages/rocketchat-ui-sidenav/client/sideNav.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { lazyloadtick } from 'meteor/rocketchat:lazy-load';

/* globals menu*/

Template.sideNav.helpers({
Expand Down Expand Up @@ -51,6 +53,7 @@ Template.sideNav.events({
},

'scroll .rooms-list'() {
lazyloadtick();
return menu.updateUnreadBars();
},

Expand All @@ -62,7 +65,7 @@ Template.sideNav.events({
Template.sideNav.onRendered(function() {
SideNav.init();
menu.init();

lazyloadtick();
const first_channel_login = RocketChat.settings.get('First_Channel_After_Login');
const room = RocketChat.roomTypes.findRoom('c', first_channel_login, Meteor.userId());
if (room !== undefined && room._id !== '') {
Expand Down
2 changes: 1 addition & 1 deletion packages/rocketchat-ui-sidenav/client/sidebarItem.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{{/if}}
{{else}}
<div class="sidebar-item__user-thumb">
{{> avatar username=username roomIcon=icon}}
{{> avatar username=username roomIcon=icon lazy=true}}
</div>
{{/if}}
</div>
Expand Down
3 changes: 2 additions & 1 deletion packages/rocketchat-ui-sidenav/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Package.onUse(function(api) {
'ecmascript',
'templating',
'rocketchat:lib',
'rocketchat:ui'
'rocketchat:ui',
'rocketchat:lazy-load'
]);

api.addFiles('client/createCombinedFlex.html', 'client');
Expand Down
10 changes: 10 additions & 0 deletions packages/rocketchat-ui/client/views/app/room.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import moment from 'moment';
import mime from 'mime-type/with-db';
import Clipboard from 'clipboard';

import { lazyloadtick } from 'meteor/rocketchat:lazy-load';

window.chatMessages = window.chatMessages || {};
const isSubscribed = _id => ChatSubscription.find({ rid: _id }).count() > 0;

Expand Down Expand Up @@ -536,6 +538,9 @@ Template.room.events({
},

'scroll .wrapper': _.throttle(function(e, t) {

lazyloadtick();

const $roomLeader = $('.room-leader');
if ($roomLeader.length) {
if (e.target.scrollTop < lastScrollTop) {
Expand Down Expand Up @@ -739,6 +744,9 @@ Template.room.events({
Template.room.onCreated(function() {
// this.scrollOnBottom = true
// this.typing = new msgTyping this.data._id

lazyloadtick();

this.showUsersOffline = new ReactiveVar(false);
this.atBottom = FlowRouter.getQueryParam('msg') ? false : true;
this.unreadCount = new ReactiveVar(0);
Expand Down Expand Up @@ -898,6 +906,8 @@ Template.room.onRendered(function() {
if (template.atBottom === true && template.isAtBottom() !== true) {
template.sendToBottom();
}

lazyloadtick();
};

template.sendToBottomIfNecessaryDebounced = _.debounce(template.sendToBottomIfNecessary, 10);
Expand Down
3 changes: 2 additions & 1 deletion packages/rocketchat-ui/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ Package.onUse(function(api) {
'rocketchat:lib',
'rocketchat:ui-master',
'raix:push',
'raix:ui-dropped-event'
'raix:ui-dropped-event',
'rocketchat:lazy-load'
]);

api.use('kadira:flow-router', 'client');
Expand Down

0 comments on commit 107afcc

Please sign in to comment.