Add the ability to upload photos from the mobile site

This commit is contained in:
movilla 2013-02-24 03:38:24 +01:00
parent 19b9b0edb8
commit 76b1e9b0dc
12 changed files with 338 additions and 9 deletions

View file

@ -4,6 +4,7 @@
* Deleting a post that was shared to Facebook now deletes it from Facebook too [#3980]( https://github.com/diaspora/diaspora/pull/3980)
* Include reshares in a users public atom feed [#1781](https://github.com/diaspora/diaspora/issues/1781)
* Add the ability to upload photos from the mobile site. [#4004](https://github.com/diaspora/diaspora/issues/4004)
## Bug Fixes

View file

@ -7,7 +7,7 @@
//= require mbp-respond.min
//= require mbp-helper
//= require jquery.autoSuggest.custom
//= require fileuploader-custom
$(document).ready(function(){
@ -273,3 +273,85 @@ $(document).ready(function(){
});
});
function createUploader(){
var aspectIds = gon.aspect_ids;
var uploader = new qq.FileUploaderBasic({
element: document.getElementById('file-upload-publisher'),
params: {'photo' : {'pending' : 'true', 'aspect_ids' : aspectIds},},
allowedExtensions: ['jpg', 'jpeg', 'png', 'gif', 'tiff'],
action: "/photos",
debug: true,
button: document.getElementById('file-upload-publisher'),
sizeLimit: 4194304,
onProgress: function(id, fileName, loaded, total){
var progress = Math.round(loaded / total * 100 );
$('#fileInfo-publisher').text(fileName + ' ' + progress + '%');
},
messages: {
typeError: Diaspora.I18n.t("photo_uploader.invalid_ext"),
sizeError: Diaspora.I18n.t("photos.new_photo.size_error"),
emptyError: Diaspora.I18n.t("photos.new_photo.empty")
},
onSubmit: function(id, fileName){
$('#file-upload-publisher').addClass("loading");
$('#publisher_textarea_wrapper').addClass("with_attachments");
$('#photodropzone').append(
"<li class='publisher_photo loading' style='position:relative;'>" +
"<img alt=\"Ajax-loader2\" src=\"/assets/ajax-loader2.gif\" />" +
"</li>"
);
},
onComplete: function(id, fileName, responseJSON) {
$('#fileInfo-publisher').text(fileName + ' completed');
var id = responseJSON.data.photo.id,
url = responseJSON.data.photo.unprocessed_image.url,
currentPlaceholder = $('li.loading').first();
$('#publisher_textarea_wrapper').addClass("with_attachments");
$('#new_status_message').append("<input type='hidden' value='" + id + "' name='photos[]' />");
// replace image placeholders
var img = currentPlaceholder.find('img');
img.attr('src', url);
img.attr('data-id', id);
currentPlaceholder.removeClass('loading');
currentPlaceholder.append("<div class='x'>X</div>" +
"<div class='circle'></div>");
////
var publisher = $('#publisher'),
textarea = publisher.find('textarea');
publisher.find("input[type='submit']").removeAttr('disabled');
$('.x').bind('click', function(){
var photo = $(this).closest('.publisher_photo');
photo.addClass("dim");
$.ajax({url: "/photos/" + photo.children('img').attr('data-id'),
dataType: 'json',
type: 'DELETE',
success: function() {
photo.fadeOut(400, function(){
photo.remove();
if ( $('.publisher_photo').length == 0){
$('#publisher_textarea_wrapper').removeClass("with_attachments");
}
});
}
});
});
},
onAllComplete: function(completed_files){
}
});
}
createUploader();

View file

@ -553,7 +553,7 @@ footer {
left: 0;
border: none;
margin: 10px 0;
font-size: larger;
font-size: 14px;
padding: 0;
min-width: 100%;
}
@ -1011,6 +1011,10 @@ select#user_language, #user_auto_follow_back_aspect_id, #aspect_ids_ {
padding: 3px;
}
select#aspect_ids_ {
width: auto !important;
}
#file-upload-spinner {
top: 0px;
}
@ -1034,3 +1038,136 @@ select#user_language, #user_auto_follow_back_aspect_id, #aspect_ids_ {
input#q.search {
margin-bottom: 20px;
}
#file-upload-publisher {
bottom: 10px !important;
display: inline-block;
padding: 3px 12px;
position: absolute !important;
left: 20px;
cursor: pointer;
img {
@include opacity(1);
vertical-align: bottom;
}
&:hover {
color: #666;
cursor: pointer;
img {
@include opacity(0.4);
}
}
&:active {
color: #444;
text-shadow: 0 1px 0 #fafafa;
img {
@include opacity(1);
}
}
&.loading {
@include opacity(1);
}
}
#publisher_textarea_wrapper {
#hide_publisher {
@include opacity(0.3);
z-index: 5;
padding: 3px;
position: absolute;
right: 6px;
top: 0;
&:hover {
@include opacity(1);
}
}
@include border-radius(2px);
background: #fff;
&.active {
border: 1px solid #999;
}
position: relative;
padding-right: 10px;
textarea {
z-index: 2;
border: none;
&:focus {
outline: 0;
background: transparent;
}
}
&.with_attachments {
padding-bottom: 55px;
border: 1px solid #CCCCCC;
}
#photodropzone {
z-index: 3;
position: absolute;
bottom: 0;
left: 0;
padding: 0;
margin: 0 !important;
li {
display: table-cell;
padding-right: 4px;
img {
max-height: 55px;
}
.circle {
@include border-radius(20px);
display: none;
z-index: 1;
position: absolute;
right: -7px;
top: -5px;
background-color: #333;
width: 20px;
max-width: 20px;
height: 20px;
max-height: 20px;
border: 1px solid #fff;
}
.x {
display: none;
z-index: 2;
position: absolute;
top: -4px;
right: -1px;
font-size: small;
font-weight: bold;
color: #FFFFFF;
}
&:hover {
cursor: default;
.circle {
display: block;
}
.x {
display: block;
}
}
}
}
}
#fileInfo-publisher {
font-size: small;
margin: 5px 2px;
position: absolute;
right: 10px;
text-align: right;
bottom: 40px;
}

View file

@ -23,6 +23,7 @@ class StatusMessagesController < ApplicationController
if @contact
@aspects_with_person = @contact.aspects
@aspect_ids = @aspects_with_person.map{|x| x.id}
gon.aspect_ids = @aspect_ids
@contacts_of_contact = @contact.contacts
render :layout => nil
end
@ -30,6 +31,7 @@ class StatusMessagesController < ApplicationController
@aspect = :all
@aspects = current_user.aspects
@aspect_ids = @aspects.map{ |a| a.id }
gon.aspect_ids = @aspect_ids
end
end

View file

@ -4,6 +4,7 @@
- content_for :head do
= javascript_include_tag :jquery
= javascript_include_tag 'fileuploader-custom'
:javascript
$(document).ready(function () {

View file

@ -2,15 +2,18 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
- content_for :head do
= jquery_include_tag
= javascript_include_tag :main
= load_javascript_locales
= include_gon
- content_for :custom_css do
:css
body {
background-color: #eee;
}
- content_for :header_action do
= submit_tag t('.share'), :class => 'btn primary', :id => "submit_new_message"
= form_for StatusMessage.new, {:data => {:ajax => false}} do |status|
#message_container
= status.hidden_field :provider_display_name, :value => 'mobile'
@ -32,3 +35,17 @@
- current_user.aspects.each do |aspect|
%option{:value => aspect.id}
= "· #{aspect.name}"
%br
%br
#fileInfo-publisher
#publisher_textarea_wrapper
%ul#photodropzone
#file-upload-publisher{:title => t('.upload_photos'), :class => 'btn'}
= image_tag 'icons/camera.png', :style => "height: 14px; width: 19px;", :alt => t('.upload_photos').titleize
#publisher_mobile
= submit_tag t('.share'), :class => 'btn primary', :id => "submit_new_message", :style => "position: absolute; right: 20px; bottom: 10px"
#publisher_photo_upload

View file

@ -78,6 +78,9 @@ en:
photo_uploader:
looking_good: "OMG, you look awesome!"
completed: "<%= file %> completed"
invalid_ext: "{file} has invalid extension. Only {extensions} are allowed."
size_error: "{file} is too large, maximum file size is {sizeLimit}."
empty: "{file} is empty, please select files again without it."
tags:
wasnt_that_interesting: "OK, I suppose #<%= tagName %> wasn't all that interesting..."
people:

View file

@ -0,0 +1,60 @@
@javascript
Feature: posting from the main page
In order to navigate Diaspora*
As a mobile user
I want to tell the world I am eating a yogurt
Background:
Given following users exist:
| username |
| bob |
| alice |
And I visit the mobile home page
And I sign in as "bob@bob.bob"
And a user with username "bob" is connected with "alice"
Given I have following aspects:
| PostingTo |
| NotPostingThingsHere |
And I have user with username "alice" in an aspect called "PostingTo"
And I have user with username "alice" in an aspect called "NotPostingThingsHere"
Scenario: posting some text
Given I publisher mobile page
And I append "I am eating yogurt" to the publisher mobile
And I select "Unicorns" from "aspect_ids_"
And I press "Share"
When I visit the mobile stream page
Then I should see "I am eating yogurt"
Scenario: post a photo without text
Given I publisher mobile page
When I attach the file "spec/fixtures/button.png" to hidden element "file" within "#file-upload-publisher"
And I wait for the ajax to finish
Then I should see an uploaded image within the photo drop zone
When I press "Share"
And I wait for the ajax to finish
When I visit the mobile stream page
Then I should see a "img" within ".stream_element div.photo_attachments"
When I log out
And I sign in as "alice@alice.alice"
When I visit the mobile stream page
Then I should see a "img" within ".stream_element div.photo_attachments"
Scenario: back out of posting a photo-only post
Given I publisher mobile page
When I attach the file "spec/fixtures/button.png" to hidden element "file" within "#file-upload-publisher"
And I wait for the ajax to finish
And I click to delete the first uploaded photo
And I wait for the ajax to finish
Then I should not see an uploaded image within the photo drop zone
Scenario: back out of uploading a picture when another has been attached
Given I publisher mobile page
And I append "I am eating yogurt" to the publisher mobile
And I attach the file "spec/fixtures/button.gif" to hidden element "file" within "#file-upload-publisher"
And I attach the file "spec/fixtures/button.png" to hidden element "file" within "#file-upload-publisher"
And I wait for the ajax to finish
And I click to delete the first uploaded photo
And I wait for the ajax to finish
Then I should see an uploaded image within the photo drop zone
And the text area wrapper mobile should be with attachments

View file

@ -96,6 +96,10 @@ Then /^the publisher should be expanded$/ do
find("#publisher")["class"].should_not include("closed")
end
Then /^the text area wrapper mobile should be with attachments$/ do
find("#publisher_textarea_wrapper")["class"].should include("with_attachments")
end
When /^I append "([^"]*)" to the publisher$/ do |stuff|
elem = find('#status_message_fake_text')
elem.native.send_keys(' ' + stuff)
@ -105,6 +109,15 @@ When /^I append "([^"]*)" to the publisher$/ do |stuff|
end
end
When /^I append "([^"]*)" to the publisher mobile$/ do |stuff|
elem = find('#status_message_text')
elem.native.send_keys(' ' + stuff)
wait_until do
find('#status_message_text').value.include?(stuff)
end
end
And /^I want to mention (?:him|her) from the profile$/ do
click_link("Mention")
wait_for_ajax_to_finish

View file

@ -1,3 +1,15 @@
When /^I visit the mobile aspects page$/ do
visit('/aspects.mobile')
end
When /^I visit the mobile home page$/ do
visit('/users/sign_in.mobile')
end
Given /^I publisher mobile page$/ do
visit('/status_messages/new.mobile')
end
When /^I visit the mobile stream page$/ do
visit('/stream.mobile')
end

View file

@ -1216,6 +1216,7 @@ qq.extend(qq.UploadHandlerXhr.prototype, {
xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.setRequestHeader("X-CSRF-Token", $("meta[name='csrf-token']").attr("content"));
xhr.setRequestHeader("Accept", "application/json");
xhr.send(file);
},
_onComplete: function(id, xhr){