Merge branch 'next-minor' into develop

This commit is contained in:
Benjamin Neff 2018-04-12 01:56:07 +02:00
commit 66175f6908
No known key found for this signature in database
GPG key ID: 971464C3F1A90194
47 changed files with 272 additions and 593 deletions

View file

@ -12,13 +12,18 @@
# 0.7.5.0 # 0.7.5.0
## Refactor ## Refactor
* Remove the 'make contacts in this aspect visible to each other' option [#7769](https://github.com/diaspora/diaspora/pull/7769)
* Remove the requirement to have at least two users to disable the /podmin redirect [#7783](https://github.com/diaspora/diaspora/pull/7783)
## Bug fixes ## Bug fixes
* Prefill conversation form on contacts page only with mutual contacts [#7744](https://github.com/diaspora/diaspora/pull/7744) * Prefill conversation form on contacts page only with mutual contacts [#7744](https://github.com/diaspora/diaspora/pull/7744)
* Fix profiles sometimes not loading properly in background tabs [#7740](https://github.com/diaspora/diaspora/pull/7740) * Fix profiles sometimes not loading properly in background tabs [#7740](https://github.com/diaspora/diaspora/pull/7740)
* Show error message when creating posts with invalid aspects [#7742](https://github.com/diaspora/diaspora/pull/7742) * Show error message when creating posts with invalid aspects [#7742](https://github.com/diaspora/diaspora/pull/7742)
* Fix mention syntax backport for two immediately consecutive mentions [#7777](https://github.com/diaspora/diaspora/pull/7777)
* Fix link to 'make yourself an admin' [#7783](https://github.com/diaspora/diaspora/pull/7783)
## Features ## Features
* Make public stream accessible for logged out users [#7775](https://github.com/diaspora/diaspora/pull/7775)
# 0.7.4.1 # 0.7.4.1

View file

@ -5,7 +5,6 @@ app.pages.Contacts = Backbone.View.extend({
el: "#contacts_container", el: "#contacts_container",
events: { events: {
"click #contacts_visibility_toggle" : "toggleContactVisibility",
"click #chat_privilege_toggle" : "toggleChatPrivilege", "click #chat_privilege_toggle" : "toggleChatPrivilege",
"click #change_aspect_name" : "showAspectNameForm", "click #change_aspect_name" : "showAspectNameForm",
"click .conversation_button": "showMessageModal", "click .conversation_button": "showMessageModal",
@ -13,7 +12,6 @@ app.pages.Contacts = Backbone.View.extend({
}, },
initialize: function(opts) { initialize: function(opts) {
this.visibilityToggle = $("#contacts_visibility_toggle i");
this.chatToggle = $("#chat_privilege_toggle i"); this.chatToggle = $("#chat_privilege_toggle i");
this.stream = opts.stream; this.stream = opts.stream;
this.stream.render(); this.stream.render();
@ -45,25 +43,6 @@ app.pages.Contacts = Backbone.View.extend({
} }
}, },
toggleContactVisibility: function() {
if (this.visibilityToggle.hasClass("entypo-lock-open")) {
this.visibilityToggle.removeClass("entypo-lock-open")
.addClass("entypo-lock")
.tooltip("destroy")
.removeAttr("data-original-title")
.attr("title", Diaspora.I18n.t("contacts.aspect_list_is_not_visible"))
.tooltip({"placement": "bottom"});
}
else {
this.visibilityToggle.removeClass("entypo-lock")
.addClass("entypo-lock-open")
.tooltip("destroy")
.removeAttr("data-original-title")
.attr("title", Diaspora.I18n.t("contacts.aspect_list_is_visible"))
.tooltip({"placement": "bottom"});
}
},
showAspectNameForm: function() { showAspectNameForm: function() {
$(".header > h3").hide(); $(".header > h3").hide();
var aspectName = $.trim($(".header h3 #aspect_name").text()); var aspectName = $.trim($(".header h3 #aspect_name").text());

View file

@ -24,9 +24,6 @@ app.pages.Profile = app.views.Base.extend({
if (app.hasPreload("photos_count")) { if (app.hasPreload("photos_count")) {
this.photos = app.parsePreload("photos_count"); this.photos = app.parsePreload("photos_count");
} }
if (app.hasPreload("contacts_count")) {
this.contacts = app.parsePreload("contacts_count");
}
this.streamCollection = _.has(opts, "streamCollection") ? opts.streamCollection : null; this.streamCollection = _.has(opts, "streamCollection") ? opts.streamCollection : null;
this.streamViewClass = _.has(opts, "streamView") ? opts.streamView : null; this.streamViewClass = _.has(opts, "streamView") ? opts.streamView : null;
@ -70,7 +67,6 @@ app.pages.Profile = app.views.Base.extend({
return new app.views.ProfileHeader({ return new app.views.ProfileHeader({
model: this.model, model: this.model,
photos: this.photos, photos: this.photos,
contacts: this.contacts
}); });
}, },

View file

@ -20,7 +20,6 @@ app.Router = Backbone.Router.extend({
"p/:id(/)": "singlePost", "p/:id(/)": "singlePost",
"people(/)": "peopleSearch", "people(/)": "peopleSearch",
"people/:id(/)": "profile", "people/:id(/)": "profile",
"people/:id/contacts(/)": "profile",
"people/:id/photos(/)": "photos", "people/:id/photos(/)": "photos",
"posts/:id(/)": "singlePost", "posts/:id(/)": "singlePost",
"profile/edit(/)": "settings", "profile/edit(/)": "settings",

View file

@ -21,10 +21,6 @@ app.views.AspectCreate = app.views.Base.extend({
}); });
}, },
_contactsVisible: function() {
return this.$("#aspect_contacts_visible").is(":checked");
},
_name: function() { _name: function() {
return this.$("#aspect_name").val(); return this.$("#aspect_name").val();
}, },
@ -71,8 +67,7 @@ app.views.AspectCreate = app.views.Base.extend({
app.aspects.create({ app.aspects.create({
"person_id": this._personId || null, "person_id": this._personId || null,
"name": this._name(), "name": this._name()
"contacts_visible": this._contactsVisible()
}); });
}, },

View file

@ -14,7 +14,6 @@ app.views.ProfileHeader = app.views.Base.extend({
initialize: function(opts) { initialize: function(opts) {
this.photos = _.has(opts, 'photos') ? opts.photos : null; this.photos = _.has(opts, 'photos') ? opts.photos : null;
this.contacts = _.has(opts, 'contacts') ? opts.contacts : null;
this.model.on("change", this.render, this); this.model.on("change", this.render, this);
$("#mentionModal").on("modal:loaded", this.mentionModalLoaded.bind(this)); $("#mentionModal").on("modal:loaded", this.mentionModalLoaded.bind(this));
$("#mentionModal").on("hidden.bs.modal", this.mentionModalHidden); $("#mentionModal").on("hidden.bs.modal", this.mentionModalHidden);
@ -24,13 +23,11 @@ app.views.ProfileHeader = app.views.Base.extend({
return _.extend({}, this.defaultPresenter(), { return _.extend({}, this.defaultPresenter(), {
show_profile_btns: this._shouldShowProfileBtns(), show_profile_btns: this._shouldShowProfileBtns(),
show_photos: this._shouldShowPhotos(), show_photos: this._shouldShowPhotos(),
show_contacts: this._shouldShowContacts(),
is_blocked: this.model.isBlocked(), is_blocked: this.model.isBlocked(),
is_sharing: this.model.isSharing(), is_sharing: this.model.isSharing(),
is_receiving: this.model.isReceiving(), is_receiving: this.model.isReceiving(),
is_mutual: this.model.isMutual(), is_mutual: this.model.isMutual(),
has_tags: this._hasTags(), has_tags: this._hasTags(),
contacts: this.contacts,
photos: this.photos photos: this.photos
}); });
}, },
@ -51,10 +48,6 @@ app.views.ProfileHeader = app.views.Base.extend({
return (this.photos && this.photos > 0); return (this.photos && this.photos > 0);
}, },
_shouldShowContacts: function() {
return (this.contacts && this.contacts > 0);
},
showMentionModal: function() { showMentionModal: function() {
app.helpers.showModal("#mentionModal"); app.helpers.showModal("#mentionModal");
}, },

View file

@ -25,7 +25,7 @@ app.views.Stream = app.views.InfScroll.extend({
markNavSelected : function() { markNavSelected : function() {
var activeStream = Backbone.history.fragment; var activeStream = Backbone.history.fragment;
var streamSelection = $("#stream_selection"); var streamSelection = $("#stream-selection");
streamSelection.find("[data-stream]").removeClass("selected"); streamSelection.find("[data-stream]").removeClass("selected");
streamSelection.find("[data-stream='" + activeStream + "']").addClass("selected"); streamSelection.find("[data-stream='" + activeStream + "']").addClass("selected");

View file

@ -4,6 +4,10 @@
} }
} }
.public-stream {
float: none;
}
.main-stream-publisher { .main-stream-publisher {
margin-top: 20px; margin-top: 20px;
padding: 0; padding: 0;

View file

@ -22,16 +22,6 @@
<input id="aspect_name" class="input-block-level form-control" maxlength=20 type="text"/> <input id="aspect_name" class="input-block-level form-control" maxlength=20 type="text"/>
</div> </div>
</div> </div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label for="aspect_contacts_visible" class="checkbox inline">
<input id="aspect_contacts_visible" type="checkbox"> {{ t "aspects.make_aspect_list_visible" }}
</label>
</div>
</div>
</div>
</form> </form>
</fieldset> </fieldset>

View file

@ -17,7 +17,7 @@
<span class="section-selected">{{ title_account_and_data_management }}</span> <span class="section-selected">{{ title_account_and_data_management }}</span>
</li> </li>
<li> <li>
<a href="#" class="section-unselected faq-link" data-section="aspects" data-items="what_is_an_aspect who_sees_post contacts_know_aspect person_multiple_aspects contacts_visible remove_notification change_aspect_of_post post_multiple_aspects restrict_posts_i_see rename_aspect delete_aspect">{{ title_aspects }}</a> <a href="#" class="section-unselected faq-link" data-section="aspects" data-items="what_is_an_aspect who_sees_post contacts_know_aspect person_multiple_aspects remove_notification change_aspect_of_post post_multiple_aspects restrict_posts_i_see rename_aspect delete_aspect">{{ title_aspects }}</a>
<span class="section-selected">{{ title_aspects }}</span> <span class="section-selected">{{ title_aspects }}</span>
</li> </li>
<li> <li>

View file

@ -82,22 +82,5 @@
</a> </a>
</li> </li>
{{/if}} {{/if}}
{{#if show_contacts}}
<li {{#isCurrentPage 'personContacts' guid}} class="active" {{/isCurrentPage}}>
{{#if is_own_profile}}
<a href="{{urlTo 'contacts'}}" id="contacts_link">
<i class="entypo-users"></i>
{{t 'profile.contacts'}}
<div class="badge badge-default">{{contacts}}</div>
</a>
{{else}}
<a href="{{urlTo 'personContacts' guid}}" id="contacts_link">
<i class="entypo-users"></i>
{{t 'profile.contacts'}}
<div class="badge badge-default">{{contacts}}</div>
</a>
{{/if}}
</li>
{{/if}}
</div> </div>
</div> </div>

View file

@ -84,18 +84,6 @@ class AspectsController < ApplicationController
head :no_content head :no_content
end end
def toggle_contact_visibility
@aspect = current_user.aspects.where(:id => params[:aspect_id]).first
if @aspect.contacts_visible?
@aspect.contacts_visible = false
else
@aspect.contacts_visible = true
end
@aspect.save
head :no_content
end
private private
def connect_person_to_aspect(aspecting_person_id) def connect_person_to_aspect(aspecting_person_id)
@ -109,6 +97,6 @@ class AspectsController < ApplicationController
end end
def aspect_params def aspect_params
params.require(:aspect).permit(:name, :contacts_visible, :chat_enabled, :order_id) params.require(:aspect).permit(:name, :chat_enabled, :order_id)
end end
end end

View file

@ -21,7 +21,7 @@ class HomeController < ApplicationController
partial_dir.join("_show.html.erb").exist? || partial_dir.join("_show.html.erb").exist? ||
partial_dir.join("_show.haml").exist? partial_dir.join("_show.haml").exist?
render :show render :show
elsif User.count > 1 && Role.where(name: "admin").any? elsif Role.admins.any?
render :default render :default
else else
redirect_to podmin_path redirect_to podmin_path

View file

@ -77,7 +77,6 @@ class PeopleController < ApplicationController
end end
gon.preloads[:person] = @presenter.as_json gon.preloads[:person] = @presenter.as_json
gon.preloads[:photos_count] = Photo.visible(current_user, @person).count(:all) gon.preloads[:photos_count] = Photo.visible(current_user, @person).count(:all)
gon.preloads[:contacts_count] = Contact.contact_contacts_for(current_user, @person).count(:all)
respond_with @presenter, layout: "with_header" respond_with @presenter, layout: "with_header"
end end
@ -123,30 +122,6 @@ class PeopleController < ApplicationController
end end
end end
def contacts
respond_to do |format|
format.json { head :not_acceptable }
format.any do
@person = Person.find_by_guid(params[:person_id])
if @person
@contact = current_user.contact_for(@person)
@contacts_of_contact = Contact.contact_contacts_for(current_user, @person)
gon.preloads[:person] = PersonPresenter.new(@person, current_user).as_json
gon.preloads[:photos_count] = Photo.visible(current_user, @person).count(:all)
gon.preloads[:contacts_count] = @contacts_of_contact.count(:all)
@contacts_of_contact = @contacts_of_contact.paginate(page: params[:page], per_page: (params[:limit] || 15))
@hashes = hashes_for_people @contacts_of_contact, @aspects
respond_with @person, layout: "with_header"
else
flash[:error] = I18n.t "people.show.does_not_exist"
redirect_to people_path
end
end
end
end
private private
def find_person def find_person

View file

@ -31,7 +31,6 @@ class PhotosController < ApplicationController
format.all do format.all do
gon.preloads[:person] = @presenter.as_json gon.preloads[:person] = @presenter.as_json
gon.preloads[:photos_count] = Photo.visible(current_user, @person).count(:all) gon.preloads[:photos_count] = Photo.visible(current_user, @person).count(:all)
gon.preloads[:contacts_count] = Contact.contact_contacts_for(current_user, @person).count(:all)
render "people/show", layout: "with_header" render "people/show", layout: "with_header"
end end
format.mobile { render "people/show" } format.mobile { render "people/show" }

View file

@ -5,7 +5,7 @@
# the COPYRIGHT file. # the COPYRIGHT file.
class StreamsController < ApplicationController class StreamsController < ApplicationController
before_action :authenticate_user! before_action :authenticate_user!, except: :public
before_action :save_selected_aspects, :only => :aspects before_action :save_selected_aspects, :only => :aspects
layout proc { request.format == :mobile ? "application" : "with_header" } layout proc { request.format == :mobile ? "application" : "with_header" }

View file

@ -46,6 +46,10 @@ module ApplicationHelper
current_user.services.size == AppConfig.configured_services.size current_user.services.size == AppConfig.configured_services.size
end end
def service_unconnected?(service)
AppConfig.show_service?(service, current_user) && current_user.services.none? {|x| x.provider == service }
end
def popover_with_close_html(without_close_html) def popover_with_close_html(without_close_html)
without_close_html + link_to('&times;'.html_safe, "#", :class => 'close') without_close_html + link_to('&times;'.html_safe, "#", :class => 'close')
end end

View file

@ -47,17 +47,6 @@ class Contact < ApplicationRecord
).destroy_all ).destroy_all
end end
def contacts
people = Person.arel_table
incoming_aspects = Aspect.where(
:user_id => self.person.owner_id,
:contacts_visible => true).joins(:contacts).where(
:contacts => {:person_id => self.user.person_id}).select('aspects.id')
incoming_aspect_ids = incoming_aspects.map{|a| a.id}
similar_contacts = Person.joins(:contacts => :aspect_memberships).where(
:aspect_memberships => {:aspect_id => incoming_aspect_ids}).where(people[:id].not_eq(self.user.person.id)).select('DISTINCT people.*')
end
def mutual? def mutual?
sharing && receiving sharing && receiving
end end
@ -72,17 +61,6 @@ class Contact < ApplicationRecord
end end
end end
def self.contact_contacts_for(user, person)
return none unless user
if person == user.person
user.contact_people
else
contact = user.contact_for(person)
contact.try(:contacts) || none
end
end
# Follows back if user setting is set so # Follows back if user setting is set so
def receive(_recipient_user_ids) def receive(_recipient_user_ids)
user.share_with(person, user.auto_follow_back_aspect) if user.auto_follow_back && !receiving user.share_with(person, user.auto_follow_back_aspect) if user.auto_follow_back && !receiving

View file

@ -2,8 +2,6 @@
module Export module Export
class AspectSerializer < ActiveModel::Serializer class AspectSerializer < ActiveModel::Serializer
attributes :name, attributes :name, :chat_enabled
:contacts_visible,
:chat_enabled
end end
end end

View file

@ -2,12 +2,13 @@
-# licensed under the Affero General Public License version 3 or later. See -# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file. -# the COPYRIGHT file.
- if user_signed_in?
.container-fluid.main-stream-publisher .container-fluid.main-stream-publisher
.pull-left.hidden-xs .pull-left.hidden-xs
= owner_image_link = owner_image_link
= render "publisher/publisher", publisher_aspects_for(stream) = render "publisher/publisher", publisher_aspects_for(stream)
- if current_user.getting_started? - if current_user&.getting_started?
.stream#main-stream{:title => popover_with_close_html("3. #{t('.stay_updated')}"), .stream#main-stream{:title => popover_with_close_html("3. #{t('.stay_updated')}"),
"data-content" => t(".stay_updated_explanation")} "data-content" => t(".stay_updated_explanation")}
- else - else
@ -17,5 +18,5 @@
.loader.hidden .loader.hidden
.spinner .spinner
- if current_user.contacts.size < 2 - if current_user && current_user.contacts.size < 2
= render 'aspects/no_contacts_message' = render 'aspects/no_contacts_message'

View file

@ -4,12 +4,6 @@
- if @aspect.contacts.size > 0 && @aspect.contacts.size < 20 - if @aspect.contacts.size > 0 && @aspect.contacts.size < 20
= start_a_conversation_link(@aspect, @aspect.contacts.size) = start_a_conversation_link(@aspect, @aspect.contacts.size)
= link_to aspect_toggle_contact_visibility_path(@aspect), id: "contacts_visibility_toggle", class: "contacts_button", method: :put, remote: true do
-if @aspect.contacts_visible?
%i.entypo-lock-open.contacts-header-icon{title: t("aspects.edit.aspect_list_is_visible")}
-else
%i.entypo-lock.contacts-header-icon{title: t("aspects.edit.aspect_list_is_not_visible")}
-if AppConfig.chat.enabled? -if AppConfig.chat.enabled?
= link_to aspect_toggle_chat_privilege_path(@aspect), id: "chat_privilege_toggle", class: "contacts_button", method: :put, remote: true do = link_to aspect_toggle_chat_privilege_path(@aspect), id: "chat_privilege_toggle", class: "contacts_button", method: :put, remote: true do
-if @aspect.chat_enabled? -if @aspect.chat_enabled?

View file

@ -31,7 +31,7 @@
%span.entypo-key %span.entypo-key
= t(".make_yourself_an_admin") = t(".make_yourself_an_admin")
!= t(".make_yourself_an_admin_info", != t(".make_yourself_an_admin_info",
wiki: link_to("diaspora* wiki", "https://wiki.diasporafoundation.org/FAQ_for_pod_maintainers#What_are_roles_and_how_do_I_use_them.3F_.2F_Make_yourself_an_admin"), wiki: link_to("diaspora* wiki", "https://wiki.diasporafoundation.org/Permalink:FAQ_-_Add_admin"),
admin_dashboard: link_to(t("javascripts.header.admin"), admin_dashboard_path)) admin_dashboard: link_to(t("javascripts.header.admin"), admin_dashboard_path))
.row .row

View file

@ -1,32 +0,0 @@
- content_for :page_title do
= @person.name
.container-fluid#profile_container
.row
.col-md-3
.sidebar.profile-sidebar#profile
-# here be JS
.col-md-9
.profile_header
-# more JS
.stream-container
#people-stream.stream
- @hashes.each do |hash|
= render partial: 'people/person', locals: hash
= will_paginate @contacts_of_contact, renderer: WillPaginate::ActionView::BootstrapLinkRenderer
-if user_signed_in? && @person
#new_status_message_pane
= render 'shared/modal',
path: new_status_message_path(:person_id => @person.id),
title: t('status_messages.new.mentioning', person: @person.name),
id: 'mentionModal'
-if @contact
.conversations-form-container#new_conversation_pane
= render 'shared/modal',
path: new_conversation_path(:contact_id => @contact.id, name: @contact.person.name, modal: true),
title: t('conversations.index.new_conversation'),
id: 'conversationModal'

View file

@ -7,7 +7,7 @@
= javascript_include_tag :jsxc, id: 'jsxc', = javascript_include_tag :jsxc, id: 'jsxc',
data: { endpoint: get_bosh_endpoint } data: { endpoint: get_bosh_endpoint }
- if current_user.getting_started? - if current_user&.getting_started?
#welcome-to-diaspora #welcome-to-diaspora
.container-fluid .container-fluid
.row .row
@ -22,9 +22,10 @@
.container-fluid .container-fluid
.row .row
- if user_signed_in?
.col-md-3 .col-md-3
.sidebar.left-navbar .sidebar.left-navbar
%ul#stream_selection %ul#stream-selection
%li{data: {stream: "stream"}} %li{data: {stream: "stream"}}
= link_to t("streams.multi.title"), stream_path, rel: "backbone", class: "hoverable" = link_to t("streams.multi.title"), stream_path, rel: "backbone", class: "hoverable"
%li.nested-list.my-activity{data: {stream: "activity"}} %li.nested-list.my-activity{data: {stream: "activity"}}
@ -120,8 +121,7 @@
.right-service-icons .right-service-icons
- AppConfig.configured_services.each do |service| - AppConfig.configured_services.each do |service|
- if AppConfig.show_service?(service, current_user) - if service_unconnected?(service)
- unless current_user.services.any? {|x| x.provider == service }
= link_to(content_tag(:div, nil, = link_to(content_tag(:div, nil,
class: "social-media-logos-#{service.to_s.downcase}-24x24", class: "social-media-logos-#{service.to_s.downcase}-24x24",
title: service.to_s.titleize), "/auth/#{service}") title: service.to_s.titleize), "/auth/#{service}")
@ -175,6 +175,8 @@
.powered-by-diaspora.text-center .powered-by-diaspora.text-center
= link_to t("layouts.application.powered_by"), "https://diasporafoundation.org" = link_to t("layouts.application.powered_by"), "https://diasporafoundation.org"
.col-md-9 .col-md-9{class: ("center-block public-stream" unless user_signed_in?)}
.stream-container#aspect-stream-container .stream-container#aspect-stream-container
- unless user_signed_in?
%h2= @stream.title
= render "aspects/aspect_stream", stream: @stream = render "aspects/aspect_stream", stream: @stream

View file

@ -2,6 +2,9 @@
-# licensed under the Affero General Public License version 3 or later. See -# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file. -# the COPYRIGHT file.
- unless user_signed_in?
%h1= @stream.title
#main-stream.stream #main-stream.stream
= render 'shared/stream', posts: @stream.stream_posts = render 'shared/stream', posts: @stream.stream_posts
= render 'shared/stream_more_button' = render 'shared/stream_more_button'

View file

@ -369,8 +369,6 @@ en:
contacts_know_aspect_a: "No. They cannot see the name of the aspect under any circumstances." contacts_know_aspect_a: "No. They cannot see the name of the aspect under any circumstances."
person_multiple_aspects_q: "Can I add a person to multiple aspects?" person_multiple_aspects_q: "Can I add a person to multiple aspects?"
person_multiple_aspects_a: "Yes. Go to your contacts page and click on “My contacts”. For each contact you can use the menu on the right to add them to (or remove them from) as many aspects as you want. Or you can add them to a new aspect (or remove them from an aspect) by clicking the aspect selector button on their profile page. Or you can even just move the pointer over their name where you see it in the stream, and a “hovercard” will appear. You can change the aspects they are in right there." person_multiple_aspects_a: "Yes. Go to your contacts page and click on “My contacts”. For each contact you can use the menu on the right to add them to (or remove them from) as many aspects as you want. Or you can add them to a new aspect (or remove them from an aspect) by clicking the aspect selector button on their profile page. Or you can even just move the pointer over their name where you see it in the stream, and a “hovercard” will appear. You can change the aspects they are in right there."
contacts_visible_q: "What does “make contacts in this aspect visible to each other” mean?"
contacts_visible_a: "If you check this option then contacts from that aspect will be able to see who else is in it, in the “Contacts” tab on your profile page. (At the moment, only your contacts who are on the same pod as you will be able to see the “Contacts” tab on your profile.) Its best to select this option only if the contacts in that aspect all know each other, for example if the aspect is for a club or society you belong to. They still wont be able to see what the aspect is called."
remove_notification_q: "If I remove someone from an aspect, or all of my aspects, are they notified of this?" remove_notification_q: "If I remove someone from an aspect, or all of my aspects, are they notified of this?"
remove_notification_a: "No. They are also not notified if you add them to more aspects, when you are already sharing with them." remove_notification_a: "No. They are also not notified if you add them to more aspects, when you are already sharing with them."
change_aspect_of_post_q: "Once I have posted something, can I change the aspect(s) that can see it?" change_aspect_of_post_q: "Once I have posted something, can I change the aspect(s) that can see it?"

View file

@ -81,7 +81,6 @@ en:
other: "The connection test returned an error for <%= count %> pods." other: "The connection test returned an error for <%= count %> pods."
aspects: aspects:
make_aspect_list_visible: "Make contacts in this aspect visible to each other?"
name: "Name" name: "Name"
create: create:
add_a_new_aspect: "Add a new aspect" add_a_new_aspect: "Add a new aspect"
@ -124,8 +123,6 @@ en:
add_contact: "Add contact" add_contact: "Add contact"
aspect_chat_is_enabled: "Contacts in this aspect are able to chat with you." aspect_chat_is_enabled: "Contacts in this aspect are able to chat with you."
aspect_chat_is_not_enabled: "Contacts in this aspect are not able to chat with you." aspect_chat_is_not_enabled: "Contacts in this aspect are not able to chat with you."
aspect_list_is_visible: "Contacts in this aspect are able to see each other."
aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other."
remove_contact: "Remove contact" remove_contact: "Remove contact"
error_add: "Couldnt add <%= name %> to the aspect :(" error_add: "Couldnt add <%= name %> to the aspect :("
error_remove: "Couldnt remove <%= name %> from the aspect :(" error_remove: "Couldnt remove <%= name %> from the aspect :("
@ -236,7 +233,6 @@ en:
gender: "Gender" gender: "Gender"
born: "Birthday" born: "Birthday"
photos: "Photos" photos: "Photos"
contacts: "Contacts"
posts: "Posts" posts: "Posts"
conversation: conversation:

View file

@ -59,7 +59,6 @@ Rails.application.routes.draw do
get "aspects" => "streams#aspects", :as => "aspects_stream" get "aspects" => "streams#aspects", :as => "aspects_stream"
resources :aspects, except: %i(index new edit) do resources :aspects, except: %i(index new edit) do
put :toggle_contact_visibility
put :toggle_chat_privilege put :toggle_chat_privilege
collection do collection do
put "order" => :update_order put "order" => :update_order
@ -165,7 +164,6 @@ Rails.application.routes.draw do
resources :people, only: %i(show index) do resources :people, only: %i(show index) do
resources :status_messages, only: %i(new create) resources :status_messages, only: %i(new create)
resources :photos, except: %i(new update) resources :photos, except: %i(new update)
get :contacts
get :stream get :stream
get :hovercard get :hovercard

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
class RemoveContactsVisibleFromAspects < ActiveRecord::Migration[5.1]
def change
remove_index :aspects, column: %i[user_id contacts_visible], name: :index_aspects_on_user_id_and_contacts_visible
remove_column :aspects, :contacts_visible, :boolean, default: true, null: false
end
end

View file

@ -1,42 +0,0 @@
@javascript
Feature: show contacts
Background:
Given following users exist:
| username | email |
| Bob Jones | bob@bob.bob |
| Alice Smith | alice@alice.alice |
| Robert Grimm | robert@grimm.grimm |
And I sign in as "robert@grimm.grimm"
And I am on "alice@alice.alice"'s page
And I add the person to my "Unicorns" aspect
Scenario: see own contacts on profile
When I am on "robert@grimm.grimm"'s page
And I press the first "#contacts_link"
Then I should be on the contacts page
Scenario: see contacts of a visible aspect list
When I am on "bob@bob.bob"'s page
And I add the person to my "Unicorns" aspect
And I sign out
And I sign in as "alice@alice.alice"
And I am on "robert@grimm.grimm"'s page
Then I should see "Contacts" within "#profile-horizontal-bar"
When I press the first "#contacts_link"
Then I should see "Bob Jones" within "#people-stream .media-body"
When I add the person to my "Besties" aspect within "#people-stream"
Then I should see a flash message containing "You have started sharing with Bob Jones!"
Scenario: don't see contacts of an invisible aspect list
When I am on "bob@bob.bob"'s page
And I add the person to my "Unicorns" aspect
And I am on the contacts page
And I follow "Unicorns"
And I press the first "a#contacts_visibility_toggle"
And I sign out
And I sign in as "alice@alice.alice"
And I am on "robert@grimm.grimm"'s page
Then I should not see "Contacts" within "#profile-horizontal-bar"

View file

@ -25,7 +25,7 @@ Feature: Keyboard navigation
Scenario: navigate downwards after changing the stream Scenario: navigate downwards after changing the stream
When I go to the activity stream page When I go to the activity stream page
And I click on selector "[data-stream='stream'] a" And I click on selector "[data-stream='stream'] a"
Then I should see "Stream" within "#stream_selection .selected" Then I should see "Stream" within "#stream-selection .selected"
When I press the "J" key somewhere When I press the "J" key somewhere
Then post 1 should be highlighted Then post 1 should be highlighted

View file

@ -12,3 +12,7 @@ Feature: The public stream
When I sign in as "alice@alice.alice" When I sign in as "alice@alice.alice"
And I am on the public stream page And I am on the public stream page
Then I should see "Bobs public post" Then I should see "Bobs public post"
Scenario: seeing public posts as a logged out user
When I am on the public stream page
Then I should see "Bobs public post"

View file

@ -72,7 +72,7 @@ module Diaspora::Mentionable
end end
# Regex to find mentions with new syntax, only used for backporting to old syntax # Regex to find mentions with new syntax, only used for backporting to old syntax
NEW_SYNTAX_REGEX = /@\{[^ ]+\}/ NEW_SYNTAX_REGEX = /@\{[^\} ]+\}/
# replaces new syntax with old syntax, to be compatible with old pods # replaces new syntax with old syntax, to be compatible with old pods
# @deprecated remove when most of the posts can handle the new syntax # @deprecated remove when most of the posts can handle the new syntax

View file

@ -31,7 +31,6 @@
"type": "object", "type": "object",
"properties": { "properties": {
"name": { "type": "string" }, "name": { "type": "string" },
"contacts_visible": { "type": "boolean" },
"chat_enabled": { "type": "boolean" } "chat_enabled": { "type": "boolean" }
}, },
"required": [ "required": [

View file

@ -156,22 +156,4 @@ describe AspectsController, :type => :controller do
end end
end end
end end
describe "#toggle_contact_visibility" do
it 'sets contacts visible' do
@alices_aspect_1.contacts_visible = false
@alices_aspect_1.save
get :toggle_contact_visibility, xhr: true, params: {aspect_id: @alices_aspect_1.id}
expect(@alices_aspect_1.reload.contacts_visible).to be true
end
it 'sets contacts hidden' do
@alices_aspect_1.contacts_visible = true
@alices_aspect_1.save
get :toggle_contact_visibility, xhr: true, params: {aspect_id: @alices_aspect_1.id}
expect(@alices_aspect_1.reload.contacts_visible).to be false
end
end
end end

View file

@ -6,31 +6,14 @@
describe HomeController, type: :controller do describe HomeController, type: :controller do
describe "#show" do describe "#show" do
it "does not redirect for :html if there are at least 2 users and an admin" do it "does not redirect for :html if there is at least one admin" do
allow(User).to receive(:count).and_return(2) expect(Role).to receive_message_chain(:admins, :any?).and_return(true)
allow(Role).to receive_message_chain(:where, :any?).and_return(true)
allow(Role).to receive_message_chain(:where, :exists?).and_return(true)
get :show get :show
expect(response).not_to be_redirect expect(response).not_to be_redirect
end end
it "redirects to the podmin page for :html if there are less than 2 users" do
allow(User).to receive(:count).and_return(1)
allow(Role).to receive_message_chain(:where, :any?).and_return(true)
get :show
expect(response).to redirect_to(podmin_path)
end
it "redirects to the podmin page for :html if there is no admin" do it "redirects to the podmin page for :html if there is no admin" do
allow(User).to receive(:count).and_return(2) expect(Role).to receive_message_chain(:admins, :any?).and_return(false)
allow(Role).to receive_message_chain(:where, :any?).and_return(false)
get :show
expect(response).to redirect_to(podmin_path)
end
it "redirects to the podmin page for :html if there are less than 2 users and no admin" do
allow(User).to receive(:count).and_return(0)
allow(Role).to receive_message_chain(:where, :any?).and_return(false)
get :show get :show
expect(response).to redirect_to(podmin_path) expect(response).to redirect_to(podmin_path)
end end

View file

@ -580,40 +580,6 @@ describe PeopleController, :type => :controller do
end end
end end
describe '#contacts' do
it 'assigns the contacts of a person' do
contact = alice.contact_for(bob.person)
contacts = contact.contacts
get :contacts, params: {person_id: bob.person.to_param}
expect(assigns(:contacts_of_contact).to_a).to eq(contacts.to_a)
expect(response).to be_success
end
it 'shows an error when invalid person id' do
get :contacts, params: {person_id: "foo"}
expect(flash[:error]).to be_present
expect(response).to redirect_to people_path
end
it "displays the correct number of photos" do
16.times do |i|
eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => true)
end
get :contacts, params: {person_id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16'
eve.post(:photo, :user_file => uploaded_photo, :to => eve.aspects.first.id, :public => false)
get :contacts, params: {person_id: eve.person.to_param}
expect(response.body).to include ',"photos_count":16' # eve is not sharing with alice
end
it "returns a 406 for json format" do
get :contacts, params: {person_id: "foo"}, format: :json
expect(response.code).to eq("406")
end
end
describe '#diaspora_id?' do describe '#diaspora_id?' do
it 'returns true for pods on urls' do it 'returns true for pods on urls' do
expect(@controller.send(:diaspora_id?, "ilya_123@pod.geraspora.de")).to be true expect(@controller.send(:diaspora_id?, "ilya_123@pod.geraspora.de")).to be true

View file

@ -7,6 +7,7 @@
describe StreamsController, :type => :controller do describe StreamsController, :type => :controller do
include_context :gon include_context :gon
context "with a logged in user" do
before do before do
sign_in alice sign_in alice
end end
@ -18,14 +19,14 @@ describe StreamsController, :type => :controller do
end end
end end
describe '#multi' do describe "#multi" do
it 'succeeds' do it "succeeds" do
get :multi get :multi
expect(response).to be_success expect(response).to be_success
end end
it 'succeeds on mobile' do it "succeeds on mobile" do
get :multi, :format => :mobile get :multi, format: :mobile
expect(response).to be_success expect(response).to be_success
end end
@ -43,15 +44,15 @@ describe StreamsController, :type => :controller do
end end
streams = { streams = {
:liked => Stream::Likes, liked: Stream::Likes,
:mentioned => Stream::Mention, mentioned: Stream::Mention,
:followed_tags => Stream::FollowedTag, followed_tags: Stream::FollowedTag,
:activity => Stream::Activity activity: Stream::Activity
} }
streams.each do |stream_path, stream_class| streams.each do |stream_path, stream_class|
describe "a GET to #{stream_path}" do describe "a GET to #{stream_path}" do
it 'assigns a stream of the proper class' do it "assigns a stream of the proper class" do
get stream_path get stream_path
expect(response).to be_success expect(response).to be_success
expect(assigns[:stream]).to be_a stream_class expect(assigns[:stream]).to be_a stream_class
@ -59,3 +60,28 @@ describe StreamsController, :type => :controller do
end end
end end
end end
context "with no user signed in" do
describe "#public" do
it "succeeds" do
get :public
expect(response).to be_success
end
it "succeeds on mobile" do
get :public, format: :mobile
expect(response).to be_success
end
end
describe "other streams" do
it "redirects to the login page" do
%i[activity followed_tags liked mentioned multi].each do |stream_path|
get stream_path
expect(response).to be_redirect
expect(response).to redirect_to new_user_session_path
end
end
end
end
end

View file

@ -35,6 +35,30 @@ describe ApplicationHelper, :type => :helper do
end end
end end
describe "#service_unconnected?" do
attr_reader :current_user
before do
@current_user = alice
end
it "returns true if the service is unconnected" do
expect(AppConfig).to receive(:show_service?).with("service", alice).and_return(true)
expect(service_unconnected?("service")).to be true
end
it "returns false if the service is already connected" do
@current_user.services << FactoryGirl.build(:service, provider: "service")
expect(AppConfig).to receive(:show_service?).with("service", alice).and_return(true)
expect(service_unconnected?("service")).to be false
end
it "returns false if the the service shouldn't be shown" do
expect(AppConfig).to receive(:show_service?).with("service", alice).and_return(false)
expect(service_unconnected?("service")).to be false
end
end
describe "#jquery_include_tag" do describe "#jquery_include_tag" do
describe "with jquery cdn" do describe "with jquery cdn" do
before do before do

View file

@ -47,12 +47,10 @@ describe Diaspora::Exporter do
"contact_groups": [ "contact_groups": [
{ {
"name": "generic", "name": "generic",
"contacts_visible": true,
"chat_enabled": false "chat_enabled": false
}, },
{ {
"name": "Work", "name": "Work",
"contacts_visible": false,
"chat_enabled": false "chat_enabled": false
} }
] ]

View file

@ -34,35 +34,6 @@ describe("app.pages.Contacts", function(){
}); });
}); });
context('toggle contacts visibility', function() {
beforeEach(function() {
this.visibilityToggle = $("#contacts_visibility_toggle");
this.lockIcon = $("#contacts_visibility_toggle i");
});
it("updates the title for the tooltip", function() {
expect(this.lockIcon.attr("data-original-title")).toBe(
Diaspora.I18n.t("contacts.aspect_list_is_visible")
);
this.visibilityToggle.trigger("click");
expect(this.lockIcon.attr("data-original-title")).toBe(
Diaspora.I18n.t("contacts.aspect_list_is_not_visible")
);
});
it("toggles the lock icon", function() {
expect(this.lockIcon.hasClass("entypo-lock-open")).toBeTruthy();
expect(this.lockIcon.hasClass("entypo-lock")).toBeFalsy();
this.visibilityToggle.trigger("click");
expect(this.lockIcon.hasClass("entypo-lock")).toBeTruthy();
expect(this.lockIcon.hasClass("entypo-lock-open")).toBeFalsy();
});
});
context('show aspect name form', function() { context('show aspect name form', function() {
beforeEach(function() { beforeEach(function() {
this.button = $('#change_aspect_name'); this.button = $('#change_aspect_name');

View file

@ -17,7 +17,6 @@ describe("app.views.AspectCreate", function() {
expect(this.view.$("#newAspectModal.modal").length).toBe(1); expect(this.view.$("#newAspectModal.modal").length).toBe(1);
expect(this.view.$("#newAspectModal form").length).toBe(1); expect(this.view.$("#newAspectModal form").length).toBe(1);
expect(this.view.$("#newAspectModal input#aspect_name").length).toBe(1); expect(this.view.$("#newAspectModal input#aspect_name").length).toBe(1);
expect(this.view.$("#newAspectModal input#aspect_contacts_visible").length).toBe(1);
expect(this.view.$("#newAspectModal .btn-primary").length).toBe(1); expect(this.view.$("#newAspectModal .btn-primary").length).toBe(1);
}); });
@ -61,21 +60,6 @@ describe("app.views.AspectCreate", function() {
expect(obj.name).toBe(name); expect(obj.name).toBe(name);
}); });
it("should send the correct contacts_visible to the server", function() {
this.view.createAspect();
var obj = JSON.parse(jasmine.Ajax.requests.mostRecent().params);
/* jshint camelcase: false */
expect(obj.contacts_visible).toBeFalsy();
/* jshint camelcase: true */
this.view.$("input#aspect_contacts_visible").prop("checked", true);
this.view.createAspect();
obj = JSON.parse(jasmine.Ajax.requests.mostRecent().params);
/* jshint camelcase: false */
expect(obj.contacts_visible).toBeTruthy();
/* jshint camelcase: true */
});
it("should send person_id = null to the server", function() { it("should send person_id = null to the server", function() {
this.view.createAspect(); this.view.createAspect();
var obj = JSON.parse(jasmine.Ajax.requests.mostRecent().params); var obj = JSON.parse(jasmine.Ajax.requests.mostRecent().params);
@ -150,7 +134,6 @@ describe("app.views.AspectCreate", function() {
expect(this.view.$("#newAspectModal.modal").length).toBe(1); expect(this.view.$("#newAspectModal.modal").length).toBe(1);
expect(this.view.$("#newAspectModal form").length).toBe(1); expect(this.view.$("#newAspectModal form").length).toBe(1);
expect(this.view.$("#newAspectModal input#aspect_name").length).toBe(1); expect(this.view.$("#newAspectModal input#aspect_name").length).toBe(1);
expect(this.view.$("#newAspectModal input#aspect_contacts_visible").length).toBe(1);
expect(this.view.$("#newAspectModal .btn-primary").length).toBe(1); expect(this.view.$("#newAspectModal .btn-primary").length).toBe(1);
}); });
@ -174,21 +157,6 @@ describe("app.views.AspectCreate", function() {
expect(obj.name).toBe(name); expect(obj.name).toBe(name);
}); });
it("should send the correct contacts_visible to the server", function() {
this.view.createAspect();
var obj = JSON.parse(jasmine.Ajax.requests.mostRecent().params);
/* jshint camelcase: false */
expect(obj.contacts_visible).toBeFalsy();
/* jshint camelcase: true */
this.view.$("input#aspect_contacts_visible").prop("checked", true);
this.view.createAspect();
obj = JSON.parse(jasmine.Ajax.requests.mostRecent().params);
/* jshint camelcase: false */
expect(obj.contacts_visible).toBeTruthy();
/* jshint camelcase: true */
});
it("should send the correct person_id to the server", function() { it("should send the correct person_id to the server", function() {
this.view.createAspect(); this.view.createAspect();
var obj = JSON.parse(jasmine.Ajax.requests.mostRecent().params); var obj = JSON.parse(jasmine.Ajax.requests.mostRecent().params);

View file

@ -217,6 +217,13 @@ STR
expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(expected_text) expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(expected_text)
end end
it "replaces the new syntax with the old syntax for immediately consecutive mentions" do
text = "mention @{#{people[0].diaspora_handle}}@{#{people[1].diaspora_handle}} text"
expected_text = "mention @{#{people[0].name}; #{people[0].diaspora_handle}}" \
"@{#{people[1].name}; #{people[1].diaspora_handle}} text"
expect(Diaspora::Mentionable.backport_mention_syntax(text)).to eq(expected_text)
end
it "removes curly braces from name of the mentioned person when adding it" do it "removes curly braces from name of the mentioned person when adding it" do
profile = FactoryGirl.build(:profile, first_name: "{Alice}", last_name: "(Smith) [123]") profile = FactoryGirl.build(:profile, first_name: "{Alice}", last_name: "(Smith) [123]")
person = FactoryGirl.create(:person, profile: profile) person = FactoryGirl.create(:person, profile: profile)

View file

@ -30,10 +30,6 @@ describe Aspect, :type => :model do
expect(aspect.contacts.size).to eq(1) expect(aspect.contacts.size).to eq(1)
end end
it "has a contacts_visible? method" do
expect(alice.aspects.first.contacts_visible?).to be true
end
it "sets an order_id" do it "sets an order_id" do
aspect_2 = alice.aspects.create(name: "People") aspect_2 = alice.aspects.create(name: "People")
expect(aspect_2.order_id).to eq(2) expect(aspect_2.order_id).to eq(2)

View file

@ -160,62 +160,6 @@ describe Contact, type: :model do
end end
end end
describe "#contacts" do
before do
bob.aspects.create(name: "next")
@original_aspect = bob.aspects.where(name: "generic").first
@new_aspect = bob.aspects.where(name: "next").first
@people1 = []
@people2 = []
1.upto(5) do
person = FactoryGirl.build(:person)
bob.contacts.create(person: person, aspects: [@original_aspect])
@people1 << person
end
1.upto(5) do
person = FactoryGirl.build(:person)
bob.contacts.create(person: person, aspects: [@new_aspect])
@people2 << person
end
# eve <-> bob <-> alice
end
context "on a contact for a local user" do
before do
alice.reload
alice.aspects.reload
@contact = alice.contact_for(bob.person)
end
it "returns the target local user's contacts that are in the same aspect" do
expect(@contact.contacts.map(&:id)).to match_array([eve.person].concat(@people1).map(&:id))
end
it "returns nothing if contacts_visible is false in that aspect" do
@original_aspect.contacts_visible = false
@original_aspect.save
expect(@contact.contacts).to eq([])
end
it "returns no duplicate contacts" do
[alice, eve].each {|c| bob.add_contact_to_aspect(bob.contact_for(c.person), bob.aspects.last) }
contact_ids = @contact.contacts.map(&:id)
expect(contact_ids.uniq).to eq(contact_ids)
end
end
context "on a contact for a remote user" do
let(:contact) { bob.contact_for @people1.first }
it "returns an empty array" do
expect(contact.contacts).to eq([])
end
end
end
describe "#receive" do describe "#receive" do
it "shares back if auto_following is enabled" do it "shares back if auto_following is enabled" do
alice.auto_follow_back = true alice.auto_follow_back = true

View file

@ -7,7 +7,6 @@ describe Export::AspectSerializer do
it "has aspect attributes" do it "has aspect attributes" do
expect(serializer.attributes).to eq( expect(serializer.attributes).to eq(
name: aspect.name, name: aspect.name,
contacts_visible: aspect.contacts_visible,
chat_enabled: aspect.chat_enabled chat_enabled: aspect.chat_enabled
) )
end end

View file

@ -170,7 +170,7 @@ class DataGenerator
end end
def work_aspect def work_aspect
user.aspects.create(name: "Work", contacts_visible: false) user.aspects.create(name: "Work")
end end
def status_messages_flavours def status_messages_flavours