Skip to content
Snippets Groups Projects
Commit a2135f65 authored by Gabriel Engel's avatar Gabriel Engel
Browse files

Merge branch 'master' into features/prevent-messages-removal

* master:
  Rename image to avatars
  Create url for avatar download
  Translations to avatar
  Add social logins in avatar
  Improve design
  Add upload preview
  Move avatar upload to server side
  Upload working
  Improve interface to select avatar
  Init avatar selection
parents da5e3d5c 6f7c002c
No related merge requests found
......@@ -45,3 +45,7 @@ percolate:migrations
underscorestring:underscore.string
meteorhacks:kadira
yasaricli:slugify
jparker:gravatar
http
cfs:filesystem
cfs:standard-packages
......@@ -13,7 +13,23 @@ blaze@2.1.2
blaze-tools@1.0.3
boilerplate-generator@1.0.3
callback-hook@1.0.3
cfs:access-point@0.1.49
cfs:base-package@0.0.30
cfs:collection@0.5.5
cfs:collection-filters@0.2.4
cfs:data-man@0.0.6
cfs:file@0.1.17
cfs:filesystem@0.1.2
cfs:http-methods@0.0.29
cfs:http-publish@0.0.13
cfs:power-queue@0.9.11
cfs:reactive-list@0.0.9
cfs:reactive-property@0.0.4
cfs:standard-packages@0.5.9
cfs:storage-adapter@0.2.2
cfs:tempstore@0.1.5
cfs:upload-http@0.0.20
cfs:worker@0.1.4
check@1.0.5
chrismbeckett:toastr@2.1.0
coffeescript@1.0.6
......@@ -83,6 +99,7 @@ ordered-dict@1.0.3
percolate:migrations@0.7.5
percolatestudio:synced-cron@1.1.0
qnub:emojione@0.0.3
raix:eventemitter@0.1.2
raix:handlebar-helpers@0.2.4
random@1.0.3
reactive-dict@1.1.0
......
......@@ -29,6 +29,10 @@ Router.onBeforeAction ->
this.layout('usernameLayout')
return this.render('usernamePrompt')
if Meteor.userId()? and not Meteor.user().avatarOrigin?
this.layout('usernameLayout')
return this.render('avatarPrompt')
this.next()
, {
except: ['login']
......
......@@ -2675,6 +2675,47 @@ a.github-fork {
}
}
.avatar-suggestion-item {
height: 80px;
margin: 10px 0px;
text-align: left;
> div {
height: 80px;
width: 80px;
background-size: cover;
display: inline-block;
border: 1px solid #DDD;
font-size: 80px;
text-align: center;
line-height: 80px;
background-color: #EEE;
color: #CCC;
&.question-mark:before {
content: "?";
position: absolute;
left: 0;
width: 80px;
}
}
button {
display: inline-block;
top: -35px;
}
input[type=file] {
position: absolute !important;
width: 100%;
top: 0;
left: 0;
height: 100%;
opacity: 0;
z-index: 10000;
* {
cursor: pointer;
}
}
}
@media all and(max-width: 1100px) {
#rocket-chat {
.flex-opened {
......
Template.avatarPrompt.onCreated ->
self = this
self.suggestions = new ReactiveVar
self.upload = new ReactiveVar
self.getSuggestions = ->
self.suggestions.set undefined
Meteor.call 'getAvatarSuggestion', (error, avatars) ->
self.suggestions.set
ready: true
avatars: avatars
self.getSuggestions()
Template.avatarPrompt.helpers
suggestions: ->
return Template.instance().suggestions.get()
upload: ->
return Template.instance().upload.get()
Template.avatarPrompt.events
'click .select-service': (e) ->
Meteor.call 'setAvatarFromService', this.blob, this.service, ->
console.log arguments
'click .login-with-service': (event, template) ->
loginWithService = "loginWith#{_.capitalize(this)}"
serviceConfig = {}
Meteor[loginWithService] serviceConfig, (error) ->
if error?.error is 'github-no-public-email'
alert t("loginServices.github_no_public_email")
return
console.log error
if error?
toastr.error error.message
return
template.getSuggestions()
'change .myFileInput': (event, template) ->
FS.Utility.eachFile event, (blob) ->
reader = new FileReader()
reader.readAsDataURL(blob)
reader.onloadend = ->
template.upload.set
service: 'upload'
blob: reader.result
<template name="avatarSuggestion">
{{#if .}}
<div class="avatar-suggestion-item">
<div style="background-image: url({{blob}});">
</div>
<button type="button" class="button primary select-service">{{_ "avatar.Use_service_avatar" service}}</button>
</div>
{{/if}}
</template>
<template name="avatarSuggestionLogin">
{{#if .}}
<div class="avatar-suggestion-item">
<div class="question-mark"></div>
<button type="button" class="button primary login-with-service">{{_ "avatar.Login_with" .}}</button>
</div>
{{/if}}
</template>
<template name="avatarPrompt">
<form id="login-card" method='/'>
<div class="fields">
<h2>{{_ "avatar.Select_an_avatar"}}</h2>
</div>
<div class="fields">
<div class='input-text active'>
<div class='field'>
<div class="avatar-suggestions">
{{#if suggestions.ready}}
{{> avatarSuggestion suggestions.avatars.gravatar}}
{{> avatarSuggestion suggestions.avatars.facebook}}
{{> avatarSuggestion suggestions.avatars.google}}
{{> avatarSuggestion suggestions.avatars.github}}
{{#unless suggestions.avatars.gravatar}}
{{> avatarSuggestionLogin 'gravatar'}}
{{/unless}}
{{#unless suggestions.avatars.facebook}}
{{> avatarSuggestionLogin 'facebook'}}
{{/unless}}
{{#unless suggestions.avatars.google}}
{{> avatarSuggestionLogin 'google'}}
{{/unless}}
{{#unless suggestions.avatars.github}}
{{> avatarSuggestionLogin 'github'}}
{{/unless}}
<div class="avatar-suggestion-item">
<div style="background-image: url({{upload.blob}});" class="{{#unless upload}}question-mark{{/unless}}">
</div>
{{#with upload}}
<button type="button" class="button primary select-service">{{_ "avatar.Use_uploaded_avatar"}}</button>
{{/with}}
{{#unless upload}}
<button type="button" class="button primary">{{_ "avatar.Select_file"}}
<input type="file" class="myFileInput">
</button>
{{/unless}}
</div>
{{else}}
{{_ "usernameRegistration.Loading_suggestion"}}
{{/if}}
</div>
</div>
</div>
</div>
{{#if username.ready}}
<div class="submit">
<button data-loading-text="{{_ "general.Please_wait"}}..." class='button primary login'><span>{{_ "usernameRegistration.Use_this_username"}}</span></button>
</div>
{{/if}}
</form>
</template>
......@@ -149,5 +149,12 @@
},
"error": {
"Not_found_or_not_allowed": "Not Found or Not Allowed"
},
"avatar": {
"Use_service_avatar": "Use %s avatar",
"Login_with": "Login with %s",
"Select_an_avatar": "Select an avatar",
"Use_uploaded_avatar": "Use uploaded avatar",
"Select_file": "Select file"
}
}
......@@ -149,5 +149,12 @@
},
"error": {
"Not_found_or_not_allowed": "Não encontrado ou não permitido"
},
"avatar": {
"Use_service_avatar": "Use o avatar de %s",
"Login_with": "Login com %s",
"Select_an_avatar": "Selecione um avatar",
"Use_uploaded_avatar": "Use o avatar de upload",
"Select_file": "Selecione um arquivo"
}
}
uploadPath = "~/uploads"
store = new FS.Store.FileSystem "avatars",
path: uploadPath
fileKeyMaker: (fileObj) ->
filename = fileObj.name()
filenameInStore = fileObj.name({store: 'avatars'})
return filenameInStore || filename
@Avatars = new FS.Collection "avatars",
stores: [store]
@Avatars.allow
insert: ->
return true
update: ->
return true
download: ->
return true
Meteor.startup ->
if Meteor.isServer
FS.HTTP.mount ['/avatar/:filename'], ->
self = this
opts = FS.Utility.extend({}, self.query || {}, self.params || {})
collectionName = opts.collectionName
collection = FS._collections['avatars']
file = if collection? then collection.findOne({ "copies.avatars.key": opts.filename }) else null
return {
collection: collection
file: file
storeName: 'avatars'
download: opts.download
filename: opts.filename
}
Meteor.methods
getAvatarSuggestion: ->
if not Meteor.userId()
throw new Meteor.Error 203, '[methods] typingStatus -> Usuário não logado'
user = Meteor.user()
avatars = []
if user.services.facebook?.id?
avatars.push
service: 'facebook'
url: "https://graph.facebook.com/#{user.services.facebook.id}/picture?type=large"
if user.services.google?.picture?
avatars.push
service: 'google'
url: user.services.google.picture
if user.services.github?.username?
avatars.push
service: 'github'
url: "https://avatars.githubusercontent.com/#{user.services.github.username}?s=200"
if user.emails?.length > 0
for email in user.emails when email.verified is true
avatars.push
service: 'gravatar'
url: Gravatar.imageUrl email.address
validAvatars = {}
for avatar in avatars
try
result = HTTP.get avatar.url, npmRequestOptions: {encoding: null}
if result.statusCode is 200
blob = "data:#{result.headers['content-type']};base64,"
blob += Buffer(result.content, 'binary').toString('base64')
avatar.blob = blob
validAvatars[avatar.service] = avatar
catch e
# ...
return validAvatars
Meteor.methods
setAvatarFromService: (image, service) ->
if not Meteor.userId()
throw new Meteor.Error 203, '[methods] typingStatus -> Usuário não logado'
user = Meteor.user()
file = new FS.File image
file.attachData image, ->
file.name user.username
Avatars.insert file, (err, fileObj) ->
Meteor.users.update {_id: user._id}, {$set: {avatarOrigin: service}}
......@@ -12,6 +12,7 @@ Meteor.publish 'userData', ->
status: 1
statusDefault: 1
statusConnection: 1
avatarOrigin: 1
emails: 1
'services.facebook.id': 1
'services.google.picture': 1
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment