Merge branch 'release/0.6.2.0'
This commit is contained in:
commit
241c17a814
522 changed files with 7040 additions and 5318 deletions
1
.rspec
1
.rspec
|
|
@ -3,3 +3,4 @@
|
||||||
--color
|
--color
|
||||||
--tag ~performance
|
--tag ~performance
|
||||||
--order random
|
--order random
|
||||||
|
--require spec_helper
|
||||||
|
|
|
||||||
35
Changelog.md
35
Changelog.md
|
|
@ -1,3 +1,38 @@
|
||||||
|
# 0.6.2.0
|
||||||
|
|
||||||
|
## Refactor
|
||||||
|
* Use string-direction gem for rtl detection [#7181](https://github.com/diaspora/diaspora/pull/7181)
|
||||||
|
* Reduce i18n.load side effects [#7184](https://github.com/diaspora/diaspora/pull/7184)
|
||||||
|
* Force jasmine fails on syntax errors [#7185](https://github.com/diaspora/diaspora/pull/7185)
|
||||||
|
* Don't display mail-related view content if it is disabled in the pod's config [#7190](https://github.com/diaspora/diaspora/pull/7190)
|
||||||
|
* Use typeahead.js from rails-assets.org [#7192](https://github.com/diaspora/diaspora/pull/7192)
|
||||||
|
* Refactor ShareVisibilitesController to use PostService [#7196](https://github.com/diaspora/diaspora/pull/7196)
|
||||||
|
* Unify desktop and mobile head elements [#7194](https://github.com/diaspora/diaspora/pull/7194) [#7209](https://github.com/diaspora/diaspora/pull/7209)
|
||||||
|
* Refactor flash messages on ajax errors for comments, likes, reshares and aspect memberships [#7202](https://github.com/diaspora/diaspora/pull/7202)
|
||||||
|
* Only require AWS-module for fog [#7201](https://github.com/diaspora/diaspora/pull/7201)
|
||||||
|
* Only show community spotlight links on the contacts page if community spotlight is enabled [#7213](https://github.com/diaspora/diaspora/pull/7213)
|
||||||
|
* Require spec\_helper in .rspec [#7223](https://github.com/diaspora/diaspora/pull/7223)
|
||||||
|
* Make the CSRF mail a bit more friendly [#7238](https://github.com/diaspora/diaspora/pull/7238) [#7241](https://github.com/diaspora/diaspora/pull/7241)
|
||||||
|
|
||||||
|
## Bug fixes
|
||||||
|
* Fix fetching comments after fetching likes [#7167](https://github.com/diaspora/diaspora/pull/7167)
|
||||||
|
* Hide 'reshare' button on already reshared posts [#7169](https://github.com/diaspora/diaspora/pull/7169)
|
||||||
|
* Only reload profile header when changing aspect memberships [#7183](https://github.com/diaspora/diaspora/pull/7183)
|
||||||
|
* Fix visiblity on invitation modal when opening it from the stream [#7191](https://github.com/diaspora/diaspora/pull/7191)
|
||||||
|
* Add avatar fallback on tags page [#7198](https://github.com/diaspora/diaspora/pull/7198)
|
||||||
|
* Update notifications when changing the stream [#7199](https://github.com/diaspora/diaspora/pull/7199)
|
||||||
|
* Fix 500 on mobile commented and liked streams [#7219](https://github.com/diaspora/diaspora/pull/7219)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
* Show spinner when loading comments in the stream [#7170](https://github.com/diaspora/diaspora/pull/7170)
|
||||||
|
* Add a dark color theme [#7152](https://github.com/diaspora/diaspora/pull/7152)
|
||||||
|
* Added setting for custom changelog URL [#7166](https://github.com/diaspora/diaspora/pull/7166)
|
||||||
|
* Show more information of recipients on conversation creation [#7129](https://github.com/diaspora/diaspora/pull/7129)
|
||||||
|
* Update notifications every 5 minutes and when opening the notification dropdown [#6952](https://github.com/diaspora/diaspora/pull/6952)
|
||||||
|
* Show browser notifications when receiving new unread notifications [#6952](https://github.com/diaspora/diaspora/pull/6952)
|
||||||
|
* Only clear comment textarea when comment submission was successful [#7186](https://github.com/diaspora/diaspora/pull/7186)
|
||||||
|
* Add support for graceful unicorn restarts [#7217](https://github.com/diaspora/diaspora/pull/7217)
|
||||||
|
|
||||||
# 0.6.1.0
|
# 0.6.1.0
|
||||||
|
|
||||||
Note: Although this is a minor release, the configuration file changed because the old Mapbox implementation is no longer valid, and the current implementation requires additional fields. Chances are high that if you're using the old integration, it will be broken anyway. If you do use Mapbox, please check out the `diaspora.yml.example` for new parameters.
|
Note: Although this is a minor release, the configuration file changed because the old Mapbox implementation is no longer valid, and the current implementation requires additional fields. Chances are high that if you're using the old integration, it will be broken anyway. If you do use Mapbox, please check out the `diaspora.yml.example` for new parameters.
|
||||||
|
|
|
||||||
8
Gemfile
8
Gemfile
|
|
@ -25,7 +25,6 @@ gem "json-schema", "2.7.0"
|
||||||
|
|
||||||
gem "devise", "4.2.0"
|
gem "devise", "4.2.0"
|
||||||
gem "devise_lastseenable", "0.0.6"
|
gem "devise_lastseenable", "0.0.6"
|
||||||
gem "devise-token_authenticatable", "0.5.2"
|
|
||||||
|
|
||||||
# Captcha
|
# Captcha
|
||||||
|
|
||||||
|
|
@ -73,8 +72,8 @@ gem "activerecord-import", "0.15.0"
|
||||||
|
|
||||||
# File uploading
|
# File uploading
|
||||||
|
|
||||||
|
gem "fog", "1.38.0", require: "fog/aws"
|
||||||
gem "carrierwave", "0.11.2"
|
gem "carrierwave", "0.11.2"
|
||||||
gem "fog", "1.38.0"
|
|
||||||
gem "mini_magick", "4.5.1"
|
gem "mini_magick", "4.5.1"
|
||||||
|
|
||||||
# GUID generation
|
# GUID generation
|
||||||
|
|
@ -105,6 +104,7 @@ source "https://rails-assets.org" do
|
||||||
gem "rails-assets-markdown-it-sup", "1.0.0"
|
gem "rails-assets-markdown-it-sup", "1.0.0"
|
||||||
gem "rails-assets-highlightjs", "9.7.0"
|
gem "rails-assets-highlightjs", "9.7.0"
|
||||||
gem "rails-assets-bootstrap-markdown", "2.10.0"
|
gem "rails-assets-bootstrap-markdown", "2.10.0"
|
||||||
|
gem "rails-assets-corejs-typeahead", "1.0.1"
|
||||||
|
|
||||||
# jQuery plugins
|
# jQuery plugins
|
||||||
|
|
||||||
|
|
@ -136,6 +136,10 @@ gem "twitter-text", "1.14.0"
|
||||||
gem "ruby-oembed", "0.10.1"
|
gem "ruby-oembed", "0.10.1"
|
||||||
gem "open_graph_reader", "0.6.1"
|
gem "open_graph_reader", "0.6.1"
|
||||||
|
|
||||||
|
# RTL support
|
||||||
|
|
||||||
|
gem "string-direction", "1.2.0"
|
||||||
|
|
||||||
# Security Headers
|
# Security Headers
|
||||||
|
|
||||||
gem "secure_headers", "3.5.0"
|
gem "secure_headers", "3.5.0"
|
||||||
|
|
|
||||||
11
Gemfile.lock
11
Gemfile.lock
|
|
@ -171,8 +171,6 @@ GEM
|
||||||
railties (>= 4.1.0, < 5.1)
|
railties (>= 4.1.0, < 5.1)
|
||||||
responders
|
responders
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
devise-token_authenticatable (0.5.2)
|
|
||||||
devise (>= 4.0.0, < 4.3.0)
|
|
||||||
devise_lastseenable (0.0.6)
|
devise_lastseenable (0.0.6)
|
||||||
devise
|
devise
|
||||||
rails (>= 3.0.4)
|
rails (>= 3.0.4)
|
||||||
|
|
@ -648,6 +646,8 @@ GEM
|
||||||
rails-assets-jquery (>= 1.9.1, < 4)
|
rails-assets-jquery (>= 1.9.1, < 4)
|
||||||
rails-assets-bootstrap-markdown (2.10.0)
|
rails-assets-bootstrap-markdown (2.10.0)
|
||||||
rails-assets-bootstrap (~> 3)
|
rails-assets-bootstrap (~> 3)
|
||||||
|
rails-assets-corejs-typeahead (1.0.1)
|
||||||
|
rails-assets-jquery (>= 1.7)
|
||||||
rails-assets-diaspora_jsxc (0.1.5.develop.7)
|
rails-assets-diaspora_jsxc (0.1.5.develop.7)
|
||||||
rails-assets-emojione (~> 2.0.1)
|
rails-assets-emojione (~> 2.0.1)
|
||||||
rails-assets-favico.js (>= 0.3.10, < 0.4)
|
rails-assets-favico.js (>= 0.3.10, < 0.4)
|
||||||
|
|
@ -821,6 +821,8 @@ GEM
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
sprockets (>= 2.8, < 4.0)
|
sprockets (>= 2.8, < 4.0)
|
||||||
state_machine (1.2.0)
|
state_machine (1.2.0)
|
||||||
|
string-direction (1.2.0)
|
||||||
|
yard (~> 0.8)
|
||||||
swd (1.0.1)
|
swd (1.0.1)
|
||||||
activesupport (>= 3)
|
activesupport (>= 3)
|
||||||
attr_required (>= 0.0.5)
|
attr_required (>= 0.0.5)
|
||||||
|
|
@ -931,7 +933,6 @@ DEPENDENCIES
|
||||||
cucumber-rails (= 1.4.5)
|
cucumber-rails (= 1.4.5)
|
||||||
database_cleaner (= 1.5.3)
|
database_cleaner (= 1.5.3)
|
||||||
devise (= 4.2.0)
|
devise (= 4.2.0)
|
||||||
devise-token_authenticatable (= 0.5.2)
|
|
||||||
devise_lastseenable (= 0.0.6)
|
devise_lastseenable (= 0.0.6)
|
||||||
diaspora-prosody-config (= 0.0.7)
|
diaspora-prosody-config (= 0.0.7)
|
||||||
diaspora_federation-rails (= 0.1.5)
|
diaspora_federation-rails (= 0.1.5)
|
||||||
|
|
@ -998,6 +999,7 @@ DEPENDENCIES
|
||||||
rails-assets-autosize (= 3.0.17)!
|
rails-assets-autosize (= 3.0.17)!
|
||||||
rails-assets-blueimp-gallery (= 2.21.3)!
|
rails-assets-blueimp-gallery (= 2.21.3)!
|
||||||
rails-assets-bootstrap-markdown (= 2.10.0)!
|
rails-assets-bootstrap-markdown (= 2.10.0)!
|
||||||
|
rails-assets-corejs-typeahead (= 1.0.1)!
|
||||||
rails-assets-diaspora_jsxc (= 0.1.5.develop.7)!
|
rails-assets-diaspora_jsxc (= 0.1.5.develop.7)!
|
||||||
rails-assets-highlightjs (= 9.7.0)!
|
rails-assets-highlightjs (= 9.7.0)!
|
||||||
rails-assets-jasmine-ajax (= 3.2.0)!
|
rails-assets-jasmine-ajax (= 3.2.0)!
|
||||||
|
|
@ -1034,6 +1036,7 @@ DEPENDENCIES
|
||||||
spring (= 2.0.0)
|
spring (= 2.0.0)
|
||||||
spring-commands-cucumber (= 1.0.1)
|
spring-commands-cucumber (= 1.0.1)
|
||||||
spring-commands-rspec (= 1.0.4)
|
spring-commands-rspec (= 1.0.4)
|
||||||
|
string-direction (= 1.2.0)
|
||||||
test_after_commit (= 1.1.0)
|
test_after_commit (= 1.1.0)
|
||||||
timecop (= 0.8.1)
|
timecop (= 0.8.1)
|
||||||
turbo_dev_assets (= 0.0.2)
|
turbo_dev_assets (= 0.0.2)
|
||||||
|
|
@ -1049,4 +1052,4 @@ DEPENDENCIES
|
||||||
will_paginate (= 3.1.5)
|
will_paginate (= 3.1.5)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.13.5
|
1.13.6
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ var app = {
|
||||||
|
|
||||||
setupHeader: function() {
|
setupHeader: function() {
|
||||||
if(app.currentUser.authenticated()) {
|
if(app.currentUser.authenticated()) {
|
||||||
|
app.notificationsCollection = new app.collections.Notifications();
|
||||||
app.header = new app.views.Header();
|
app.header = new app.views.Header();
|
||||||
$("header").prepend(app.header.el);
|
$("header").prepend(app.header.el);
|
||||||
app.header.render();
|
app.header.render();
|
||||||
|
|
@ -114,6 +115,7 @@ var app = {
|
||||||
// so we use Backbone.history.navigate instead.
|
// so we use Backbone.history.navigate instead.
|
||||||
var change = Backbone.history.navigate(link.attr("href").substring(1) ,true);
|
var change = Backbone.history.navigate(link.attr("href").substring(1) ,true);
|
||||||
if(change === undefined) { Backbone.history.loadUrl(link.attr("href").substring(1)); }
|
if(change === undefined) { Backbone.history.loadUrl(link.attr("href").substring(1)); }
|
||||||
|
app.notificationsCollection.fetch();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
114
app/assets/javascripts/app/collections/notifications.js
Normal file
114
app/assets/javascripts/app/collections/notifications.js
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
app.collections.Notifications = Backbone.Collection.extend({
|
||||||
|
model: app.models.Notification,
|
||||||
|
// URL parameter
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
url: Routes.notifications({per_page: 10, page: 1}),
|
||||||
|
/* eslint-enable camelcase */
|
||||||
|
page: 2,
|
||||||
|
perPage: 5,
|
||||||
|
unreadCount: 0,
|
||||||
|
unreadCountByType: {},
|
||||||
|
timeout: 300000, // 5 minutes
|
||||||
|
|
||||||
|
initialize: function() {
|
||||||
|
this.fetch();
|
||||||
|
setInterval(this.pollNotifications.bind(this), this.timeout);
|
||||||
|
Diaspora.BrowserNotification.requestPermission();
|
||||||
|
},
|
||||||
|
|
||||||
|
pollNotifications: function() {
|
||||||
|
var unreadCountBefore = this.unreadCount;
|
||||||
|
this.fetch();
|
||||||
|
|
||||||
|
this.once("finishedLoading", function() {
|
||||||
|
if (unreadCountBefore < this.unreadCount) {
|
||||||
|
Diaspora.BrowserNotification.spawnNotification(
|
||||||
|
Diaspora.I18n.t("notifications.new_notifications", {count: this.unreadCount}));
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch: function(options) {
|
||||||
|
options = options || {};
|
||||||
|
options.remove = false;
|
||||||
|
options.merge = true;
|
||||||
|
options.parse = true;
|
||||||
|
Backbone.Collection.prototype.fetch.apply(this, [options]);
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchMore: function() {
|
||||||
|
var hasMoreNotifications = (this.page * this.perPage) <= this.length;
|
||||||
|
// There are more notifications to load on the current page
|
||||||
|
if (hasMoreNotifications) {
|
||||||
|
this.page++;
|
||||||
|
// URL parameter
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
var route = Routes.notifications({per_page: this.perPage, page: this.page});
|
||||||
|
/* eslint-enable camelcase */
|
||||||
|
this.fetch({url: route, pushBack: true});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds new models to the collection at the end or at the beginning of the collection and
|
||||||
|
* then fires an event for each model of the collection. It will fire a different event
|
||||||
|
* based on whether the models were added at the end (typically when the scroll triggers to load more
|
||||||
|
* notifications) or at the beginning (new notifications have been added to the front of the list).
|
||||||
|
*/
|
||||||
|
set: function(items, options) {
|
||||||
|
options = options || {};
|
||||||
|
options.at = options.pushBack ? this.length : 0;
|
||||||
|
|
||||||
|
// Retreive back the new created models
|
||||||
|
var models = [];
|
||||||
|
var accu = function(model) { models.push(model); };
|
||||||
|
this.on("add", accu);
|
||||||
|
Backbone.Collection.prototype.set.apply(this, [items, options]);
|
||||||
|
this.off("add", accu);
|
||||||
|
|
||||||
|
if (options.pushBack) {
|
||||||
|
models.forEach(function(model) { this.trigger("pushBack", model); }.bind(this));
|
||||||
|
} else {
|
||||||
|
// Fires events in the reverse order so that the first event is prepended in first position
|
||||||
|
models.reverse();
|
||||||
|
models.forEach(function(model) { this.trigger("pushFront", model); }.bind(this));
|
||||||
|
}
|
||||||
|
this.trigger("finishedLoading");
|
||||||
|
},
|
||||||
|
|
||||||
|
parse: function(response) {
|
||||||
|
this.unreadCount = response.unread_count;
|
||||||
|
this.unreadCountByType = response.unread_count_by_type;
|
||||||
|
|
||||||
|
return _.map(response.notification_list, function(item) {
|
||||||
|
/* eslint-disable new-cap */
|
||||||
|
var model = new this.model(item);
|
||||||
|
/* eslint-enable new-cap */
|
||||||
|
model.on("change:unread", this.onChangedUnreadStatus.bind(this));
|
||||||
|
return model;
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
setAllRead: function() {
|
||||||
|
this.forEach(function(model) { model.setRead(); });
|
||||||
|
},
|
||||||
|
|
||||||
|
setRead: function(guid) {
|
||||||
|
this.find(function(model) { return model.guid === guid; }).setRead();
|
||||||
|
},
|
||||||
|
|
||||||
|
setUnread: function(guid) {
|
||||||
|
this.find(function(model) { return model.guid === guid; }).setUnread();
|
||||||
|
},
|
||||||
|
|
||||||
|
onChangedUnreadStatus: function(model) {
|
||||||
|
if (model.get("unread") === true) {
|
||||||
|
this.unreadCount++;
|
||||||
|
this.unreadCountByType[model.get("type")]++;
|
||||||
|
} else {
|
||||||
|
this.unreadCount = Math.max(this.unreadCount - 1, 0);
|
||||||
|
this.unreadCountByType[model.get("type")] = Math.max(this.unreadCountByType[model.get("type")] - 1, 0);
|
||||||
|
}
|
||||||
|
this.trigger("update");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
app.collections.Reshares = Backbone.Collection.extend({
|
app.collections.Reshares = Backbone.Collection.extend({
|
||||||
model: app.models.Reshare,
|
model: app.models.Reshare,
|
||||||
url : "/reshares"
|
|
||||||
|
initialize: function(models, options) {
|
||||||
|
this.url = "/posts/" + options.post.id + "/reshares";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
|
||||||
69
app/assets/javascripts/app/models/notification.js
Normal file
69
app/assets/javascripts/app/models/notification.js
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
app.models.Notification = Backbone.Model.extend({
|
||||||
|
constructor: function(attributes, options) {
|
||||||
|
options = options || {};
|
||||||
|
options.parse = true;
|
||||||
|
Backbone.Model.apply(this, [attributes, options]);
|
||||||
|
this.guid = this.get("id");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flattens the notification object returned by the server.
|
||||||
|
*
|
||||||
|
* The server returns an object that looks like:
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* "reshared": {
|
||||||
|
* "id": 45,
|
||||||
|
* "target_type": "Post",
|
||||||
|
* "target_id": 11,
|
||||||
|
* "recipient_id": 1,
|
||||||
|
* "unread": true,
|
||||||
|
* "created_at": "2015-10-27T19:56:30.000Z",
|
||||||
|
* "updated_at": "2015-10-27T19:56:30.000Z",
|
||||||
|
* "note_html": <html/>
|
||||||
|
* },
|
||||||
|
* "type": "reshared"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* The returned object looks like:
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* "type": "reshared",
|
||||||
|
* "id": 45,
|
||||||
|
* "target_type": "Post",
|
||||||
|
* "target_id": 11,
|
||||||
|
* "recipient_id": 1,
|
||||||
|
* "unread": true,
|
||||||
|
* "created_at": "2015-10-27T19:56:30.000Z",
|
||||||
|
* "updated_at": "2015-10-27T19:56:30.000Z",
|
||||||
|
* "note_html": <html/>,
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
parse: function(response) {
|
||||||
|
var result = {type: response.type};
|
||||||
|
result = $.extend(result, response[result.type]);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
setRead: function() {
|
||||||
|
this.setUnreadStatus(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
setUnread: function() {
|
||||||
|
this.setUnreadStatus(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
setUnreadStatus: function(state) {
|
||||||
|
if (this.get("unread") !== state) {
|
||||||
|
$.ajax({
|
||||||
|
url: Routes.notification(this.guid),
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
data: {set_unread: state},
|
||||||
|
/* eslint-enable camelcase */
|
||||||
|
type: "PUT",
|
||||||
|
context: this,
|
||||||
|
success: function() { this.set("unread", state); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -70,9 +70,10 @@ app.models.Post.Interactions = Backbone.Model.extend({
|
||||||
self.post.set({participation: true});
|
self.post.set({participation: true});
|
||||||
self.trigger("change");
|
self.trigger("change");
|
||||||
self.set({"likes_count" : self.get("likes_count") + 1});
|
self.set({"likes_count" : self.get("likes_count") + 1});
|
||||||
|
self.likes.trigger("change");
|
||||||
},
|
},
|
||||||
error: function() {
|
error: function(model, response) {
|
||||||
app.flashMessages.error(Diaspora.I18n.t("failed_to_like"));
|
app.flashMessages.handleAjaxError(response);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -84,23 +85,26 @@ app.models.Post.Interactions = Backbone.Model.extend({
|
||||||
this.userLike().destroy({success : function() {
|
this.userLike().destroy({success : function() {
|
||||||
self.trigger('change');
|
self.trigger('change');
|
||||||
self.set({"likes_count" : self.get("likes_count") - 1});
|
self.set({"likes_count" : self.get("likes_count") - 1});
|
||||||
|
self.likes.trigger("change");
|
||||||
}});
|
}});
|
||||||
|
|
||||||
app.instrument("track", "Unlike");
|
app.instrument("track", "Unlike");
|
||||||
},
|
},
|
||||||
|
|
||||||
comment : function (text) {
|
comment: function(text, options) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
this.comments.make(text).fail(function () {
|
this.comments.make(text).fail(function(response) {
|
||||||
app.flashMessages.error(Diaspora.I18n.t("failed_to_comment"));
|
app.flashMessages.handleAjaxError(response);
|
||||||
|
if (options.error) { options.error(); }
|
||||||
}).done(function() {
|
}).done(function() {
|
||||||
self.post.set({participation: true});
|
self.post.set({participation: true});
|
||||||
|
self.set({"comments_count": self.get("comments_count") + 1});
|
||||||
self.trigger('change'); //updates after sync
|
self.trigger('change'); //updates after sync
|
||||||
|
if (options.success) { options.success(); }
|
||||||
});
|
});
|
||||||
|
|
||||||
this.trigger("change"); //updates count in an eager manner
|
|
||||||
|
|
||||||
app.instrument("track", "Comment");
|
app.instrument("track", "Comment");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -116,9 +120,11 @@ app.models.Post.Interactions = Backbone.Model.extend({
|
||||||
app.stream.addNow(reshare);
|
app.stream.addNow(reshare);
|
||||||
}
|
}
|
||||||
interactions.trigger("change");
|
interactions.trigger("change");
|
||||||
|
interactions.set({"reshares_count": interactions.get("reshares_count") + 1});
|
||||||
|
interactions.reshares.trigger("change");
|
||||||
})
|
})
|
||||||
.fail(function(){
|
.fail(function(response) {
|
||||||
app.flashMessages.error(Diaspora.I18n.t("reshares.duplicate"));
|
app.flashMessages.handleAjaxError(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.instrument("track", "Reshare");
|
app.instrument("track", "Reshare");
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,9 @@ app.pages.Contacts = Backbone.View.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
showMessageModal: function(){
|
showMessageModal: function(){
|
||||||
|
$("#conversationModal").on("modal:loaded", function() {
|
||||||
|
new app.views.ConversationsForm({prefill: gon.conversationPrefill});
|
||||||
|
});
|
||||||
app.helpers.showModal("#conversationModal");
|
app.helpers.showModal("#conversationModal");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ app.pages.Profile = app.views.Base.extend({
|
||||||
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;
|
||||||
|
|
||||||
this.model.on("change", this.render, this);
|
|
||||||
this.model.on("sync", this._done, this);
|
this.model.on("sync", this._done, this);
|
||||||
|
|
||||||
// bind to global events
|
// bind to global events
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ app.Router = Backbone.Router.extend({
|
||||||
notifications: function() {
|
notifications: function() {
|
||||||
this._loadContacts();
|
this._loadContacts();
|
||||||
this.renderAspectMembershipDropdowns($(document));
|
this.renderAspectMembershipDropdowns($(document));
|
||||||
new app.views.Notifications({el: "#notifications_container"});
|
new app.views.Notifications({el: "#notifications_container", collection: app.notificationsCollection});
|
||||||
},
|
},
|
||||||
|
|
||||||
peopleSearch: function() {
|
peopleSearch: function() {
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ app.views.AspectMembership = app.views.Base.extend({
|
||||||
_displayError: function(model, resp) {
|
_displayError: function(model, resp) {
|
||||||
this._done();
|
this._done();
|
||||||
this.dropdown.closest(".aspect_membership_dropdown").removeClass("open"); // close the dropdown
|
this.dropdown.closest(".aspect_membership_dropdown").removeClass("open"); // close the dropdown
|
||||||
app.flashMessages.error(resp.responseText);
|
app.flashMessages.handleAjaxError(resp);
|
||||||
},
|
},
|
||||||
|
|
||||||
// remove the membership with the given id
|
// remove the membership with the given id
|
||||||
|
|
@ -134,7 +134,7 @@ app.views.AspectMembership = app.views.Base.extend({
|
||||||
this.listenToOnce(membership, "sync", this._successDestroyCb);
|
this.listenToOnce(membership, "sync", this._successDestroyCb);
|
||||||
this.listenToOnce(membership, "error", this._displayError);
|
this.listenToOnce(membership, "error", this._displayError);
|
||||||
|
|
||||||
return membership.destroy();
|
return membership.destroy({wait: true});
|
||||||
},
|
},
|
||||||
|
|
||||||
_successDestroyCb: function(aspectMembership) {
|
_successDestroyCb: function(aspectMembership) {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ app.views.CommentStream = app.views.Base.extend({
|
||||||
|
|
||||||
postRenderTemplate : function() {
|
postRenderTemplate : function() {
|
||||||
this.model.comments.each(this.appendComment, this);
|
this.model.comments.each(this.appendComment, this);
|
||||||
|
this.commentBox = this.$(".comment_box");
|
||||||
|
this.commentSubmitButton = this.$("input[name='commit']");
|
||||||
},
|
},
|
||||||
|
|
||||||
presenter: function(){
|
presenter: function(){
|
||||||
|
|
@ -38,15 +40,35 @@ app.views.CommentStream = app.views.Base.extend({
|
||||||
createComment: function(evt) {
|
createComment: function(evt) {
|
||||||
if(evt){ evt.preventDefault(); }
|
if(evt){ evt.preventDefault(); }
|
||||||
|
|
||||||
var commentText = $.trim(this.$('.comment_box').val());
|
var commentText = $.trim(this.commentBox.val());
|
||||||
this.$(".comment_box").val("");
|
if (commentText === "") {
|
||||||
this.$(".comment_box").css("height", "");
|
this.commentBox.focus();
|
||||||
if(commentText) {
|
return;
|
||||||
this.model.comment(commentText);
|
|
||||||
return this;
|
|
||||||
} else {
|
|
||||||
this.$(".comment_box").focus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.disableCommentBox();
|
||||||
|
|
||||||
|
this.model.comment(commentText, {
|
||||||
|
success: function() {
|
||||||
|
this.commentBox.val("");
|
||||||
|
this.enableCommentBox();
|
||||||
|
autosize.update(this.commentBox);
|
||||||
|
}.bind(this),
|
||||||
|
error: function() {
|
||||||
|
this.enableCommentBox();
|
||||||
|
this.commentBox.focus();
|
||||||
|
}.bind(this)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
disableCommentBox: function() {
|
||||||
|
this.commentBox.prop("disabled", true);
|
||||||
|
this.commentSubmitButton.prop("disabled", true);
|
||||||
|
},
|
||||||
|
|
||||||
|
enableCommentBox: function() {
|
||||||
|
this.commentBox.removeAttr("disabled");
|
||||||
|
this.commentSubmitButton.removeAttr("disabled");
|
||||||
},
|
},
|
||||||
|
|
||||||
keyDownOnCommentBox: function(evt) {
|
keyDownOnCommentBox: function(evt) {
|
||||||
|
|
@ -104,10 +126,12 @@ app.views.CommentStream = app.views.Base.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
expandComments: function(evt){
|
expandComments: function(evt){
|
||||||
|
this.$(".loading-comments").removeClass("hidden");
|
||||||
if(evt){ evt.preventDefault(); }
|
if(evt){ evt.preventDefault(); }
|
||||||
this.model.comments.fetch({
|
this.model.comments.fetch({
|
||||||
success: function() {
|
success: function() {
|
||||||
this.$("div.comment.show_comments").addClass("hidden");
|
this.$("div.comment.show_comments").addClass("hidden");
|
||||||
|
this.$(".loading-comments").addClass("hidden");
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,40 +5,83 @@ app.views.ConversationsForm = Backbone.View.extend({
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
"keydown .conversation-message-text": "keyDown",
|
"keydown .conversation-message-text": "keyDown",
|
||||||
|
"click .conversation-recipient-tag .remove": "removeRecipient"
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function(opts) {
|
initialize: function(opts) {
|
||||||
this.contacts = _.has(opts, "contacts") ? opts.contacts : null;
|
opts = opts || {};
|
||||||
this.prefill = [];
|
this.conversationRecipients = [];
|
||||||
if (_.has(opts, "prefillName") && _.has(opts, "prefillValue")) {
|
|
||||||
this.prefill = [{name: opts.prefillName, value: opts.prefillValue}];
|
this.typeaheadElement = this.$el.find("#contacts-search-input");
|
||||||
|
this.contactsIdsListInput = this.$el.find("#contact-ids");
|
||||||
|
this.tagListElement = this.$("#recipients-tag-list");
|
||||||
|
|
||||||
|
this.search = new app.views.SearchBase({
|
||||||
|
el: this.$el.find("#new-conversation"),
|
||||||
|
typeaheadInput: this.typeaheadElement,
|
||||||
|
customSearch: true,
|
||||||
|
autoselect: true,
|
||||||
|
remoteRoute: {url: "/contacts", extraParameters: "mutual=true"}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bindTypeaheadEvents();
|
||||||
|
|
||||||
|
this.tagListElement.empty();
|
||||||
|
if (opts.prefill) {
|
||||||
|
this.prefill(opts.prefill);
|
||||||
}
|
}
|
||||||
this.prepareAutocomplete(this.contacts);
|
|
||||||
this.$("form#new-conversation").on("ajax:success", this.conversationCreateSuccess);
|
this.$("form#new-conversation").on("ajax:success", this.conversationCreateSuccess);
|
||||||
this.$("form#new-conversation").on("ajax:error", this.conversationCreateError);
|
this.$("form#new-conversation").on("ajax:error", this.conversationCreateError);
|
||||||
},
|
},
|
||||||
|
|
||||||
prepareAutocomplete: function(data){
|
addRecipient: function(person) {
|
||||||
this.$("#contact-autocomplete").autoSuggest(data, {
|
this.conversationRecipients.push(person);
|
||||||
selectedItemProp: "name",
|
this.updateContactIdsListInput();
|
||||||
searchObjProps: "name",
|
/* eslint-disable camelcase */
|
||||||
asHtmlID: "contact_ids",
|
this.tagListElement.append(HandlebarsTemplates.conversation_recipient_tag_tpl(person));
|
||||||
retrieveLimit: 10,
|
/* eslint-enable camelcase */
|
||||||
minChars: 1,
|
|
||||||
keyDelay: 0,
|
|
||||||
startText: '',
|
|
||||||
emptyText: Diaspora.I18n.t("no_results"),
|
|
||||||
preFill: this.prefill
|
|
||||||
});
|
|
||||||
$("#contact_ids").attr("aria-labelledby", "toLabel").focus();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
keyDown : function(evt) {
|
prefill: function(handles) {
|
||||||
if(evt.which === Keycodes.ENTER && evt.ctrlKey) {
|
handles.forEach(this.addRecipient.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
updateContactIdsListInput: function() {
|
||||||
|
this.contactsIdsListInput.val(_(this.conversationRecipients).pluck("id").join(","));
|
||||||
|
this.search.ignoreDiasporaIds.length = 0;
|
||||||
|
this.conversationRecipients.forEach(this.search.ignorePersonForSuggestions.bind(this.search));
|
||||||
|
},
|
||||||
|
|
||||||
|
bindTypeaheadEvents: function() {
|
||||||
|
this.typeaheadElement.on("typeahead:select", function(evt, person) {
|
||||||
|
this.onSuggestionSelection(person);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
onSuggestionSelection: function(person) {
|
||||||
|
this.addRecipient(person);
|
||||||
|
this.typeaheadElement.typeahead("val", "");
|
||||||
|
},
|
||||||
|
|
||||||
|
keyDown: function(evt) {
|
||||||
|
if (evt.which === Keycodes.ENTER && evt.ctrlKey) {
|
||||||
$(evt.target).parents("form").submit();
|
$(evt.target).parents("form").submit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeRecipient: function(evt) {
|
||||||
|
var $recipientTagEl = $(evt.target).parents(".conversation-recipient-tag");
|
||||||
|
var diasporaHandle = $recipientTagEl.data("diaspora-handle");
|
||||||
|
|
||||||
|
this.conversationRecipients = this.conversationRecipients.filter(function(person) {
|
||||||
|
return diasporaHandle !== person.handle;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.updateContactIdsListInput();
|
||||||
|
$recipientTagEl.remove();
|
||||||
|
},
|
||||||
|
|
||||||
conversationCreateSuccess: function(evt, data) {
|
conversationCreateSuccess: function(evt, data) {
|
||||||
app._changeLocation(Routes.conversation(data.id));
|
app._changeLocation(Routes.conversation(data.id));
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ app.views.ConversationsInbox = Backbone.View.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
new app.views.ConversationsForm({contacts: gon.contacts});
|
new app.views.ConversationsForm();
|
||||||
this.setupConversation();
|
this.setupConversation();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,13 @@ app.views.FlashMessages = app.views.Base.extend({
|
||||||
|
|
||||||
error: function(message){
|
error: function(message){
|
||||||
this._flash(message, true);
|
this._flash(message, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
handleAjaxError: function(response) {
|
||||||
|
if (response.status === 0) {
|
||||||
|
this.error(Diaspora.I18n.t("errors.connection"));
|
||||||
|
} else {
|
||||||
|
this.error(response.responseText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@ app.views.Header = app.views.Base.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
postRenderTemplate: function(){
|
postRenderTemplate: function() {
|
||||||
new app.views.Notifications({ el: "#notification-dropdown" });
|
new app.views.Notifications({el: "#notification-dropdown", collection: app.notificationsCollection});
|
||||||
this.notificationDropdown = new app.views.NotificationDropdown({ el: "#notification-dropdown" });
|
new app.views.NotificationDropdown({el: "#notification-dropdown", collection: app.notificationsCollection});
|
||||||
new app.views.Search({ el: "#header-search-form" });
|
new app.views.Search({el: "#header-search-form"});
|
||||||
},
|
},
|
||||||
|
|
||||||
menuElement: function(){ return this.$("ul.dropdown"); },
|
menuElement: function() { return this.$("ul.dropdown"); }
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ app.views.LikesInfo = app.views.Base.extend({
|
||||||
tooltipSelector : ".avatar",
|
tooltipSelector : ".avatar",
|
||||||
|
|
||||||
initialize : function() {
|
initialize : function() {
|
||||||
this.model.interactions.bind('change', this.render, this);
|
this.model.interactions.likes.on("change", this.render, this);
|
||||||
this.displayAvatars = false;
|
this.displayAvatars = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -19,18 +19,16 @@ app.views.LikesInfo = app.views.Base.extend({
|
||||||
return _.extend(this.defaultPresenter(), {
|
return _.extend(this.defaultPresenter(), {
|
||||||
likes : this.model.interactions.likes.toJSON(),
|
likes : this.model.interactions.likes.toJSON(),
|
||||||
likesCount : this.model.interactions.likesCount(),
|
likesCount : this.model.interactions.likesCount(),
|
||||||
displayAvatars : this.model.interactions.get("fetched") && this.displayAvatars
|
displayAvatars: this.displayAvatars
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
showAvatars : function(evt){
|
showAvatars : function(evt){
|
||||||
if(evt) { evt.preventDefault() }
|
if(evt) { evt.preventDefault() }
|
||||||
this.displayAvatars = true;
|
this.displayAvatars = true;
|
||||||
if(!this.model.interactions.get("fetched")){
|
this.model.interactions.likes.fetch({success: function() {
|
||||||
this.model.interactions.fetch();
|
this.model.interactions.likes.trigger("change");
|
||||||
} else {
|
}.bind(this)});
|
||||||
this.model.interactions.trigger("change");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,21 @@ app.views.NotificationDropdown = app.views.Base.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function(){
|
initialize: function(){
|
||||||
$(document.body).click($.proxy(this.hideDropdown, this));
|
$(document.body).click(this.hideDropdown.bind(this));
|
||||||
|
|
||||||
this.notifications = [];
|
|
||||||
this.perPage = 5;
|
|
||||||
this.hasMoreNotifs = true;
|
|
||||||
this.badge = this.$el;
|
this.badge = this.$el;
|
||||||
this.dropdown = $("#notification-dropdown");
|
this.dropdown = $("#notification-dropdown");
|
||||||
this.dropdownNotifications = this.dropdown.find(".notifications");
|
this.dropdownNotifications = this.dropdown.find(".notifications");
|
||||||
this.ajaxLoader = this.dropdown.find(".ajax-loader");
|
this.ajaxLoader = this.dropdown.find(".ajax-loader");
|
||||||
this.perfectScrollbarInitialized = false;
|
this.perfectScrollbarInitialized = false;
|
||||||
|
this.dropdownNotifications.scroll(this.dropdownScroll.bind(this));
|
||||||
|
this.bindCollectionEvents();
|
||||||
|
},
|
||||||
|
|
||||||
|
bindCollectionEvents: function() {
|
||||||
|
this.collection.on("pushFront", this.onPushFront.bind(this));
|
||||||
|
this.collection.on("pushBack", this.onPushBack.bind(this));
|
||||||
|
this.collection.on("finishedLoading", this.finishLoading.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleDropdown: function(evt){
|
toggleDropdown: function(evt){
|
||||||
|
|
@ -31,12 +36,11 @@ app.views.NotificationDropdown = app.views.Base.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
showDropdown: function(){
|
showDropdown: function(){
|
||||||
this.resetParams();
|
|
||||||
this.ajaxLoader.show();
|
this.ajaxLoader.show();
|
||||||
this.dropdown.addClass("dropdown-open");
|
this.dropdown.addClass("dropdown-open");
|
||||||
this.updateScrollbar();
|
this.updateScrollbar();
|
||||||
this.dropdownNotifications.addClass("loading");
|
this.dropdownNotifications.addClass("loading");
|
||||||
this.getNotifications();
|
this.collection.fetch();
|
||||||
},
|
},
|
||||||
|
|
||||||
hideDropdown: function(evt){
|
hideDropdown: function(evt){
|
||||||
|
|
@ -50,40 +54,18 @@ app.views.NotificationDropdown = app.views.Base.extend({
|
||||||
|
|
||||||
dropdownScroll: function(){
|
dropdownScroll: function(){
|
||||||
var isLoading = ($(".loading").length === 1);
|
var isLoading = ($(".loading").length === 1);
|
||||||
if (this.isBottom() && this.hasMoreNotifs && !isLoading){
|
if (this.isBottom() && !isLoading) {
|
||||||
this.dropdownNotifications.addClass("loading");
|
this.dropdownNotifications.addClass("loading");
|
||||||
this.getNotifications();
|
this.collection.fetchMore();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getParams: function(){
|
|
||||||
if(this.notifications.length === 0){ return{ per_page: 10, page: 1 }; }
|
|
||||||
else{ return{ per_page: this.perPage, page: this.nextPage }; }
|
|
||||||
},
|
|
||||||
|
|
||||||
resetParams: function(){
|
|
||||||
this.notifications.length = 0;
|
|
||||||
this.hasMoreNotifs = true;
|
|
||||||
delete this.nextPage;
|
|
||||||
},
|
|
||||||
|
|
||||||
isBottom: function(){
|
isBottom: function(){
|
||||||
var bottom = this.dropdownNotifications.prop("scrollHeight") - this.dropdownNotifications.height();
|
var bottom = this.dropdownNotifications.prop("scrollHeight") - this.dropdownNotifications.height();
|
||||||
var currentPosition = this.dropdownNotifications.scrollTop();
|
var currentPosition = this.dropdownNotifications.scrollTop();
|
||||||
return currentPosition + 50 >= bottom;
|
return currentPosition + 50 >= bottom;
|
||||||
},
|
},
|
||||||
|
|
||||||
getNotifications: function(){
|
|
||||||
var self = this;
|
|
||||||
$.getJSON(Routes.notifications(this.getParams()), function(notifications){
|
|
||||||
$.each(notifications, function(){ self.notifications.push(this); });
|
|
||||||
self.hasMoreNotifs = notifications.length >= self.perPage;
|
|
||||||
if(self.nextPage){ self.nextPage++; }
|
|
||||||
else { self.nextPage = 3; }
|
|
||||||
self.renderNotifications();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
hideAjaxLoader: function(){
|
hideAjaxLoader: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
this.ajaxLoader.find(".spinner").fadeTo(200, 0, function(){
|
this.ajaxLoader.find(".spinner").fadeTo(200, 0, function(){
|
||||||
|
|
@ -93,28 +75,23 @@ app.views.NotificationDropdown = app.views.Base.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
renderNotifications: function(){
|
onPushBack: function(notification) {
|
||||||
var self = this;
|
var node = this.dropdownNotifications.append(notification.get("note_html"));
|
||||||
this.dropdownNotifications.find(".media.stream-element").remove();
|
$(node).find(".unread-toggle .entypo-eye").tooltip("destroy").tooltip();
|
||||||
$.each(self.notifications, function(index, notifications){
|
$(node).find(this.avatars.selector).error(this.avatars.fallback);
|
||||||
$.each(notifications, function(index, notification){
|
},
|
||||||
if($.inArray(notification, notifications) === -1){
|
|
||||||
var node = self.dropdownNotifications.append(notification.note_html);
|
|
||||||
$(node).find(".unread-toggle .entypo-eye").tooltip("destroy").tooltip();
|
|
||||||
$(node).find(self.avatars.selector).error(self.avatars.fallback);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.hideAjaxLoader();
|
onPushFront: function(notification) {
|
||||||
|
var node = this.dropdownNotifications.prepend(notification.get("note_html"));
|
||||||
|
$(node).find(".unread-toggle .entypo-eye").tooltip("destroy").tooltip();
|
||||||
|
$(node).find(this.avatars.selector).error(this.avatars.fallback);
|
||||||
|
},
|
||||||
|
|
||||||
|
finishLoading: function() {
|
||||||
app.helpers.timeago(this.dropdownNotifications);
|
app.helpers.timeago(this.dropdownNotifications);
|
||||||
|
|
||||||
this.updateScrollbar();
|
this.updateScrollbar();
|
||||||
|
this.hideAjaxLoader();
|
||||||
this.dropdownNotifications.removeClass("loading");
|
this.dropdownNotifications.removeClass("loading");
|
||||||
this.dropdownNotifications.scroll(function(){
|
|
||||||
self.dropdownScroll();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
updateScrollbar: function() {
|
updateScrollbar: function() {
|
||||||
|
|
|
||||||
|
|
@ -1,96 +1,85 @@
|
||||||
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
||||||
|
|
||||||
app.views.Notifications = Backbone.View.extend({
|
app.views.Notifications = Backbone.View.extend({
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
"click .unread-toggle" : "toggleUnread",
|
"click .unread-toggle": "toggleUnread",
|
||||||
"click #mark_all_read_link": "markAllRead"
|
"click #mark-all-read-link": "markAllRead"
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
$(".unread-toggle .entypo-eye").tooltip();
|
$(".unread-toggle .entypo-eye").tooltip();
|
||||||
app.helpers.timeago($(document));
|
app.helpers.timeago($(document));
|
||||||
|
this.bindCollectionEvents();
|
||||||
|
},
|
||||||
|
|
||||||
|
bindCollectionEvents: function() {
|
||||||
|
this.collection.on("change", this.onChangedUnreadStatus.bind(this));
|
||||||
|
this.collection.on("update", this.updateView.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleUnread: function(evt) {
|
toggleUnread: function(evt) {
|
||||||
var note = $(evt.target).closest(".stream-element");
|
var note = $(evt.target).closest(".stream-element");
|
||||||
var unread = note.hasClass("unread");
|
var unread = note.hasClass("unread");
|
||||||
var guid = note.data("guid");
|
var guid = note.data("guid");
|
||||||
if (unread){ this.setRead(guid); }
|
if (unread) {
|
||||||
else { this.setUnread(guid); }
|
this.collection.setRead(guid);
|
||||||
},
|
} else {
|
||||||
|
this.collection.setUnread(guid);
|
||||||
getAllUnread: function() { return $(".media.stream-element.unread"); },
|
|
||||||
|
|
||||||
setRead: function(guid) { this.setUnreadStatus(guid, false); },
|
|
||||||
|
|
||||||
setUnread: function(guid){ this.setUnreadStatus(guid, true); },
|
|
||||||
|
|
||||||
setUnreadStatus: function(guid, state){
|
|
||||||
$.ajax({
|
|
||||||
url: "/notifications/" + guid,
|
|
||||||
data: { set_unread: state },
|
|
||||||
type: "PUT",
|
|
||||||
context: this,
|
|
||||||
success: this.clickSuccess
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
clickSuccess: function(data) {
|
|
||||||
var guid = data.guid;
|
|
||||||
var type = $(".stream-element[data-guid=" + guid + "]").data("type");
|
|
||||||
this.updateView(guid, type, data.unread);
|
|
||||||
},
|
|
||||||
|
|
||||||
markAllRead: function(evt){
|
|
||||||
if(evt) { evt.preventDefault(); }
|
|
||||||
var self = this;
|
|
||||||
this.getAllUnread().each(function(i, el){
|
|
||||||
self.setRead($(el).data("guid"));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
updateView: function(guid, type, unread) {
|
|
||||||
var change = unread ? 1 : -1,
|
|
||||||
allNotes = $("#notifications_container .list-group > a:eq(0) .badge"),
|
|
||||||
typeNotes = $("#notifications_container .list-group > a[data-type=" + type + "] .badge"),
|
|
||||||
headerBadge = $(".notifications-link .badge"),
|
|
||||||
note = $(".notifications .stream-element[data-guid=" + guid + "]"),
|
|
||||||
markAllReadLink = $("a#mark_all_read_link"),
|
|
||||||
translationKey = unread ? "notifications.mark_read" : "notifications.mark_unread";
|
|
||||||
|
|
||||||
if(unread){ note.removeClass("read").addClass("unread"); }
|
|
||||||
else { note.removeClass("unread").addClass("read"); }
|
|
||||||
|
|
||||||
$(".unread-toggle .entypo-eye", note)
|
|
||||||
.tooltip("destroy")
|
|
||||||
.removeAttr("data-original-title")
|
|
||||||
.attr("title",Diaspora.I18n.t(translationKey))
|
|
||||||
.tooltip();
|
|
||||||
|
|
||||||
[allNotes, typeNotes, headerBadge].forEach(function(element){
|
|
||||||
element.text(function(i, text){
|
|
||||||
return parseInt(text) + change;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
[allNotes, typeNotes].forEach(function(badge) {
|
|
||||||
if(badge.text() > 0) {
|
|
||||||
badge.removeClass("hidden");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
badge.addClass("hidden");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if(headerBadge.text() > 0){
|
|
||||||
headerBadge.removeClass("hidden");
|
|
||||||
markAllReadLink.removeClass("disabled");
|
|
||||||
}
|
}
|
||||||
else{
|
},
|
||||||
headerBadge.addClass("hidden");
|
|
||||||
|
markAllRead: function() {
|
||||||
|
this.collection.setAllRead();
|
||||||
|
},
|
||||||
|
|
||||||
|
onChangedUnreadStatus: function(model) {
|
||||||
|
var unread = model.get("unread");
|
||||||
|
var translationKey = unread ? "notifications.mark_read" : "notifications.mark_unread";
|
||||||
|
var note = $(".stream-element[data-guid=" + model.guid + "]");
|
||||||
|
|
||||||
|
note.find(".entypo-eye")
|
||||||
|
.tooltip("destroy")
|
||||||
|
.removeAttr("data-original-title")
|
||||||
|
.attr("title", Diaspora.I18n.t(translationKey))
|
||||||
|
.tooltip();
|
||||||
|
|
||||||
|
if (unread) {
|
||||||
|
note.removeClass("read").addClass("unread");
|
||||||
|
} else {
|
||||||
|
note.removeClass("unread").addClass("read");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateView: function() {
|
||||||
|
var notificationsContainer = $("#notifications_container");
|
||||||
|
|
||||||
|
// update notification counts in the sidebar
|
||||||
|
Object.keys(this.collection.unreadCountByType).forEach(function(notificationType) {
|
||||||
|
var count = this.collection.unreadCountByType[notificationType];
|
||||||
|
this.updateBadge(notificationsContainer.find("a[data-type=" + notificationType + "] .badge"), count);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
this.updateBadge(notificationsContainer.find("a[data-type=all] .badge"), this.collection.unreadCount);
|
||||||
|
|
||||||
|
// update notification count in the header
|
||||||
|
this.updateBadge($(".notifications-link .badge"), this.collection.unreadCount);
|
||||||
|
|
||||||
|
var markAllReadLink = $("a#mark-all-read-link");
|
||||||
|
|
||||||
|
if (this.collection.unreadCount > 0) {
|
||||||
|
markAllReadLink.removeClass("disabled");
|
||||||
|
} else {
|
||||||
markAllReadLink.addClass("disabled");
|
markAllReadLink.addClass("disabled");
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateBadge: function(badge, count) {
|
||||||
|
badge.text(count);
|
||||||
|
if (count > 0) {
|
||||||
|
badge.removeClass("hidden");
|
||||||
|
} else {
|
||||||
|
badge.addClass("hidden");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ 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.contacts = _.has(opts, 'contacts') ? opts.contacts : null;
|
||||||
|
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);
|
||||||
},
|
},
|
||||||
|
|
@ -79,8 +80,11 @@ app.views.ProfileHeader = app.views.Base.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
showMessageModal: function(){
|
showMessageModal: function(){
|
||||||
|
$("#conversationModal").on("modal:loaded", function() {
|
||||||
|
new app.views.ConversationsForm({prefill: gon.conversationPrefill});
|
||||||
|
});
|
||||||
app.helpers.showModal("#conversationModal");
|
app.helpers.showModal("#conversationModal");
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ app.views.PublisherMention = app.views.SearchBase.extend({
|
||||||
typeaheadInput: this.typeaheadInput,
|
typeaheadInput: this.typeaheadInput,
|
||||||
customSearch: true,
|
customSearch: true,
|
||||||
autoselect: true,
|
autoselect: true,
|
||||||
remoteRoute: "/contacts"
|
remoteRoute: {url: "/contacts"}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ app.views.ResharesInfo = app.views.Base.extend({
|
||||||
tooltipSelector : ".avatar",
|
tooltipSelector : ".avatar",
|
||||||
|
|
||||||
initialize : function() {
|
initialize : function() {
|
||||||
this.model.interactions.bind("change", this.render, this);
|
this.model.interactions.reshares.bind("change", this.render, this);
|
||||||
this.displayAvatars = false;
|
this.displayAvatars = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -19,18 +19,16 @@ app.views.ResharesInfo = app.views.Base.extend({
|
||||||
return _.extend(this.defaultPresenter(), {
|
return _.extend(this.defaultPresenter(), {
|
||||||
reshares : this.model.interactions.reshares.toJSON(),
|
reshares : this.model.interactions.reshares.toJSON(),
|
||||||
resharesCount : this.model.interactions.resharesCount(),
|
resharesCount : this.model.interactions.resharesCount(),
|
||||||
displayAvatars : this.model.interactions.get("fetched") && this.displayAvatars
|
displayAvatars: this.displayAvatars
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
showAvatars : function(evt){
|
showAvatars : function(evt){
|
||||||
if(evt) { evt.preventDefault() }
|
if(evt) { evt.preventDefault() }
|
||||||
this.displayAvatars = true;
|
this.displayAvatars = true;
|
||||||
if(!this.model.interactions.get("fetched")){
|
this.model.interactions.reshares.fetch({success: function() {
|
||||||
this.model.interactions.fetch();
|
this.model.interactions.reshares.trigger("change");
|
||||||
} else {
|
}.bind(this)});
|
||||||
this.model.interactions.trigger("change");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,13 @@ app.views.SearchBase = app.views.Base.extend({
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allow bloodhound to look for remote results if there is a route given in the options
|
// Allow bloodhound to look for remote results if there is a route given in the options
|
||||||
if(options.remoteRoute) {
|
if (options.remoteRoute && options.remoteRoute.url) {
|
||||||
|
var extraParameters = "";
|
||||||
|
if (options.remoteRoute.extraParameters) {
|
||||||
|
extraParameters += "&" + options.remoteRoute.extraParameters;
|
||||||
|
}
|
||||||
bloodhoundOptions.remote = {
|
bloodhoundOptions.remote = {
|
||||||
url: options.remoteRoute + ".json?q=%QUERY",
|
url: options.remoteRoute.url + ".json?q=%QUERY" + extraParameters,
|
||||||
wildcard: "%QUERY",
|
wildcard: "%QUERY",
|
||||||
transform: this.transformBloodhoundResponse.bind(this)
|
transform: this.transformBloodhoundResponse.bind(this)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ app.views.Search = app.views.SearchBase.extend({
|
||||||
this.searchInput = this.$("#q");
|
this.searchInput = this.$("#q");
|
||||||
app.views.SearchBase.prototype.initialize.call(this, {
|
app.views.SearchBase.prototype.initialize.call(this, {
|
||||||
typeaheadInput: this.searchInput,
|
typeaheadInput: this.searchInput,
|
||||||
remoteRoute: this.$el.attr("action"),
|
remoteRoute: {url: this.$el.attr("action")},
|
||||||
suggestionLink: true
|
suggestionLink: true
|
||||||
});
|
});
|
||||||
this.searchInput.on("typeahead:select", this.suggestionSelected);
|
this.searchInput.on("typeahead:select", this.suggestionSelected);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ app.views.Tags = Backbone.View.extend({
|
||||||
if(app.publisher) {
|
if(app.publisher) {
|
||||||
app.publisher.setText("#"+ opts.hashtagName + " ");
|
app.publisher.setText("#"+ opts.hashtagName + " ");
|
||||||
}
|
}
|
||||||
|
// add avatar fallback if it can't be loaded
|
||||||
|
$(app.views.Base.prototype.avatars.selector).error(app.views.Base.prototype.avatars.fallback);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
|
||||||
22
app/assets/javascripts/helpers/browser_notification.js
Normal file
22
app/assets/javascripts/helpers/browser_notification.js
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
Diaspora.BrowserNotification = {
|
||||||
|
requestPermission: function() {
|
||||||
|
if ("Notification" in window && Notification.permission !== "granted" && Notification.permission !== "denied") {
|
||||||
|
Notification.requestPermission();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
spawnNotification: function(title, summary) {
|
||||||
|
if ("Notification" in window && Notification.permission === "granted") {
|
||||||
|
if (!_.isString(title)) {
|
||||||
|
throw new Error("No notification title given.");
|
||||||
|
}
|
||||||
|
|
||||||
|
summary = summary || "";
|
||||||
|
|
||||||
|
new Notification(title, {
|
||||||
|
body: summary,
|
||||||
|
icon: ImagePaths.get("branding/logos/asterisk_white_mobile.png")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -18,7 +18,7 @@ Diaspora.I18n = {
|
||||||
},
|
},
|
||||||
|
|
||||||
updateLocale: function(locale, data) {
|
updateLocale: function(locale, data) {
|
||||||
locale.data = $.extend(locale.data, data);
|
locale.data = $.extend({}, locale.data, data);
|
||||||
|
|
||||||
var rule = locale.data.pluralization_rule;
|
var rule = locale.data.pluralization_rule;
|
||||||
if (typeof rule !== "undefined") {
|
if (typeof rule !== "undefined") {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
// initialize jsxc xmpp client
|
// initialize jsxc xmpp client
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
if (app.currentUser.authenticated()) {
|
if (app.currentUser.authenticated()) {
|
||||||
$.post('api/v1/tokens', null, function(data) {
|
$.post("/user/auth_token", null, function(data) {
|
||||||
if (jsxc && data['token']) {
|
if (jsxc && data['token']) {
|
||||||
var jid = app.currentUser.get('diaspora_id');
|
var jid = app.currentUser.get('diaspora_id');
|
||||||
jsxc.init({
|
jsxc.init({
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
//= require markdown-it-sup
|
//= require markdown-it-sup
|
||||||
//= require highlightjs
|
//= require highlightjs
|
||||||
//= require clear-form
|
//= require clear-form
|
||||||
//= require typeahead.bundle.js
|
//= require corejs-typeahead
|
||||||
//= require app/app
|
//= require app/app
|
||||||
//= require diaspora
|
//= require diaspora
|
||||||
//= require_tree ./helpers
|
//= require_tree ./helpers
|
||||||
|
|
|
||||||
|
|
@ -98,8 +98,12 @@
|
||||||
success: function() {
|
success: function() {
|
||||||
Diaspora.Mobile.PostActions.toggleActive(link);
|
Diaspora.Mobile.PostActions.toggleActive(link);
|
||||||
},
|
},
|
||||||
error: function() {
|
error: function(response) {
|
||||||
alert(Diaspora.I18n.t("failed_to_reshare"));
|
if (response.status === 0) {
|
||||||
|
alert(Diaspora.I18n.t("errors.connection"));
|
||||||
|
} else {
|
||||||
|
alert(response.responseText);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
complete: function() {
|
complete: function() {
|
||||||
Diaspora.Mobile.PostActions.hideLoader(link);
|
Diaspora.Mobile.PostActions.hideLoader(link);
|
||||||
|
|
|
||||||
|
|
@ -187,9 +187,9 @@ $btn-success-color: #333 !default;
|
||||||
// $input-bg-disabled: $gray-lighter
|
// $input-bg-disabled: $gray-lighter
|
||||||
|
|
||||||
//** Text color for `<input>`s
|
//** Text color for `<input>`s
|
||||||
// $input-color: $gray
|
$input-color: $text-dark-grey !default;
|
||||||
//** `<input>` border color
|
//** `<input>` border color
|
||||||
// $input-border: #ccc
|
$input-border: $border-grey !default;
|
||||||
|
|
||||||
// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
|
// TODO: Rename `$input-border-radius` to `$input-border-radius-base` in v4
|
||||||
//** Default `.form-control` border radius
|
//** Default `.form-control` border radius
|
||||||
|
|
@ -202,6 +202,7 @@ $btn-success-color: #333 !default;
|
||||||
|
|
||||||
//** Border color for inputs on focus
|
//** Border color for inputs on focus
|
||||||
// $input-border-focus: #66afe9
|
// $input-border-focus: #66afe9
|
||||||
|
$input-border-focus: $input-border !default;
|
||||||
|
|
||||||
//** Placeholder text color
|
//** Placeholder text color
|
||||||
// $input-color-placeholder: #999
|
// $input-color-placeholder: #999
|
||||||
|
|
@ -668,7 +669,7 @@ $navbar-collapse-max-height: 480px;
|
||||||
//
|
//
|
||||||
//##
|
//##
|
||||||
//** Background color on `.list-group-item`
|
//** Background color on `.list-group-item`
|
||||||
$list-group-bg: $white;
|
$list-group-bg: $white !default;
|
||||||
//** `.list-group-item` border color
|
//** `.list-group-item` border color
|
||||||
$list-group-border: transparent;
|
$list-group-border: transparent;
|
||||||
//** List group border radius
|
//** List group border radius
|
||||||
|
|
|
||||||
|
|
@ -3,31 +3,32 @@ $black: #000;
|
||||||
|
|
||||||
$text-grey: #999;
|
$text-grey: #999;
|
||||||
$text-dark-grey: #666;
|
$text-dark-grey: #666;
|
||||||
$text: #333;
|
$text-color-pale: $text-grey !default;
|
||||||
|
$text-color-active: $black !default;
|
||||||
|
|
||||||
$background-white: $white;
|
$background-grey: #eee !default;
|
||||||
$background-grey: #eee;
|
$background-blue: #e7f2f7 !default;
|
||||||
$background-blue: #e7f2f7;
|
|
||||||
|
|
||||||
$grey: #2b2b2b;
|
$grey: #2b2b2b;
|
||||||
$medium-gray: #ccc;
|
$medium-gray: #ccc;
|
||||||
$light-grey: #ddd;
|
$light-grey: #ddd;
|
||||||
|
|
||||||
$border-grey: $light-grey;
|
$border-grey: $light-grey !default;
|
||||||
$border-medium-grey: $medium-gray;
|
$border-medium-grey: $medium-gray !default;
|
||||||
$border-dark-grey: $text-grey;
|
$border-dark-grey: $text-grey !default;
|
||||||
$border-medium-grey: #ccc;
|
|
||||||
|
|
||||||
$link-grey: #777;
|
$link-grey: #777;
|
||||||
$link-disabled-grey: $text-grey;
|
|
||||||
|
|
||||||
$green: #8ede3d;
|
$icon-color: $black !default;
|
||||||
|
|
||||||
|
$green: #8ede3d !default;
|
||||||
$light-green: lighten($green, 20%);
|
$light-green: lighten($green, 20%);
|
||||||
$red: #a80000;
|
$red: #a80000 !default;
|
||||||
$blue: #3f8fba;
|
$blue: #3f8fba !default;
|
||||||
|
|
||||||
$main-background: #f0f0f0 !default;
|
$main-background: darken($white, 6%) !default;
|
||||||
$sidebars-background: $background-white !default;
|
$framed-background: $white !default;
|
||||||
$left-navbar-drawer-background: darken($sidebars-background, 6%);
|
$left-navbar-drawer-background: darken($white, 6%) !default;
|
||||||
|
$hovercard-background: $white !default;
|
||||||
|
|
||||||
$card-shadow: 0 1px 2px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12) !default;
|
$card-shadow: 0 1px 2px 0 rgba(0, 0, 0, .16), 0 2px 10px 0 rgba(0, 0, 0, .12) !default;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
// Only overriding existing selectors here, so disable some lint rules
|
||||||
|
// scss-lint:disable IdSelector, SelectorFormat, NestingDepth, SelectorDepth, QualifyingElement
|
||||||
|
body {
|
||||||
|
.navbar.navbar-fixed-top #user_menu .dropdown-menu > li > a {
|
||||||
|
color: $text-color;
|
||||||
|
&:hover { color: $white; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.publisher {
|
||||||
|
.mentions-input-box { background-color: $gray; }
|
||||||
|
form {
|
||||||
|
#publisher_textarea_wrapper { background-color: $gray; }
|
||||||
|
.btn.btn-link.question_mark:hover .entypo-cog { color: $gray-light; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.write-preview-tabs > li.active * { color: $text-color; }
|
||||||
|
.md-preview { background-color: $gray; }
|
||||||
|
.md-cancel:hover .entypo-cross { color: $gray-light; }
|
||||||
|
.publisher-buttonbar .btn.btn-link:hover i { color: $gray-light; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.aspect_dropdown li a .text { color: $dropdown-link-color; }
|
||||||
|
|
||||||
|
.info .tag { background-color: $gray-light; }
|
||||||
|
|
||||||
|
.poll_form .progress {
|
||||||
|
background-color: $gray-dark;
|
||||||
|
.bar { background-color: $gray-light; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-element .collapsible {
|
||||||
|
.markdown-content hr { border-top: 1px solid $hr-border; }
|
||||||
|
.expander {
|
||||||
|
@include linear-gradient(transparent, $gray-light, 0%, 95%);
|
||||||
|
border-bottom: 2px solid $gray-light;
|
||||||
|
color: $text-color;
|
||||||
|
text-shadow: 0 0 7px $black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code,
|
||||||
|
pre {
|
||||||
|
background-color: $gray-dark;
|
||||||
|
border: 1px solid $border-medium-grey;
|
||||||
|
color: $text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code { border: 0; }
|
||||||
|
|
||||||
|
@import 'highlightjs/darcula';
|
||||||
|
|
||||||
|
#single-post-content .head {
|
||||||
|
#post-info .author { color: lighten($gray-lighter, 27%); }
|
||||||
|
#single-post-actions i.entypo-heart.red:hover { color: $red; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.opengraph a { color: lighten($gray-lighter, 27%); }
|
||||||
|
|
||||||
|
.tag:hover { background-color: desaturate(darken($blue, 35%), 20%); }
|
||||||
|
|
||||||
|
#profile_container .profile_header {
|
||||||
|
#author_info #sharing_message.entypo-check { color: lighten($green, 10%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#invitationsModal #email_invitation { border-top: 1px dashed $gray-light; }
|
||||||
|
|
||||||
|
#contacts_container #people_stream.contacts .stream-element.in_aspect {
|
||||||
|
background-color: $state-success-bg;
|
||||||
|
border-left: 3px solid darken($state-success-bg, 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-navbar #tags_list {
|
||||||
|
.as-list {
|
||||||
|
color: $text-color;
|
||||||
|
|
||||||
|
em {
|
||||||
|
background-color: lighten($background-blue, 10%);
|
||||||
|
color: $text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.as-result-item.active { color: $text-color; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#faq .question {
|
||||||
|
background-color: $gray-dark;
|
||||||
|
a.toggle { color: $gray-lighter; }
|
||||||
|
&.collapsed { border: 2px solid $gray-dark; }
|
||||||
|
&.opened {
|
||||||
|
border: 2px solid darken($green, 10%);
|
||||||
|
h4 { background-color: darken($green, 10%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.answer { background-color: $gray; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcome-to-diaspora { background: $orange; }
|
||||||
|
|
||||||
|
.block-form fieldset .form-control:focus { border-color: $input-border; }
|
||||||
|
|
||||||
|
&.page-registrations.action-new,
|
||||||
|
&.page-registrations.action-create {
|
||||||
|
.ball { filter: invert(100%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner { border-color: $gray-light transparent $gray-light $gray-light; }
|
||||||
|
|
||||||
|
// AutoSuggest CSS
|
||||||
|
ul.as-selections {
|
||||||
|
background-color: $framed-background;
|
||||||
|
|
||||||
|
li.as-selection-item,
|
||||||
|
li.as-selection-item.blur {
|
||||||
|
background-color: $gray-dark;
|
||||||
|
border: 1px solid $gray-darker;
|
||||||
|
box-shadow: 0 1px 1px $gray-darker;
|
||||||
|
color: $text-color;
|
||||||
|
text-shadow: 0 1px 1px $gray-darker;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.as-selection-item a.as-close,
|
||||||
|
li.as-selection-item.blur a.as-close {
|
||||||
|
color: $text-color;
|
||||||
|
text-shadow: 0 1px 1px $gray-darker;
|
||||||
|
}
|
||||||
|
|
||||||
|
li:hover.as-selection-item {
|
||||||
|
background-color: $light-blue;
|
||||||
|
border-color: $brand-primary;
|
||||||
|
color: $white;
|
||||||
|
a.as-close { color: $gray-light; }
|
||||||
|
}
|
||||||
|
|
||||||
|
li.as-selection-item.selected { border-color: $brand-primary; }
|
||||||
|
li.as-selection-item a:hover.as-close { color: $white; }
|
||||||
|
li.as-selection-item a:active.as-close { color: $gray-lighter; }
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.as-list {
|
||||||
|
background-color: $gray-dark;
|
||||||
|
box-shadow: 0 2px 12px $gray-light;
|
||||||
|
color: $text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.as-result-item,
|
||||||
|
li.as-message {
|
||||||
|
border: 1px solid $gray-dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
li.as-result-item.active {
|
||||||
|
background-color: $brand-primary;
|
||||||
|
border-color: $brand-primary;
|
||||||
|
text-shadow: none;
|
||||||
|
|
||||||
|
em { background: darken($brand-primary, 10%); }
|
||||||
|
}
|
||||||
|
// End AutoSuggest CSS
|
||||||
|
|
||||||
|
// Bootstrap Switch CSS
|
||||||
|
.bootstrap-switch {
|
||||||
|
border-color: $border-grey;
|
||||||
|
.bootstrap-switch-label { background: $framed-background; }
|
||||||
|
.bootstrap-switch-handle-on.bootstrap-switch-default,
|
||||||
|
.bootstrap-switch-handle-off.bootstrap-switch-default {
|
||||||
|
background: $gray-dark;
|
||||||
|
color: $text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// End Bootstrap Switch CSS
|
||||||
|
}
|
||||||
|
|
@ -17,10 +17,4 @@ body {
|
||||||
.left-navbar {
|
.left-navbar {
|
||||||
border-right: 1px solid $border-grey;
|
border-right: 1px solid $border-grey;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-sidebar-fixed-background,
|
|
||||||
.right-sidebar-fixed-background,
|
|
||||||
.rightbar {
|
|
||||||
border-left: 1px solid $sidebars-background;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
153
app/assets/stylesheets/color_themes/dark/_style.scss
Normal file
153
app/assets/stylesheets/color_themes/dark/_style.scss
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
// Main color(s)
|
||||||
|
$white: #fff;
|
||||||
|
$black: #000;
|
||||||
|
|
||||||
|
$gray-base: $black;
|
||||||
|
$gray-darker: lighten($gray-base, 6%);
|
||||||
|
$gray-dark: lighten($gray-base, 9.5%);
|
||||||
|
$gray: lighten($gray-base, 13.5%);
|
||||||
|
$gray-light: lighten($gray-base, 28%);
|
||||||
|
$gray-lighter: lighten($gray-base, 58%);
|
||||||
|
|
||||||
|
$green: #346535;
|
||||||
|
$red: #622;
|
||||||
|
$blue: #4183c4;
|
||||||
|
$yellow: #645a1b;
|
||||||
|
$orange: #664100;
|
||||||
|
|
||||||
|
$light-blue: lighten($blue, 5%);
|
||||||
|
|
||||||
|
$brand-primary: darken($blue, 5%);
|
||||||
|
$brand-success: $green;
|
||||||
|
$brand-info: darken(adjust-hue($brand-primary, -30), 15%);
|
||||||
|
$brand-danger: lighten($red, 10%);
|
||||||
|
|
||||||
|
// Bootstrap Variables
|
||||||
|
//== Scaffolding
|
||||||
|
$body-bg: $gray;
|
||||||
|
$text-color: lighten($gray-lighter, 17%);
|
||||||
|
$link-color: $blue;
|
||||||
|
|
||||||
|
//== Tables
|
||||||
|
$table-bg-accent: $gray-dark;
|
||||||
|
$table-border-color: $gray-light;
|
||||||
|
|
||||||
|
//== Buttons
|
||||||
|
$btn-default-color: $gray-lighter;
|
||||||
|
$btn-default-bg: $gray-light;
|
||||||
|
$btn-default-border: $gray-darker;
|
||||||
|
|
||||||
|
$btn-success-color: $white;
|
||||||
|
|
||||||
|
//== Forms
|
||||||
|
$input-bg: $gray-dark;
|
||||||
|
|
||||||
|
$input-color: $text-color;
|
||||||
|
$input-border: $gray-light;
|
||||||
|
$input-border-focus: $brand-primary;
|
||||||
|
|
||||||
|
$input-color-placeholder: lighten($gray-light, 7%);
|
||||||
|
|
||||||
|
$legend-color: $text-color;
|
||||||
|
$legend-border-color: $gray-light;
|
||||||
|
|
||||||
|
//== Dropdowns
|
||||||
|
$dropdown-bg: lighten($gray-base, 15%);
|
||||||
|
$dropdown-divider-bg: $gray-darker;
|
||||||
|
$dropdown-link-color: $text-color;
|
||||||
|
$dropdown-link-hover-color: $dropdown-link-color;
|
||||||
|
|
||||||
|
//== Navbar
|
||||||
|
$navbar-inverse-bg: $gray-darker;
|
||||||
|
$navbar-inverse-link-hover-color: $text-color;
|
||||||
|
$navbar-inverse-brand-hover-color: $navbar-inverse-link-hover-color;
|
||||||
|
|
||||||
|
//== Tabs
|
||||||
|
$nav-tabs-active-link-hover-bg: $gray;
|
||||||
|
$nav-tabs-active-link-hover-border-color: $gray-darker;
|
||||||
|
|
||||||
|
//== Navs
|
||||||
|
$nav-link-hover-bg: $gray-darker;
|
||||||
|
|
||||||
|
//== Pagination
|
||||||
|
$pagination-color: $light-blue;
|
||||||
|
$pagination-bg: $gray-light;
|
||||||
|
$pagination-border: $gray-darker;
|
||||||
|
|
||||||
|
$pagination-hover-color: $gray-dark;
|
||||||
|
$pagination-hover-bg: $light-blue;
|
||||||
|
$pagination-hover-border: $pagination-border;
|
||||||
|
|
||||||
|
$pagination-active-border: $pagination-border;
|
||||||
|
|
||||||
|
$pagination-disabled-color: $gray-dark;
|
||||||
|
$pagination-disabled-bg: $gray-light;
|
||||||
|
$pagination-disabled-border: $pagination-border;
|
||||||
|
|
||||||
|
//== Form states and alerts
|
||||||
|
$state-success-text: lighten($green, 30%);
|
||||||
|
$state-success-bg: darken($green, 10%);
|
||||||
|
$state-success-border: darken($state-success-bg, 20%);
|
||||||
|
|
||||||
|
$state-info-text: lighten($blue, 20%);
|
||||||
|
$state-info-bg: darken($blue, 20%);
|
||||||
|
$state-info-border: darken($state-info-bg, 20%);
|
||||||
|
|
||||||
|
$state-warning-text: lighten($yellow, 30%);
|
||||||
|
$state-warning-bg: $yellow;
|
||||||
|
$state-warning-border: darken($state-warning-bg, 20%);
|
||||||
|
|
||||||
|
$state-danger-text: lighten($red, 40%);
|
||||||
|
$state-danger-bg: $red;
|
||||||
|
$state-danger-border: darken($state-danger-bg, 20%);
|
||||||
|
|
||||||
|
|
||||||
|
//== Popovers
|
||||||
|
$popover-bg: lighten($gray, 5%);
|
||||||
|
$popover-border-color: $gray-darker;
|
||||||
|
|
||||||
|
//== Modals
|
||||||
|
$modal-content-bg: $gray;
|
||||||
|
$modal-header-border-color: $gray-light;
|
||||||
|
|
||||||
|
//== List group
|
||||||
|
$list-group-bg: $gray;
|
||||||
|
$list-group-link-color: $text-color;
|
||||||
|
|
||||||
|
//== Panels
|
||||||
|
$panel-bg: $gray;
|
||||||
|
$panel-default-text: $text-color;
|
||||||
|
$panel-default-border: $gray-darker;
|
||||||
|
$panel-default-heading-bg: $gray-dark;
|
||||||
|
|
||||||
|
//== Thumbnails
|
||||||
|
$thumbnail-border: $gray-darker;
|
||||||
|
|
||||||
|
//== Wells
|
||||||
|
$well-bg: $gray-dark;
|
||||||
|
|
||||||
|
//== Close
|
||||||
|
$close-color: $gray-lighter;
|
||||||
|
|
||||||
|
//== Type
|
||||||
|
$hr-border: $gray-light;
|
||||||
|
|
||||||
|
// Variables
|
||||||
|
$text-color-pale: $gray-light;
|
||||||
|
$text-color-active: lighten($gray-lighter, 27%);
|
||||||
|
|
||||||
|
$background-grey: $gray-dark;
|
||||||
|
$background-blue: desaturate(darken($blue, 25%), 15%);
|
||||||
|
|
||||||
|
$border-grey: $gray-darker;
|
||||||
|
$border-medium-grey: $gray-light;
|
||||||
|
$border-dark-grey: darken($border-grey, 4.5%);
|
||||||
|
|
||||||
|
$icon-color: $text-color;
|
||||||
|
|
||||||
|
$main-background: $gray-dark;
|
||||||
|
$framed-background: $gray;
|
||||||
|
$left-navbar-drawer-background: $main-background;
|
||||||
|
$hovercard-background: $gray;
|
||||||
|
|
||||||
|
@import 'color_themes/color_theme_override_dark';
|
||||||
3
app/assets/stylesheets/color_themes/dark/desktop.scss
Normal file
3
app/assets/stylesheets/color_themes/dark/desktop.scss
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
@import 'mixins';
|
||||||
|
@import 'color_themes/dark/style';
|
||||||
|
@import 'application';
|
||||||
63
app/assets/stylesheets/color_themes/dark/mobile.scss
Normal file
63
app/assets/stylesheets/color_themes/dark/mobile.scss
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
@import 'mixins';
|
||||||
|
@import 'color_themes/dark/style';
|
||||||
|
|
||||||
|
// Only overriding existing selectors here, so disable some lint rules
|
||||||
|
// scss-lint:disable SelectorFormat, NestingDepth, SelectorDepth
|
||||||
|
body {
|
||||||
|
.settings-container,
|
||||||
|
.stream-element,
|
||||||
|
.login-form {
|
||||||
|
border: 1px solid $border-grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-element,
|
||||||
|
.comments {
|
||||||
|
.from a { color: $text-color; }
|
||||||
|
.info { color: lighten($gray-light, 12%); }
|
||||||
|
.nsfw-shield { background-color: $gray-light; }
|
||||||
|
|
||||||
|
.bottom-bar {
|
||||||
|
background: lighten($framed-background, 4.5%);
|
||||||
|
.post-action .disabled { color: $text-color-pale; }
|
||||||
|
.post-stats .count { background-color: lighten($framed-background, 4.5%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.reshare {
|
||||||
|
border-bottom: 1px solid $border-medium-grey;
|
||||||
|
.reshare_via span { color: $border-medium-grey; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-link,
|
||||||
|
.no-more-posts {
|
||||||
|
background: { color: $btn-default-bg; }
|
||||||
|
border: 1px solid $gray;
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2 {
|
||||||
|
color: $text-color;
|
||||||
|
text-shadow: 0 2px 0 $gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-element.unread { background-color: $gray; }
|
||||||
|
.stream-element.read { background-color: $gray-darker; }
|
||||||
|
|
||||||
|
.header-full-width { border-bottom: 1px solid $border-grey; }
|
||||||
|
|
||||||
|
.user_aspects {
|
||||||
|
&,
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
border-color: $gray-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has_connection {
|
||||||
|
background-color: $green;
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// scss-lint:enable IdSelector, SelectorFormat, NestingDepth, SelectorDepth
|
||||||
|
|
||||||
|
@import 'mobile/mobile';
|
||||||
|
|
@ -3,7 +3,6 @@ $background: #fff;
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
$main-background: $background;
|
$main-background: $background;
|
||||||
$sidebars-background: $background;
|
|
||||||
$card-shadow: none;
|
$card-shadow: none;
|
||||||
|
|
||||||
@import 'color_themes/color_theme_override_origwhite';
|
@import 'color_themes/color_theme_override_origwhite';
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,27 @@
|
||||||
.comment_stream {
|
.comment_stream {
|
||||||
.show_comments {
|
.show_comments {
|
||||||
margin-top: 5px;
|
|
||||||
border-top: 1px solid $border-grey;
|
border-top: 1px solid $border-grey;
|
||||||
|
line-height: $line-height-computed;
|
||||||
|
margin-top: 5px;
|
||||||
a {
|
a {
|
||||||
color: $text-grey;
|
color: $text-grey;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
.media { margin-top: 10px; }
|
.media { margin-top: 10px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading-comments {
|
||||||
|
height: $line-height-computed + 11px; // height of .show_comments: line-height, 10px margin, 1px border
|
||||||
|
margin-top: -$line-height-computed - 11px;
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media { margin: 5px; }
|
||||||
|
}
|
||||||
|
|
||||||
.comments > .comment,
|
.comments > .comment,
|
||||||
.comment.new-comment-form-wrapper {
|
.comment.new-comment-form-wrapper {
|
||||||
.avatar {
|
.avatar {
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,13 @@
|
||||||
margin-right: 25px;
|
margin-right: 25px;
|
||||||
}
|
}
|
||||||
#chat_privilege_toggle > .enabled {
|
#chat_privilege_toggle > .enabled {
|
||||||
color: #000;
|
color: $text-color-active;
|
||||||
}
|
}
|
||||||
.contacts-header-icon {
|
.contacts-header-icon {
|
||||||
font-size: 24.5px;
|
font-size: 24.5px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
color: lighten($black,75%);
|
color: $text-color-pale;
|
||||||
&:hover { color: $black; }
|
&:hover { color: $text-color; }
|
||||||
}
|
}
|
||||||
#suggest_member.btn { margin-top: 8px; }
|
#suggest_member.btn { margin-top: 8px; }
|
||||||
}
|
}
|
||||||
|
|
@ -56,14 +56,14 @@
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
color: lighten($black,75%);
|
color: $text-color-pale;
|
||||||
&:hover { color: $black; }
|
&:hover { color: $text-color; }
|
||||||
}
|
}
|
||||||
&.in_aspect {
|
&.in_aspect {
|
||||||
border-left: 3px solid $brand-success;
|
border-left: 3px solid $brand-success;
|
||||||
background-color: lighten($brand-success,35%);
|
background-color: lighten($brand-success,35%);
|
||||||
}
|
}
|
||||||
&:not(.in_aspect) { border-left: 3px solid $white; }
|
&:not(.in_aspect) { border-left: 3px solid $framed-background; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.no_contacts {
|
.no_contacts {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.stream-element {
|
.stream-element {
|
||||||
background-color: $white;
|
background-color: $framed-background;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
.stream-element.message,
|
.stream-element.message,
|
||||||
.stream-element.new-message {
|
.stream-element.new-message {
|
||||||
border: 1px solid $light-grey;
|
border: 1px solid $border-grey;
|
||||||
box-shadow: $card-shadow;
|
box-shadow: $card-shadow;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.unread { background-color: darken($background-white, 5%); }
|
&.unread { background-color: $background-grey; }
|
||||||
&.selected { background-color: $blue; }
|
&.selected { background-color: $blue; }
|
||||||
|
|
||||||
.last_author, .last_message {
|
.last_author, .last_message {
|
||||||
|
|
@ -183,10 +183,60 @@
|
||||||
}
|
}
|
||||||
// scss-lint:enable SelectorDepth
|
// scss-lint:enable SelectorDepth
|
||||||
|
|
||||||
#new_conversation_pane {
|
.new-conversation {
|
||||||
ul.as-selections { width: 100% !important; }
|
ul.as-selections { width: 100% !important; }
|
||||||
|
|
||||||
input#contact_ids { box-shadow: none; }
|
input#contact_ids { box-shadow: none; }
|
||||||
|
|
||||||
label { font-weight: bold; }
|
label { font-weight: bold; }
|
||||||
|
|
||||||
|
.twitter-typeahead,
|
||||||
|
.tt-menu {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.recipients-tag-list {
|
||||||
|
.conversation-recipient-tag {
|
||||||
|
background-color: $brand-primary;
|
||||||
|
border-radius: $btn-border-radius-base;
|
||||||
|
display: inline-flex;
|
||||||
|
margin: 0 2px $form-group-margin-bottom;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
&:first-child { margin-left: 0; }
|
||||||
|
|
||||||
|
&:last-child { margin-right: 0; }
|
||||||
|
|
||||||
|
div {
|
||||||
|
align-self: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
height: 40px;
|
||||||
|
margin-right: 8px;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-and-handle {
|
||||||
|
color: $white;
|
||||||
|
margin-right: 8px;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
.diaspora-id { font-size: $font-size-small; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.entypo-circled-cross {
|
||||||
|
color: $white;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 20px;
|
||||||
|
height: 22px;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
&:hover { color: $light-grey; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-conversation.form-horizontal .form-group:last-of-type { margin-bottom: 0; }
|
.new-conversation.form-horizontal .form-group:last-of-type { margin-bottom: 0; }
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,7 @@ textarea {
|
||||||
&:active:focus,
|
&:active:focus,
|
||||||
&:invalid:focus,
|
&:invalid:focus,
|
||||||
&:invalid:required:focus {
|
&:invalid:required:focus {
|
||||||
border-color: $border-grey;
|
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
color: $text-dark-grey;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// scss-lint:enable QualifyingElement
|
// scss-lint:enable QualifyingElement
|
||||||
|
|
@ -29,7 +27,6 @@ textarea {
|
||||||
margin: 20px auto;
|
margin: 20px auto;
|
||||||
|
|
||||||
fieldset {
|
fieldset {
|
||||||
background-color: $white;
|
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
position: relative; // To correctly place the entypo icon
|
position: relative; // To correctly place the entypo icon
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
}
|
}
|
||||||
.view_all {
|
.view_all {
|
||||||
background-color: $link-color;
|
background-color: $link-color;
|
||||||
border-top: 3px solid $white;
|
border-top: 3px solid $dropdown-bg;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
a {
|
a {
|
||||||
color: $white;
|
color: $white;
|
||||||
|
|
|
||||||
|
|
@ -98,9 +98,9 @@ ul#help_nav {
|
||||||
line-height: 70px;
|
line-height: 70px;
|
||||||
|
|
||||||
[class^="entypo-"], [class*="entypo-"] {
|
[class^="entypo-"], [class*="entypo-"] {
|
||||||
color: #bfbfbf;
|
color: $text-color-pale;
|
||||||
|
|
||||||
&.entypo-chat{ color: #000000; }
|
&.entypo-chat { color: $text-color-active; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-info-card {
|
.landing-info-card {
|
||||||
background-color: $white;
|
background-color: $framed-background;
|
||||||
border: 1px solid $light-grey;
|
border: 1px solid $border-grey;
|
||||||
box-shadow: $card-shadow;
|
box-shadow: $card-shadow;
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
|
|
||||||
background-color: $background-white;
|
background-color: $hovercard-background;
|
||||||
border: 1px solid $border-dark-grey;
|
border: 1px solid $border-dark-grey;
|
||||||
font-size: small;
|
font-size: small;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[class^="entypo-"], [class*="entypo-"] {
|
[class^="entypo-"], [class*="entypo-"] {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
color: black;
|
color: $icon-color;
|
||||||
|
|
||||||
&.red { color: #A40802; }
|
&.red { color: #A40802; }
|
||||||
&.white { color: white; }
|
&.white { color: white; }
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
[class^="entypo-"],
|
[class^="entypo-"],
|
||||||
[class*="entypo-"] {
|
[class*="entypo-"] {
|
||||||
color: $text-grey;
|
color: $text-color-pale;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
line-height: $line-height-base;
|
line-height: $line-height-base;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
@ -12,12 +12,12 @@
|
||||||
|
|
||||||
[class^="entypo-"]:hover,
|
[class^="entypo-"]:hover,
|
||||||
[class*="entypo-"]:hover {
|
[class*="entypo-"]:hover {
|
||||||
color: $text;
|
color: $text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.hide_conversation i { font-size: $line-height-computed * 1.5; }
|
&.hide_conversation i { font-size: $line-height-computed * 1.5; }
|
||||||
&.delete_conversation i { font-size: $font-size-base * 1.5; }
|
&.delete_conversation i { font-size: $font-size-base * 1.5; }
|
||||||
&.destroy_participation i { color: $black; }
|
&.destroy_participation i { color: $text-color-active; }
|
||||||
&.destroy_participation i:hover { color: $text-dark-grey; }
|
&.destroy_participation i:hover { color: $text-dark-grey; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#invite_code {
|
#invite_code {
|
||||||
background-color: $white;
|
background-color: $framed-background;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
#invitationsModal {
|
#invitationsModal {
|
||||||
.modal-header, .modal-body {
|
.modal-header, .modal-body {
|
||||||
color: $text;
|
color: $text-color;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
text-align: initial;
|
text-align: initial;
|
||||||
}
|
}
|
||||||
#paste_link { font-weight: 700; }
|
#paste_link { font-weight: 700; }
|
||||||
#invite_code { margin-top: 10px; }
|
#invite_code { margin-top: 10px; }
|
||||||
#codes_left { color: $text-grey; }
|
#codes_left { color: $text-color-pale; }
|
||||||
.controls { margin-left: 140px; }
|
.controls { margin-left: 140px; }
|
||||||
#email_invitation {
|
#email_invitation {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
border-top: 1px dashed $border-grey;
|
border-top: 1px dashed $border-grey;
|
||||||
label { font-weight: 700; }
|
label { font-weight: 700; }
|
||||||
#already_sent {
|
#already_sent {
|
||||||
color: $text-grey;
|
color: $text-color-pale;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
.md-footer,
|
.md-footer,
|
||||||
.md-header {
|
.md-header {
|
||||||
background: $sidebars-background;
|
background: $white;
|
||||||
border: 0;
|
border: 0;
|
||||||
display: block;
|
display: block;
|
||||||
height: 42px;
|
height: 42px;
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
[class^="entypo-"],
|
[class^="entypo-"],
|
||||||
[class*="entypo-"],
|
[class*="entypo-"],
|
||||||
.glyphicon {
|
.glyphicon {
|
||||||
color: $black;
|
color: $icon-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
width: 18px;
|
width: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover .entypo-cross { color: $text; }
|
&:hover .entypo-cross { color: $text-color; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.mentions {
|
.mentions {
|
||||||
color: white;
|
color: transparent;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
&.active:not(.bottom_collapse),
|
&.active:not(.bottom_collapse),
|
||||||
&.active:not(.bottom_collapse) > [class^="entypo"] {
|
&.active:not(.bottom_collapse) > [class^="entypo"] {
|
||||||
color: $text;
|
color: $text-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,3 +61,5 @@
|
||||||
.subject { padding: 0 10px; }
|
.subject { padding: 0 10px; }
|
||||||
|
|
||||||
.message-count, .unread-message-count { margin: 10px 2px; }
|
.message-count, .unread-message-count { margin: 10px 2px; }
|
||||||
|
|
||||||
|
.new-conversation .as-selections { background-color: transparent; }
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ footer {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
background-color: #fff;
|
background-color: $framed-background;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
||||||
border: 1px solid #bbb;
|
border: 1px solid #bbb;
|
||||||
|
|
@ -176,7 +176,7 @@ footer {
|
||||||
border-radius: 3px 3px 0 0;
|
border-radius: 3px 3px 0 0;
|
||||||
|
|
||||||
border: {
|
border: {
|
||||||
bottom: 1px solid #ccc;
|
bottom: 1px solid $border-medium-grey;
|
||||||
}
|
}
|
||||||
|
|
||||||
img.big-stream-photo {
|
img.big-stream-photo {
|
||||||
|
|
@ -322,7 +322,7 @@ footer {
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-full-width {
|
.header-full-width {
|
||||||
background-color: #fff;
|
background-color: $framed-background;
|
||||||
border-bottom: 1px solid #aaa;
|
border-bottom: 1px solid #aaa;
|
||||||
margin: -10px; // Counter the #main padding
|
margin: -10px; // Counter the #main padding
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
@ -462,7 +462,7 @@ select {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: $text-grey;
|
color: $text-grey;
|
||||||
background: {
|
background: {
|
||||||
color: #fff;
|
color: $framed-background;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ ul.followed_tags {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
background-color: $white;
|
background-color: $framed-background;
|
||||||
border: 1px solid $border-grey;
|
border: 1px solid $border-grey;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
box-shadow: 0 1px 2px rgba($border-dark-grey, 0.5);
|
box-shadow: 0 1px 2px rgba($border-dark-grey, 0.5);
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
background-color: $background-grey;
|
background-color: $background-grey;
|
||||||
.unread-toggle {
|
.unread-toggle {
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
.entypo-eye { color: $black; }
|
.entypo-eye { color: $text-color-active; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
padding: 9px 5px;
|
padding: 9px 5px;
|
||||||
.entypo-eye {
|
.entypo-eye {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: lighten($black,75%);
|
color: $text-color-pale;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
line-height: 17px;
|
line-height: 17px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#profile_container {
|
#profile_container {
|
||||||
.profile_header {
|
.profile_header {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
background-color: $white;
|
background-color: $framed-background;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
#diaspora_handle {
|
#diaspora_handle {
|
||||||
color: $text-grey;
|
color: $text-color-pale;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
#sharing_message {
|
#sharing_message {
|
||||||
|
|
@ -64,8 +64,8 @@
|
||||||
.profile-header-icon {
|
.profile-header-icon {
|
||||||
font-size: 24.5px;
|
font-size: 24.5px;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
color: lighten($black,75%);
|
color: $text-color-pale;
|
||||||
&:hover { color: $black; }
|
&:hover { color: $text-color; }
|
||||||
}
|
}
|
||||||
#mention_button { font-weight: 700; }
|
#mention_button { font-weight: 700; }
|
||||||
}
|
}
|
||||||
|
|
@ -80,8 +80,12 @@
|
||||||
&.active {
|
&.active {
|
||||||
border-bottom: 3px solid $brand-primary;
|
border-bottom: 3px solid $brand-primary;
|
||||||
a {
|
a {
|
||||||
color: $black;
|
color: $text-color-active;
|
||||||
[class^="entypo-"], [class*="entypo-"] { color: $black; }
|
|
||||||
|
[class^="entypo-"],
|
||||||
|
[class*="entypo-"] {
|
||||||
|
color: $text-color-active;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
|
|
@ -94,9 +98,13 @@
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $black;
|
color: $text-color-active;
|
||||||
[class^="entypo-"], [class*="entypo-"] { color: $black; }
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
|
[class^="entypo-"],
|
||||||
|
[class*="entypo-"] {
|
||||||
|
color: $text-color-active;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.captcha-input {
|
.captcha-input {
|
||||||
border-bottom: 1px solid $border-grey;
|
border-bottom: 1px solid $input-border;
|
||||||
border-bottom-left-radius: 5px;
|
border-bottom-left-radius: 5px;
|
||||||
border-bottom-right-radius: 5px;
|
border-bottom-right-radius: 5px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
.sidebar,
|
.sidebar,
|
||||||
.framed-content {
|
.framed-content {
|
||||||
background-color: $white;
|
background-color: $framed-background;
|
||||||
border: 1px solid $light-grey;
|
border: 1px solid $border-grey;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
box-shadow: $card-shadow;
|
box-shadow: $card-shadow;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.control-icons {
|
.control-icons {
|
||||||
background: $white;
|
background: $framed-background;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumbnail {
|
.thumbnail {
|
||||||
background: $white;
|
background: $framed-background;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: $card-shadow;
|
box-shadow: $card-shadow;
|
||||||
height: 240px;
|
height: 240px;
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus,
|
&:focus,
|
||||||
&:active {
|
&:active {
|
||||||
border-color: $light-grey;
|
border-color: $border-grey;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
|
|
||||||
#main_stream .stream-element {
|
#main_stream .stream-element {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
border: 1px solid $light-grey;
|
border: 1px solid $border-grey;
|
||||||
box-shadow: $card-shadow;
|
box-shadow: $card-shadow;
|
||||||
|
|
||||||
&.highlighted {
|
&.highlighted {
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.stream-element {
|
.stream-element {
|
||||||
background-color: $white;
|
background-color: $framed-background;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
& > .media {
|
& > .media {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="loading-comments comment text-center hidden">
|
||||||
|
<div class="media">
|
||||||
|
<div class="loader">
|
||||||
|
<div class="spinner"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="comments"> </div>
|
<div class="comments"> </div>
|
||||||
|
|
||||||
{{#if loggedIn}}
|
{{#if loggedIn}}
|
||||||
|
|
|
||||||
12
app/assets/templates/conversation_recipient_tag_tpl.jst.hbs
Normal file
12
app/assets/templates/conversation_recipient_tag_tpl.jst.hbs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<div class="conversation-recipient-tag clearfix" data-diaspora-handle="{{ handle }}">
|
||||||
|
<div href="{{ url }}">
|
||||||
|
<img src="{{ avatar }}" class="avatar img-responsive center-block">
|
||||||
|
</div>
|
||||||
|
<div class="pull-left clearfix name-and-handle" href="{{ url }}">
|
||||||
|
<div class="name">{{ name }}</div>
|
||||||
|
<div class="diaspora-id">{{ handle }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="remove pull-right clearfix">
|
||||||
|
<i class="entypo-circled-cross"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
<ul class="dropdown-menu" role="menu">
|
<ul class="dropdown-menu" role="menu">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<a href="#" id="mark_all_read_link" class="btn btn-default btn-sm {{#unless current_user.notifications_count}}disabled{{/unless}}">
|
<a href="#" id="mark-all-read-link" class="btn btn-default btn-sm {{#unless current_user.notifications_count}}disabled{{/unless}}">
|
||||||
{{t "header.mark_all_as_read"}}
|
{{t "header.mark_all_as_read"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -61,11 +61,10 @@
|
||||||
{{t "header.recent_notifications"}}
|
{{t "header.recent_notifications"}}
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="notifications">
|
<div class="ajax-loader">
|
||||||
<div class="ajax-loader">
|
<div class="spinner"></div>
|
||||||
<div class="spinner"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="notifications"></div>
|
||||||
<div class="view_all">
|
<div class="view_all">
|
||||||
<a href="/notifications" id="view_all_notifications">
|
<a href="/notifications" id="view_all_notifications">
|
||||||
{{t "header.view_all"}}
|
{{t "header.view_all"}}
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ module Api
|
||||||
session[:response_type] = @response_type
|
session[:response_type] = @response_type
|
||||||
session[:redirect_uri] = @redirect_uri
|
session[:redirect_uri] = @redirect_uri
|
||||||
session[:scopes] = scopes_as_space_seperated_values
|
session[:scopes] = scopes_as_space_seperated_values
|
||||||
|
session[:state] = params[:state]
|
||||||
session[:nonce] = params[:nonce]
|
session[:nonce] = params[:nonce]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -149,6 +150,7 @@ module Api
|
||||||
session.delete(:response_type)
|
session.delete(:response_type)
|
||||||
session.delete(:redirect_uri)
|
session.delete(:redirect_uri)
|
||||||
session.delete(:scopes)
|
session.delete(:scopes)
|
||||||
|
session.delete(:state)
|
||||||
session.delete(:nonce)
|
session.delete(:nonce)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -162,6 +164,7 @@ module Api
|
||||||
req.update_param("redirect_uri", session[:redirect_uri])
|
req.update_param("redirect_uri", session[:redirect_uri])
|
||||||
req.update_param("response_type", response_type_as_space_seperated_values)
|
req.update_param("response_type", response_type_as_space_seperated_values)
|
||||||
req.update_param("scope", session[:scopes])
|
req.update_param("scope", session[:scopes])
|
||||||
|
req.update_param("state", session[:state])
|
||||||
req.update_param("nonce", session[:nonce])
|
req.update_param("nonce", session[:nonce])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
class Api::V1::TokensController < ApplicationController
|
|
||||||
skip_before_filter :verify_authenticity_token
|
|
||||||
before_filter :authenticate_user!
|
|
||||||
|
|
||||||
respond_to :json
|
|
||||||
|
|
||||||
def create
|
|
||||||
current_user.ensure_authentication_token!
|
|
||||||
render :status => 200, :json => { :token => current_user.authentication_token }
|
|
||||||
end
|
|
||||||
|
|
||||||
def destroy
|
|
||||||
current_user.reset_authentication_token!
|
|
||||||
render :json => true, :status => 200
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -12,11 +12,17 @@ class CommentsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
comment = comment_service.create(params[:post_id], params[:text])
|
begin
|
||||||
|
comment = comment_service.create(params[:post_id], params[:text])
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
render text: I18n.t("comments.create.error"), status: 404
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if comment
|
if comment
|
||||||
respond_create_success(comment)
|
respond_create_success(comment)
|
||||||
else
|
else
|
||||||
render nothing: true, status: 404
|
render text: I18n.t("comments.create.error"), status: 422
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ class ContactsController < ApplicationController
|
||||||
# Used for mentions in the publisher and pagination on the contacts page
|
# Used for mentions in the publisher and pagination on the contacts page
|
||||||
format.json {
|
format.json {
|
||||||
@people = if params[:q].present?
|
@people = if params[:q].present?
|
||||||
Person.search(params[:q], current_user, only_contacts: true).limit(15)
|
mutual = params[:mutual].present? && params[:mutual]
|
||||||
|
Person.search(params[:q], current_user, only_contacts: true, mutual: mutual).limit(15)
|
||||||
else
|
else
|
||||||
set_up_contacts_json
|
set_up_contacts_json
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,17 @@ class ConversationsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
contact_ids = params[:contact_ids]
|
# Contacts autocomplete does not work the same way on mobile and desktop
|
||||||
|
# Mobile returns contact ids array while desktop returns person id
|
||||||
|
# This will have to be removed when mobile autocomplete is ported to Typeahead
|
||||||
|
recipients_param, column = [%i(contact_ids id), %i(person_ids person_id)].find {|param, _| params[param].present? }
|
||||||
|
if recipients_param
|
||||||
|
person_ids = current_user.contacts.mutual.where(column => params[recipients_param].split(",")).pluck(:person_id)
|
||||||
|
end
|
||||||
|
|
||||||
# Can't split nil
|
unless person_ids.present?
|
||||||
if contact_ids
|
render text: I18n.t("javascripts.conversation.create.no_recipient"), status: 422
|
||||||
contact_ids = contact_ids.split(',') if contact_ids.is_a? String
|
return
|
||||||
person_ids = current_user.contacts.where(id: contact_ids).pluck(:person_id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
opts = params.require(:conversation).permit(:subject)
|
opts = params.require(:conversation).permit(:subject)
|
||||||
|
|
@ -43,16 +48,12 @@ class ConversationsController < ApplicationController
|
||||||
opts[:message] = { text: params[:conversation][:text] }
|
opts[:message] = { text: params[:conversation][:text] }
|
||||||
@conversation = current_user.build_conversation(opts)
|
@conversation = current_user.build_conversation(opts)
|
||||||
|
|
||||||
if person_ids.present? && @conversation.save
|
if @conversation.save
|
||||||
Diaspora::Federation::Dispatcher.defer_dispatch(current_user, @conversation)
|
Diaspora::Federation::Dispatcher.defer_dispatch(current_user, @conversation)
|
||||||
flash[:notice] = I18n.t("conversations.create.sent")
|
flash[:notice] = I18n.t("conversations.create.sent")
|
||||||
render json: {id: @conversation.id}
|
render json: {id: @conversation.id}
|
||||||
else
|
else
|
||||||
message = I18n.t("conversations.create.fail")
|
render text: I18n.t("conversations.create.fail"), status: 422
|
||||||
if person_ids.blank?
|
|
||||||
message = I18n.t("javascripts.conversation.create.no_recipient")
|
|
||||||
end
|
|
||||||
render text: message, status: 422
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -91,17 +92,23 @@ class ConversationsController < ApplicationController
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@contacts_json = contacts_data.to_json
|
|
||||||
@contact_ids = ""
|
|
||||||
|
|
||||||
if params[:contact_id]
|
|
||||||
@contact_ids = current_user.contacts.find(params[:contact_id]).id
|
|
||||||
elsif params[:aspect_id]
|
|
||||||
@contact_ids = current_user.aspects.find(params[:aspect_id]).contacts.map{|c| c.id}.join(',')
|
|
||||||
end
|
|
||||||
if session[:mobile_view] == true && request.format.html?
|
if session[:mobile_view] == true && request.format.html?
|
||||||
|
@contacts_json = contacts_data.to_json
|
||||||
|
|
||||||
|
@contact_ids = if params[:contact_id]
|
||||||
|
current_user.contacts.find(params[:contact_id]).id
|
||||||
|
elsif params[:aspect_id]
|
||||||
|
current_user.aspects.find(params[:aspect_id]).contacts.pluck(:id).join(",")
|
||||||
|
end
|
||||||
|
|
||||||
render :layout => true
|
render :layout => true
|
||||||
else
|
else
|
||||||
|
if params[:contact_id]
|
||||||
|
gon.push conversation_prefill: [current_user.contacts.find(params[:contact_id]).person.as_json]
|
||||||
|
elsif params[:aspect_id]
|
||||||
|
gon.push conversation_prefill: current_user.aspects
|
||||||
|
.find(params[:aspect_id]).contacts.map {|c| c.person.as_json }
|
||||||
|
end
|
||||||
render :layout => false
|
render :layout => false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class LikesController < ApplicationController
|
||||||
format.json { render :json => @like.as_api_response(:backbone), :status => 201 }
|
format.json { render :json => @like.as_api_response(:backbone), :status => 201 }
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
render :nothing => true, :status => 422
|
render text: I18n.t("likes.create.error"), status: 422
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ class NotificationsController < ApplicationController
|
||||||
format.html
|
format.html
|
||||||
format.xml { render :xml => @notifications.to_xml }
|
format.xml { render :xml => @notifications.to_xml }
|
||||||
format.json {
|
format.json {
|
||||||
render json: @notifications, each_serializer: NotificationSerializer
|
render json: render_as_json(@unread_notification_count, @grouped_unread_notification_counts, @notifications)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -82,4 +82,15 @@ class NotificationsController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def render_as_json(unread_count, unread_count_by_type, notification_list)
|
||||||
|
{
|
||||||
|
unread_count: unread_count,
|
||||||
|
unread_count_by_type: unread_count_by_type,
|
||||||
|
notification_list: notification_list.map {|note|
|
||||||
|
NotificationSerializer.new(note, default_serializer_options).as_json
|
||||||
|
}
|
||||||
|
}.as_json
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,19 @@ class ResharesController < ApplicationController
|
||||||
current_user.dispatch_post(@reshare)
|
current_user.dispatch_post(@reshare)
|
||||||
render :json => ExtremePostPresenter.new(@reshare, current_user), :status => 201
|
render :json => ExtremePostPresenter.new(@reshare, current_user), :status => 201
|
||||||
else
|
else
|
||||||
render :nothing => true, :status => 422
|
render text: I18n.t("reshares.create.error"), status: 422
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def index
|
||||||
|
@reshares = target.reshares.includes(author: :profile)
|
||||||
|
render json: @reshares.as_api_response(:backbone)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def target
|
||||||
|
@target ||= current_user.find_visible_shareable_by_id(Post, params[:post_id]) ||
|
||||||
|
raise(ActiveRecord::RecordNotFound.new)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,14 @@ class ShareVisibilitiesController < ApplicationController
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def update
|
def update
|
||||||
#note :id references a postvisibility
|
post = post_service.find!(params[:post_id])
|
||||||
params[:shareable_id] ||= params[:post_id]
|
current_user.toggle_hidden_shareable(post)
|
||||||
params[:shareable_type] ||= 'Post'
|
head :ok
|
||||||
|
|
||||||
vis = current_user.toggle_hidden_shareable(accessible_post)
|
|
||||||
render :nothing => true, :status => 200
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def accessible_post
|
def post_service
|
||||||
@post ||= params[:shareable_type].constantize.where(:id => params[:post_id]).select("id, guid, author_id, created_at").first
|
@post_service ||= PostService.new(current_user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,11 @@ class UsersController < ApplicationController
|
||||||
redirect_to edit_user_path
|
redirect_to edit_user_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def auth_token
|
||||||
|
current_user.ensure_authentication_token!
|
||||||
|
render status: 200, json: {token: current_user.authentication_token}
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# rubocop:disable Metrics/MethodLength
|
# rubocop:disable Metrics/MethodLength
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def changelog_url
|
def changelog_url
|
||||||
|
return AppConfig.settings.changelog_url.get if AppConfig.settings.changelog_url.present?
|
||||||
|
|
||||||
url = "https://github.com/diaspora/diaspora/blob/master/Changelog.md"
|
url = "https://github.com/diaspora/diaspora/blob/master/Changelog.md"
|
||||||
url.sub!('/master/', "/#{AppConfig.git_revision}/") if AppConfig.git_revision.present?
|
url.sub!('/master/', "/#{AppConfig.git_revision}/") if AppConfig.git_revision.present?
|
||||||
url
|
url
|
||||||
|
|
@ -31,14 +33,6 @@ module ApplicationHelper
|
||||||
"bookmarklet('#{bookmarklet_url}', #{width}, #{height});"
|
"bookmarklet('#{bookmarklet_url}', #{width}, #{height});"
|
||||||
end
|
end
|
||||||
|
|
||||||
def contacts_link
|
|
||||||
if current_user.contacts.size > 0
|
|
||||||
contacts_path
|
|
||||||
else
|
|
||||||
community_spotlight_path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def all_services_connected?
|
def all_services_connected?
|
||||||
current_user.services.size == AppConfig.configured_services.size
|
current_user.services.size == AppConfig.configured_services.size
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ module LayoutHelper
|
||||||
def current_user_atom_tag
|
def current_user_atom_tag
|
||||||
return unless @person.present?
|
return unless @person.present?
|
||||||
content_tag(:link, "", rel: "alternate", href: @person.atom_url, type: "application/atom+xml",
|
content_tag(:link, "", rel: "alternate", href: @person.atom_url, type: "application/atom+xml",
|
||||||
title: t(".public_feed", name: @person.name))
|
title: t("layouts.application.public_feed", name: @person.name))
|
||||||
end
|
end
|
||||||
|
|
||||||
def translation_missing_warnings
|
def translation_missing_warnings
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ module SessionsHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_password_reset_link?
|
def display_password_reset_link?
|
||||||
devise_mapping.recoverable? && controller_name != "passwords"
|
AppConfig.mail.enable? && devise_mapping.recoverable? && controller_name != "passwords"
|
||||||
end
|
end
|
||||||
|
|
||||||
def flash_class(name)
|
def flash_class(name)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,10 @@ module StreamHelper
|
||||||
aspects_stream_path(max_time: time_for_scroll(@stream), a_ids: session[:a_ids])
|
aspects_stream_path(max_time: time_for_scroll(@stream), a_ids: session[:a_ids])
|
||||||
elsif current_page?(:public_stream)
|
elsif current_page?(:public_stream)
|
||||||
public_stream_path(max_time: time_for_scroll(@stream))
|
public_stream_path(max_time: time_for_scroll(@stream))
|
||||||
|
elsif current_page?(:commented_stream)
|
||||||
|
commented_stream_path(max_time: time_for_scroll(@stream))
|
||||||
|
elsif current_page?(:liked_stream)
|
||||||
|
liked_stream_path(max_time: time_for_scroll(@stream))
|
||||||
elsif current_page?(:mentioned_stream)
|
elsif current_page?(:mentioned_stream)
|
||||||
mentioned_stream_path(max_time: time_for_scroll(@stream))
|
mentioned_stream_path(max_time: time_for_scroll(@stream))
|
||||||
elsif current_page?(:followed_tags_stream)
|
elsif current_page?(:followed_tags_stream)
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ class Person < ActiveRecord::Base
|
||||||
[where_clause, q_tokens]
|
[where_clause, q_tokens]
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.search(search_str, user, only_contacts: false)
|
def self.search(search_str, user, only_contacts: false, mutual: false)
|
||||||
search_str.strip!
|
search_str.strip!
|
||||||
return none if search_str.blank? || search_str.size < 2
|
return none if search_str.blank? || search_str.size < 2
|
||||||
|
|
||||||
|
|
@ -159,6 +159,8 @@ class Person < ActiveRecord::Base
|
||||||
).searchable(user)
|
).searchable(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
query = query.where(contacts: {sharing: true, receiving: true}) if mutual
|
||||||
|
|
||||||
query.where(closed_account: false)
|
query.where(closed_account: false)
|
||||||
.where(sql, *tokens)
|
.where(sql, *tokens)
|
||||||
.includes(:profile)
|
.includes(:profile)
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,10 @@ class Pod < ActiveRecord::Base
|
||||||
def check_all!
|
def check_all!
|
||||||
Pod.find_in_batches(batch_size: 20) {|batch| batch.each(&:test_connection!) }
|
Pod.find_in_batches(batch_size: 20) {|batch| batch.each(&:test_connection!) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_scheduled!
|
||||||
|
Pod.where(scheduled_check: true).find_each(&:test_connection!)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def offline?
|
def offline?
|
||||||
|
|
@ -76,6 +80,10 @@ class Pod < ActiveRecord::Base
|
||||||
"#{id}:#{host}"
|
"#{id}:#{host}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def schedule_check_if_needed
|
||||||
|
update_column(:scheduled_check, true) if offline? && !scheduled_check
|
||||||
|
end
|
||||||
|
|
||||||
def test_connection!
|
def test_connection!
|
||||||
result = ConnectionTester.check uri.to_s
|
result = ConnectionTester.check uri.to_s
|
||||||
logger.debug "tested pod: '#{uri}' - #{result.inspect}"
|
logger.debug "tested pod: '#{uri}' - #{result.inspect}"
|
||||||
|
|
@ -108,6 +116,7 @@ class Pod < ActiveRecord::Base
|
||||||
|
|
||||||
attributes_from_result(result)
|
attributes_from_result(result)
|
||||||
touch(:checked_at)
|
touch(:checked_at)
|
||||||
|
self.scheduled_check = false
|
||||||
|
|
||||||
save
|
save
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,14 @@ class Reshare < Post
|
||||||
self.root.update_reshares_counter if self.root.present?
|
self.root.update_reshares_counter if self.root.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
acts_as_api
|
||||||
|
api_accessible :backbone do |t|
|
||||||
|
t.add :id
|
||||||
|
t.add :guid
|
||||||
|
t.add :author
|
||||||
|
t.add :created_at
|
||||||
|
end
|
||||||
|
|
||||||
def root_diaspora_id
|
def root_diaspora_id
|
||||||
root.try(:author).try(:diaspora_handle)
|
root.try(:author).try(:diaspora_handle)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
# the COPYRIGHT file.
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
class User < ActiveRecord::Base
|
class User < ActiveRecord::Base
|
||||||
|
include AuthenticationToken
|
||||||
include Connecting
|
include Connecting
|
||||||
include Querying
|
include Querying
|
||||||
include SocialActions
|
include SocialActions
|
||||||
|
|
@ -16,7 +17,7 @@ class User < ActiveRecord::Base
|
||||||
scope :halfyear_actives, ->(time = Time.now) { logged_in_since(time - 6.month) }
|
scope :halfyear_actives, ->(time = Time.now) { logged_in_since(time - 6.month) }
|
||||||
scope :active, -> { joins(:person).where(people: {closed_account: false}) }
|
scope :active, -> { joins(:person).where(people: {closed_account: false}) }
|
||||||
|
|
||||||
devise :token_authenticatable, :database_authenticatable, :registerable,
|
devise :database_authenticatable, :registerable,
|
||||||
:recoverable, :rememberable, :trackable, :validatable,
|
:recoverable, :rememberable, :trackable, :validatable,
|
||||||
:lockable, :lastseenable, :lock_strategy => :none, :unlock_strategy => :none
|
:lockable, :lastseenable, :lock_strategy => :none, :unlock_strategy => :none
|
||||||
|
|
||||||
|
|
|
||||||
26
app/models/user/authentication_token.rb
Normal file
26
app/models/user/authentication_token.rb
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
class User
|
||||||
|
module AuthenticationToken
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
# Generate new authentication token and save the record.
|
||||||
|
def reset_authentication_token!
|
||||||
|
self.authentication_token = self.class.authentication_token
|
||||||
|
save(validate: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate authentication token unless already exists and save the record.
|
||||||
|
def ensure_authentication_token!
|
||||||
|
reset_authentication_token! if authentication_token.blank?
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
# Generate a token checking if one does not already exist in the database.
|
||||||
|
def authentication_token
|
||||||
|
loop do
|
||||||
|
token = Devise.friendly_token(30)
|
||||||
|
break token unless User.exists?(authentication_token: token)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -104,7 +104,7 @@ class PostPresenter < BasePresenter
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_reshare
|
def user_reshare
|
||||||
@post.reshare_for(current_user)
|
@post.reshare_for(current_user).try(:as_api_response, :backbone)
|
||||||
end
|
end
|
||||||
|
|
||||||
def already_participated_in_poll
|
def already_participated_in_poll
|
||||||
|
|
|
||||||
30
app/views/application/_head.haml
Normal file
30
app/views/application/_head.haml
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
%title
|
||||||
|
= page_title yield(:page_title)
|
||||||
|
|
||||||
|
%meta{charset: "utf-8"}/
|
||||||
|
= content_for?(:meta_data) ? yield(:meta_data) : metas_tags
|
||||||
|
|
||||||
|
/ favicon
|
||||||
|
/ For Apple devices
|
||||||
|
%link{rel: "apple-touch-icon", href: image_path("apple-touch-icon.png")}
|
||||||
|
/ For Nokia devices
|
||||||
|
%link{rel: "shortcut icon", href: image_path("apple-touch-icon.png")}
|
||||||
|
/ All others
|
||||||
|
%link{rel: "shortcut icon", href: image_path("favicon.png")}
|
||||||
|
|
||||||
|
- if rtl?
|
||||||
|
= stylesheet_link_tag :rtl, media: "all"
|
||||||
|
|
||||||
|
- if Rails.env.test?
|
||||||
|
= stylesheet_link_tag :poltergeist_disable_transition, media: "all"
|
||||||
|
|
||||||
|
= jquery_include_tag
|
||||||
|
= include_gon(camel_case: true, nonce: content_security_policy_nonce(:script))
|
||||||
|
= yield(:javascript)
|
||||||
|
|
||||||
|
= chartbeat_head_block
|
||||||
|
= csrf_meta_tag
|
||||||
|
= current_user_atom_tag
|
||||||
|
= include_mixpanel
|
||||||
|
|
||||||
|
= yield(:head)
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t('.title')
|
= t(".title")
|
||||||
|
|
||||||
.container-fluid#contacts_container
|
.container-fluid#contacts_container
|
||||||
.row
|
.row
|
||||||
|
|
@ -9,33 +9,34 @@
|
||||||
|
|
||||||
.col-md-9
|
.col-md-9
|
||||||
.stream.contacts.framed-content#people_stream
|
.stream.contacts.framed-content#people_stream
|
||||||
= render 'contacts/header'
|
= render "contacts/header"
|
||||||
|
|
||||||
- if @contacts_size > 0
|
- if @contacts_size > 0
|
||||||
- if @aspect && @aspect.contacts.length == 0
|
- if @aspect && @aspect.contacts.length == 0
|
||||||
.well
|
.well
|
||||||
= t('.no_contacts_in_aspect')
|
= t(".no_contacts_in_aspect")
|
||||||
#contact_stream
|
#contact_stream
|
||||||
-# JS
|
-# JS
|
||||||
|
|
||||||
- else
|
- else
|
||||||
.no_contacts
|
.no_contacts
|
||||||
%h3
|
%h3
|
||||||
= t('.no_contacts')
|
= t(".no_contacts")
|
||||||
|
- if AppConfig.settings.community_spotlight.enable?
|
||||||
|
%p
|
||||||
|
!= t(".no_contacts_message",
|
||||||
|
community_spotlight: link_to(t(".community_spotlight"), community_spotlight_path))
|
||||||
%p
|
%p
|
||||||
!= t('.no_contacts_message',
|
.btn.btn-link{"data-toggle" => "modal"}
|
||||||
:community_spotlight => link_to(t('.community_spotlight'), community_spotlight_path))
|
= t("invitations.new.invite_someone_to_join")
|
||||||
%p
|
|
||||||
.btn.btn-link{ 'data-toggle' => 'modal' }
|
|
||||||
= t('invitations.new.invite_someone_to_join')
|
|
||||||
|
|
||||||
#paginate
|
#paginate
|
||||||
.loader.hidden
|
.loader.hidden
|
||||||
.spinner
|
.spinner
|
||||||
|
|
||||||
-if @aspect
|
-if @aspect
|
||||||
#new_conversation_pane
|
.conversations-form-container#new_conversation_pane
|
||||||
= render 'shared/modal',
|
= render "shared/modal",
|
||||||
:path => new_conversation_path(:aspect_id => @aspect.id, :name => @aspect.name, :modal => true),
|
path: new_conversation_path(aspect_id: @aspect.id, name: @aspect.name, modal: true),
|
||||||
:title => t('conversations.index.new_conversation'),
|
title: t("conversations.index.new_conversation"),
|
||||||
:id => 'conversationModal'
|
id: "conversationModal"
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,13 @@
|
||||||
= form_for Conversation.new, html: {id: "new-conversation",
|
= form_for Conversation.new, html: {id: "new-conversation",
|
||||||
class: "new-conversation form-horizontal"}, remote: true do |conversation|
|
class: "new-conversation form-horizontal"}, remote: true do |conversation|
|
||||||
.form-group
|
.form-group
|
||||||
%label#toLabel{for: "contact_ids"}
|
%label#to-label{for: "contacts-search-input"}= t(".to")
|
||||||
= t(".to")
|
.recipients-tag-list.clearfix#recipients-tag-list
|
||||||
= text_field_tag "contact_autocomplete", nil, id: "contact-autocomplete", class: "form-control"
|
= text_field_tag "contact_autocomplete", nil, id: "contacts-search-input", class: "form-control"
|
||||||
|
- unless defined?(mobile) && mobile
|
||||||
|
= text_field_tag "person_ids", nil, id: "contact-ids", type: "hidden",
|
||||||
|
aria: {labelledby: "to-label"}
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
%label#subject-label{for: "conversation-subject"}
|
%label#subject-label{for: "conversation-subject"}
|
||||||
= t(".subject")
|
= t(".subject")
|
||||||
|
|
@ -14,12 +18,14 @@
|
||||||
aria: {labelledby: "subject-label"},
|
aria: {labelledby: "subject-label"},
|
||||||
value: "",
|
value: "",
|
||||||
placeholder: t("conversations.new.subject_default")
|
placeholder: t("conversations.new.subject_default")
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
%label.sr-only#message-label{for: "new-message-text"} = t(".message")
|
%label.sr-only#message-label{for: "new-message-text"}= t(".message")
|
||||||
= text_area_tag "conversation[text]", "",
|
= text_area_tag "conversation[text]", "",
|
||||||
rows: 5,
|
rows: 5,
|
||||||
id: "new-message-text",
|
id: "new-message-text",
|
||||||
class: "conversation-message-text input-block-level form-control",
|
class: "conversation-message-text input-block-level form-control",
|
||||||
aria: {labelledby: "message-label"}
|
aria: {labelledby: "message-label"}
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
= conversation.submit t(".send"), "data-disable-with" => t(".sending"), :class => "btn btn-primary pull-right"
|
= conversation.submit t(".send"), "data-disable-with" => t(".sending"), :class => "btn btn-primary pull-right"
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,4 @@
|
||||||
- for participant in conversation.participants
|
- for participant in conversation.participants
|
||||||
= person_image_link(participant, :size => :thumb_small)
|
= person_image_link(participant, :size => :thumb_small)
|
||||||
|
|
||||||
.stream
|
= render partial: "messages", locals: {conversation: conversation}
|
||||||
= render partial: 'messages', locals: { conversation: conversation }
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,2 @@
|
||||||
:javascript
|
= include_gon camel_case: true
|
||||||
$(document).ready(function () {
|
|
||||||
var data = $.parseJSON( "#{escape_javascript(@contacts_json)}" );
|
|
||||||
new app.views.ConversationsForm({
|
|
||||||
el: $("form#new-conversation").parent(),
|
|
||||||
contacts: data,
|
|
||||||
prefillName: "#{h params[:name]}",
|
|
||||||
prefillValue: "#{@contact_ids}"
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
= render 'conversations/new'
|
= render 'conversations/new'
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
:plain
|
:plain
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
var data = $.parseJSON( "#{escape_javascript(@contacts_json).html_safe}" ),
|
var data = $.parseJSON( "#{escape_javascript(@contacts_json).html_safe}" ),
|
||||||
autocompleteInput = $("#contact-autocomplete");
|
autocompleteInput = $("#contacts-search-input");
|
||||||
|
|
||||||
autocompleteInput.autoSuggest(data, {
|
autocompleteInput.autoSuggest(data, {
|
||||||
selectedItemProp: "name",
|
selectedItemProp: "name",
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
retrieveLimit: 10,
|
retrieveLimit: 10,
|
||||||
minChars: 1,
|
minChars: 1,
|
||||||
keyDelay: 0,
|
keyDelay: 0,
|
||||||
startText: '',
|
startText: "",
|
||||||
emptyText: "#{t("no_results")}",
|
emptyText: "#{t("no_results")}",
|
||||||
preFill: [{name : "#{h params[:name]}",
|
preFill: [{name : "#{h params[:name]}",
|
||||||
value : "#{@contact_ids}"}]
|
value : "#{@contact_ids}"}]
|
||||||
|
|
@ -27,6 +27,6 @@
|
||||||
#flash-messages
|
#flash-messages
|
||||||
.container-fluid.row
|
.container-fluid.row
|
||||||
%h3
|
%h3
|
||||||
= t('conversations.index.new_conversation')
|
= t("conversations.index.new_conversation")
|
||||||
|
|
||||||
= render 'conversations/new'
|
= render "conversations/new", mobile: true
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
- if controller_name != 'sessions'
|
- if controller_name != 'sessions'
|
||||||
= link_to t('.sign_in'), new_session_path(resource_name)
|
= link_to t('.sign_in'), new_session_path(resource_name)
|
||||||
%br/
|
%br/
|
||||||
- if AppConfig.settings.enable_registrations? && devise_mapping.registerable? && controller_name != 'registrations'
|
- if display_registration_link?
|
||||||
= link_to t('.sign_up'), new_registration_path(resource_name)
|
= link_to t('.sign_up'), new_registration_path(resource_name)
|
||||||
%br/
|
%br/
|
||||||
- else
|
- else
|
||||||
%b= t('.sign_up_closed')
|
%b= t('.sign_up_closed')
|
||||||
%br/
|
%br/
|
||||||
- if devise_mapping.recoverable? && controller_name != 'passwords'
|
- if display_password_reset_link?
|
||||||
= link_to t('.forgot_your_password'), new_password_path(resource_name)
|
= link_to t('.forgot_your_password'), new_password_path(resource_name)
|
||||||
%br/
|
%br/
|
||||||
- if devise_mapping.confirmable? && controller_name != 'confirmations'
|
- if devise_mapping.confirmable? && controller_name != 'confirmations'
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,33 @@
|
||||||
#paste_link
|
#paste_link
|
||||||
= t('.paste_link')
|
= t(".paste_link")
|
||||||
%span#codes_left
|
%span#codes_left
|
||||||
= "(" + t(".codes_left", count: @invite_code.count) + ")" unless AppConfig.settings.enable_registrations?
|
= "(" + t(".codes_left", count: @invite_code.count) + ")" unless AppConfig.settings.enable_registrations?
|
||||||
.form-horizontal
|
.form-horizontal
|
||||||
.control-group
|
.control-group
|
||||||
= invite_link(@invite_code)
|
= invite_link(@invite_code)
|
||||||
|
|
||||||
#email_invitation
|
- if AppConfig.mail.enable?
|
||||||
= form_tag new_user_invitation_path, class: 'form-horizontal' do
|
#email_invitation
|
||||||
|
= form_tag new_user_invitation_path, class: "form-horizontal" do
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
%label.col-sm-2.control-label{ for: 'email_inviter_emails' }
|
%label.col-sm-2.control-label{for: "email_inviter_emails"}
|
||||||
= t('email')
|
= t("email")
|
||||||
.col-sm-10
|
.col-sm-10
|
||||||
= text_field_tag 'email_inviter[emails]', @invalid_emails, title: t('.comma_separated_plz'),
|
= text_field_tag "email_inviter[emails]", @invalid_emails, title: t(".comma_separated_plz"),
|
||||||
placeholder: 'foo@bar.com, max@foo.com...', class: "form-control"
|
placeholder: "foo@bar.com, max@foo.com...", class: "form-control"
|
||||||
#already_sent
|
#already_sent
|
||||||
= t("invitations.create.note_already_sent", emails: @valid_emails) unless @valid_emails.empty?
|
= t("invitations.create.note_already_sent", emails: @valid_emails) unless @valid_emails.empty?
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
%label.col-sm-2.control-label{ for: 'email_inviter_locale' }
|
%label.col-sm-2.control-label{for: "email_inviter_locale"}
|
||||||
= t('.language')
|
= t(".language")
|
||||||
.col-sm-10
|
.col-sm-10
|
||||||
= select_tag 'email_inviter[locale]', options_from_collection_for_select(available_language_options,
|
= select_tag "email_inviter[locale]", options_from_collection_for_select(available_language_options,
|
||||||
"second", "first", selected: current_user.language), class: "form-control"
|
"second", "first", selected: current_user.language), class: "form-control"
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
.pull-right.col-md-12
|
.pull-right.col-md-12
|
||||||
= submit_tag t('.send_an_invitation'), class: 'btn btn-primary pull-right',
|
= submit_tag t(".send_an_invitation"), class: "btn btn-primary pull-right",
|
||||||
data: {disable_with: t('.sending_invitation')}
|
data: {disable_with: t(".sending_invitation")}
|
||||||
.clearfix
|
.clearfix
|
||||||
|
|
|
||||||
|
|
@ -3,47 +3,25 @@
|
||||||
-# the COPYRIGHT file.
|
-# the COPYRIGHT file.
|
||||||
|
|
||||||
!!!
|
!!!
|
||||||
%html{lang: I18n.locale.to_s, dir: (rtl?) ? 'rtl' : 'ltr'}
|
%html{lang: I18n.locale.to_s, dir: (rtl? ? "rtl" : "ltr")}
|
||||||
%head{prefix: og_prefix}
|
%head{prefix: og_prefix}
|
||||||
%title
|
%meta{name: "viewport", content: "width=device-width, initial-scale=1"}/
|
||||||
= page_title yield(:page_title)
|
|
||||||
|
|
||||||
%meta{charset: 'utf-8'}/
|
- content_for :javascript do
|
||||||
%meta{name: "viewport", content: "width=device-width, initial-scale=1"}/
|
= old_browser_js_support
|
||||||
= content_for?(:meta_data) ? yield(:meta_data) : metas_tags
|
|
||||||
|
|
||||||
%link{rel: 'shortcut icon', href: "#{image_path('favicon.png')}" }
|
<!--[if IE]>
|
||||||
|
= javascript_include_tag :ie
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
= chartbeat_head_block
|
= javascript_include_tag :main, :templates
|
||||||
= include_mixpanel
|
= load_javascript_locales
|
||||||
|
|
||||||
|
= render "head"
|
||||||
= include_color_theme
|
= include_color_theme
|
||||||
|
|
||||||
- if rtl?
|
|
||||||
= stylesheet_link_tag :rtl, media: 'all'
|
|
||||||
|
|
||||||
- if Rails.env.test?
|
|
||||||
= stylesheet_link_tag :poltergeist_disable_transition, media: "all"
|
|
||||||
|
|
||||||
= old_browser_js_support
|
|
||||||
<!--[if IE]>
|
|
||||||
= javascript_include_tag :ie
|
|
||||||
<![endif]-->
|
|
||||||
|
|
||||||
= jquery_include_tag
|
|
||||||
= javascript_include_tag :main, :templates
|
|
||||||
= load_javascript_locales
|
|
||||||
|
|
||||||
= translation_missing_warnings
|
= translation_missing_warnings
|
||||||
= current_user_atom_tag
|
|
||||||
|
|
||||||
= yield(:head)
|
%body{class: "page-#{controller_name} action-#{action_name}"}
|
||||||
= csrf_meta_tag
|
|
||||||
|
|
||||||
|
|
||||||
= include_gon(camel_case: true, nonce: content_security_policy_nonce(:script))
|
|
||||||
|
|
||||||
%body{ class: "page-#{controller_name} action-#{action_name}" }
|
|
||||||
= yield :before_content
|
= yield :before_content
|
||||||
|
|
||||||
%noscript
|
%noscript
|
||||||
|
|
|
||||||
|
|
@ -3,56 +3,25 @@
|
||||||
-# the COPYRIGHT file.
|
-# the COPYRIGHT file.
|
||||||
|
|
||||||
!!!
|
!!!
|
||||||
%html{:lang => I18n.locale.to_s, :dir => (rtl?) ? 'rtl' : 'ltr'}
|
%html{lang: I18n.locale.to_s, dir: (rtl? ? "rtl" : "ltr")}
|
||||||
%head
|
%head{prefix: og_prefix}
|
||||||
%title
|
- content_for :javascript do
|
||||||
= pod_name
|
= javascript_include_tag "mobile/mobile"
|
||||||
|
= load_javascript_locales
|
||||||
|
|
||||||
%meta{:name => "description", :content => "diaspora* mobile"}/
|
= render "head"
|
||||||
%meta{:name => "author", :content => "Diaspora, Inc."}/
|
= include_color_theme "mobile"
|
||||||
%meta{:charset => 'utf-8'}/
|
|
||||||
|
|
||||||
/ Viewport scale
|
%meta{name: "viewport", content: "width=device-width, minimum-scale=1 maximum-scale=1"}/
|
||||||
%meta{:name =>'viewport', :content => "width=device-width, minimum-scale=1 maximum-scale=1"}/
|
%meta{name: "HandheldFriendly", content: "True"}/
|
||||||
%meta{:name => "HandheldFriendly", :content => "True"}/
|
%meta{name: "MobileOptimized", content: "320"}/
|
||||||
%meta{:name => "MobileOptimized", :content => "320"}/
|
%meta{"http-equiv" => "cleartype", :content => "on"}/
|
||||||
/ Force cleartype on WP7
|
|
||||||
%meta{'http-equiv' => "cleartype", :content => 'on'}/
|
|
||||||
|
|
||||||
/ Home screen icon (sized for retina displays)
|
|
||||||
%link{rel: "apple-touch-icon", href: image_path("apple-touch-icon.png")}
|
|
||||||
/ For Nokia devices
|
|
||||||
%link{rel: "shortcut icon", href: image_path("apple-touch-icon.png")}
|
|
||||||
/ For desktop
|
|
||||||
%link{rel: 'shortcut icon', href: image_path("favicon.png")}
|
|
||||||
|
|
||||||
/ iOS mobile web app indicator
|
/ iOS mobile web app indicator
|
||||||
/ NOTE(we will enable these once we don't have to rely on back/forward buttons anymore)
|
/ NOTE(we will enable these once we don't have to rely on back/forward buttons anymore)
|
||||||
/%meta{:name => "apple-mobile-web-app-capable", :content => "yes"}
|
/%meta{:name => "apple-mobile-web-app-capable", :content => "yes"}
|
||||||
/%link{:rel => "apple-touch-startup-image", :href => "/images/apple-splash.png"}
|
/%link{:rel => "apple-touch-startup-image", :href => "/images/apple-splash.png"}
|
||||||
= yield :meta_data
|
|
||||||
|
|
||||||
= chartbeat_head_block
|
|
||||||
|
|
||||||
/ Stylesheets
|
|
||||||
|
|
||||||
= include_color_theme "mobile"
|
|
||||||
= yield(:custom_css)
|
|
||||||
|
|
||||||
|
|
||||||
= csrf_meta_tag
|
|
||||||
|
|
||||||
- if rtl?
|
|
||||||
= stylesheet_link_tag :rtl, :media => 'all'
|
|
||||||
|
|
||||||
- if Rails.env.test?
|
|
||||||
= stylesheet_link_tag :poltergeist_disable_transition, media: "all"
|
|
||||||
|
|
||||||
= jquery_include_tag
|
|
||||||
|
|
||||||
= yield(:head)
|
|
||||||
|
|
||||||
= include_gon(camel_case: true, nonce: content_security_policy_nonce(:script))
|
|
||||||
%body
|
%body
|
||||||
#app
|
#app
|
||||||
= render "layouts/header"
|
= render "layouts/header"
|
||||||
|
|
@ -62,10 +31,8 @@
|
||||||
#main{:role => "main"}
|
#main{:role => "main"}
|
||||||
- if current_page?(:activity_stream)
|
- if current_page?(:activity_stream)
|
||||||
%h3
|
%h3
|
||||||
= t('streams.activity.title')
|
= t("streams.activity.title")
|
||||||
= yield
|
= yield
|
||||||
|
|
||||||
/ javascripts at the bottom
|
|
||||||
= javascript_include_tag "mobile/mobile"
|
|
||||||
= load_javascript_locales
|
|
||||||
= include_chartbeat
|
= include_chartbeat
|
||||||
|
= include_mixpanel_guid
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
= t(".notifications")
|
= t(".notifications")
|
||||||
.list-group
|
.list-group
|
||||||
%a.list-group-item{href: "/notifications" + (params[:show] == "unread" ? "?show=unread" : ""),
|
%a.list-group-item{href: "/notifications" + (params[:show] == "unread" ? "?show=unread" : ""),
|
||||||
class: ("active" unless params[:type] && @grouped_unread_notification_counts.has_key?(params[:type]))}
|
class: ("active" unless params[:type] && @grouped_unread_notification_counts.has_key?(params[:type])),
|
||||||
|
data: {type: "all"}}
|
||||||
%span.pull-right.badge{class: ("hidden" unless @unread_notification_count > 0)}
|
%span.pull-right.badge{class: ("hidden" unless @unread_notification_count > 0)}
|
||||||
= @unread_notification_count
|
= @unread_notification_count
|
||||||
= t(".all_notifications")
|
= t(".all_notifications")
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
id: 'mentionModal'
|
id: 'mentionModal'
|
||||||
|
|
||||||
-if @contact
|
-if @contact
|
||||||
#new_conversation_pane
|
.conversations-form-container#new_conversation_pane
|
||||||
= render 'shared/modal',
|
= render 'shared/modal',
|
||||||
path: new_conversation_path(:contact_id => @contact.id, name: @contact.person.name, modal: true),
|
path: new_conversation_path(:contact_id => @contact.id, name: @contact.person.name, modal: true),
|
||||||
title: t('conversations.index.new_conversation'),
|
title: t('conversations.index.new_conversation'),
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
-# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
||||||
-# licensed under the Affero General Public License version 3 or later. See
|
|
||||||
-# the COPYRIGHT file.
|
|
||||||
|
|
||||||
- content_for :head do
|
|
||||||
= javascript_include_tag :photos
|
|
||||||
|
|
||||||
#author_info
|
|
||||||
= person_image_link(post.author, :size => :thumb_small)
|
|
||||||
.from
|
|
||||||
%h2
|
|
||||||
= post.author_name
|
|
||||||
|
|
||||||
#show_photo{:data=>{:guid=>post.id}}
|
|
||||||
= image_tag post.url(:scaled_full)
|
|
||||||
|
|
||||||
#caption
|
|
||||||
= post.text
|
|
||||||
|
|
||||||
%br
|
|
||||||
= link_to t('photos.show.show_original_post'), post_path(post.status_message)
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
= t(".share_this")
|
= t(".share_this")
|
||||||
= invite_link(current_user.invitation_code)
|
= invite_link(current_user.invitation_code)
|
||||||
.invitations-link.btn.btn-link#invitations-button{"data-toggle" => "modal"}
|
|
||||||
= t(".by_email")
|
|
||||||
|
|
||||||
= render "shared/modal",
|
- if AppConfig.mail.enable?
|
||||||
path: new_user_invitation_path,
|
.invitations-link.btn.btn-link#invitations-button{"data-toggle" => "modal"}
|
||||||
id: "invitationsModal",
|
= t(".by_email")
|
||||||
title: t("invitations.new.invite_someone_to_join")
|
|
||||||
|
- content_for :after_content do
|
||||||
|
= render "shared/modal",
|
||||||
|
path: new_user_invitation_path,
|
||||||
|
id: "invitationsModal",
|
||||||
|
title: t("invitations.new.invite_someone_to_join")
|
||||||
|
|
|
||||||
|
|
@ -117,58 +117,59 @@
|
||||||
|
|
||||||
= render partial: "post_default"
|
= render partial: "post_default"
|
||||||
|
|
||||||
.row
|
- if AppConfig.mail.enable?
|
||||||
.col-md-12
|
.row
|
||||||
%h3
|
.col-md-12
|
||||||
= t(".receive_email_notifications")
|
%h3
|
||||||
= form_for "user", url: edit_user_path, html: {method: :put} do |f|
|
= t(".receive_email_notifications")
|
||||||
= f.fields_for :email_preferences do |type|
|
= form_for "user", url: edit_user_path, html: {method: :put} do |f|
|
||||||
#email_prefs
|
= f.fields_for :email_preferences do |type|
|
||||||
- if current_user.admin?
|
#email_prefs
|
||||||
= type.label :someone_reported, class: "checkbox-inline" do
|
- if current_user.admin?
|
||||||
= type.check_box :someone_reported, {checked: @email_prefs["someone_reported"]}, false, true
|
= type.label :someone_reported, class: "checkbox-inline" do
|
||||||
= t(".someone_reported")
|
= type.check_box :someone_reported, {checked: @email_prefs["someone_reported"]}, false, true
|
||||||
|
= t(".someone_reported")
|
||||||
|
|
||||||
.small-horizontal-spacer
|
.small-horizontal-spacer
|
||||||
|
|
||||||
= type.label :started_sharing, class: "checkbox-inline" do
|
= type.label :started_sharing, class: "checkbox-inline" do
|
||||||
= type.check_box :started_sharing, {checked: @email_prefs["started_sharing"]}, false, true
|
= type.check_box :started_sharing, {checked: @email_prefs["started_sharing"]}, false, true
|
||||||
= t(".started_sharing")
|
= t(".started_sharing")
|
||||||
.small-horizontal-spacer
|
.small-horizontal-spacer
|
||||||
|
|
||||||
= type.label :mentioned, class: "checkbox-inline" do
|
= type.label :mentioned, class: "checkbox-inline" do
|
||||||
= type.check_box :mentioned, {checked: @email_prefs["mentioned"]}, false, true
|
= type.check_box :mentioned, {checked: @email_prefs["mentioned"]}, false, true
|
||||||
= t(".mentioned")
|
= t(".mentioned")
|
||||||
.small-horizontal-spacer
|
.small-horizontal-spacer
|
||||||
|
|
||||||
= type.label :liked, class: "checkbox-inline" do
|
= type.label :liked, class: "checkbox-inline" do
|
||||||
= type.check_box :liked, {checked: @email_prefs["liked"]}, false, true
|
= type.check_box :liked, {checked: @email_prefs["liked"]}, false, true
|
||||||
= t(".liked")
|
= t(".liked")
|
||||||
.small-horizontal-spacer
|
.small-horizontal-spacer
|
||||||
|
|
||||||
= type.label :reshared, class: "checkbox-inline" do
|
= type.label :reshared, class: "checkbox-inline" do
|
||||||
= type.check_box :reshared, {checked: @email_prefs["reshared"]}, false, true
|
= type.check_box :reshared, {checked: @email_prefs["reshared"]}, false, true
|
||||||
= t(".reshared")
|
= t(".reshared")
|
||||||
.small-horizontal-spacer
|
.small-horizontal-spacer
|
||||||
|
|
||||||
= type.label :comment_on_post, class: "checkbox-inline" do
|
= type.label :comment_on_post, class: "checkbox-inline" do
|
||||||
= type.check_box :comment_on_post, {checked: @email_prefs["comment_on_post"]}, false, true
|
= type.check_box :comment_on_post, {checked: @email_prefs["comment_on_post"]}, false, true
|
||||||
= t(".comment_on_post")
|
= t(".comment_on_post")
|
||||||
.small-horizontal-spacer
|
.small-horizontal-spacer
|
||||||
|
|
||||||
= type.label :also_commented, class: "checkbox-inline" do
|
= type.label :also_commented, class: "checkbox-inline" do
|
||||||
= type.check_box :also_commented, {checked: @email_prefs["also_commented"]}, false, true
|
= type.check_box :also_commented, {checked: @email_prefs["also_commented"]}, false, true
|
||||||
= t(".also_commented")
|
= t(".also_commented")
|
||||||
.small-horizontal-spacer
|
.small-horizontal-spacer
|
||||||
|
|
||||||
= type.label :private_message, class: "checkbox-inline" do
|
= type.label :private_message, class: "checkbox-inline" do
|
||||||
= type.check_box :private_message, {checked: @email_prefs["private_message"]}, false, true
|
= type.check_box :private_message, {checked: @email_prefs["private_message"]}, false, true
|
||||||
= t(".private_message")
|
= t(".private_message")
|
||||||
|
|
||||||
.small-horizontal-spacer
|
.small-horizontal-spacer
|
||||||
|
|
||||||
.clearfix= f.submit t(".change"), class: "btn btn-primary pull-right", id: "change_email_preferences"
|
.clearfix= f.submit t(".change"), class: "btn btn-primary pull-right", id: "change_email_preferences"
|
||||||
%hr
|
%hr
|
||||||
|
|
||||||
.row
|
.row
|
||||||
.col-md-6#account_data
|
.col-md-6#account_data
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue