diff --git a/app/javascript/styles/gabsocial/components/buttons.scss b/app/javascript/styles/gabsocial/components/buttons.scss
index 36481aef..0270c1b7 100644
--- a/app/javascript/styles/gabsocial/components/buttons.scss
+++ b/app/javascript/styles/gabsocial/components/buttons.scss
@@ -1,16 +1,20 @@
-button {
+button,
+a.button {
&.standard {
+
+ // NOTE - will define the larger standard buttons here and apply class where used.
+
&-small {
- background: $gab-small-cta-primary;
- color: white;
- text-transform: uppercase;
- letter-spacing: 1px;
- font-size: 14px;
+ height: 20px;
+ padding: 5px 15px;
border: none;
border-radius: 4px;
- height: 25px;
- padding: 1px 12px;
- font-weight: bold;
+ @include font-size(11);
+ @include line-height(11);
+ @include font-weight(bold);
+ text-transform: uppercase;
+ color: white;
+ background: $gab-small-cta-primary;
}
}
}
From a6f09dc0c78bd9f159616ceef5d8fe14f6aceab1 Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Sat, 20 Jul 2019 01:06:32 +0300
Subject: [PATCH 30/41] group unread count
---
app/controllers/api/v1/timelines/group_controller.rb | 6 ++++++
app/models/group_account.rb | 1 +
app/models/status.rb | 5 +++++
.../20190721214831_add_unread_count_to_group_accounts.rb | 5 +++++
db/schema.rb | 3 ++-
5 files changed, 19 insertions(+), 1 deletion(-)
create mode 100644 db/migrate/20190721214831_add_unread_count_to_group_accounts.rb
diff --git a/app/controllers/api/v1/timelines/group_controller.rb b/app/controllers/api/v1/timelines/group_controller.rb
index 411418cb..b19f3961 100644
--- a/app/controllers/api/v1/timelines/group_controller.rb
+++ b/app/controllers/api/v1/timelines/group_controller.rb
@@ -9,6 +9,8 @@ class Api::V1::Timelines::GroupController < Api::BaseController
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
def show
+ mark_as_unread
+
render json: @statuses,
each_serializer: REST::StatusSerializer,
relationships: StatusRelationshipsPresenter.new(@statuses, current_user.account_id)
@@ -16,6 +18,10 @@ class Api::V1::Timelines::GroupController < Api::BaseController
private
+ def mark_as_unread
+ GroupAccount.where(group: @group, account: current_account).update_all("unread_count = 0")
+ end
+
def set_group
@group = Group.find(params[:id])
end
diff --git a/app/models/group_account.rb b/app/models/group_account.rb
index ea4ec62d..12485d98 100644
--- a/app/models/group_account.rb
+++ b/app/models/group_account.rb
@@ -9,6 +9,7 @@
# role :string
# created_at :datetime not null
# updated_at :datetime not null
+# unread_count :integer default(0)
#
class GroupAccount < ApplicationRecord
diff --git a/app/models/status.rb b/app/models/status.rb
index ae86194b..ce467daf 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -256,6 +256,7 @@ class Status < ApplicationRecord
after_create_commit :store_uri, if: :local?
after_create_commit :update_statistics, if: :local?
+ after_create_commit :increase_group_unread_counts, if: Proc.new { |status| !status.group_id.nil? }
around_create GabSocial::Snowflake::Callbacks
@@ -535,4 +536,8 @@ class Status < ApplicationRecord
AccountConversation.remove_status(inbox_owner, self)
end
end
+
+ def increase_group_unread_counts
+ GroupAccount.where(group_id: group_id).where.not(account_id: account_id).update_all("unread_count = unread_count + 1")
+ end
end
diff --git a/db/migrate/20190721214831_add_unread_count_to_group_accounts.rb b/db/migrate/20190721214831_add_unread_count_to_group_accounts.rb
new file mode 100644
index 00000000..8a9f19df
--- /dev/null
+++ b/db/migrate/20190721214831_add_unread_count_to_group_accounts.rb
@@ -0,0 +1,5 @@
+class AddUnreadCountToGroupAccounts < ActiveRecord::Migration[5.2]
+ def change
+ add_column :group_accounts, :unread_count, :integer, default: 0
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a27da0bf..b3aaf19c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_07_16_173227) do
+ActiveRecord::Schema.define(version: 2019_07_21_214831) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -327,6 +327,7 @@ ActiveRecord::Schema.define(version: 2019_07_16_173227) do
t.string "role"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.integer "unread_count", default: 0
t.index ["account_id", "group_id"], name: "index_group_accounts_on_account_id_and_group_id", unique: true
t.index ["account_id"], name: "index_group_accounts_on_account_id"
t.index ["group_id", "account_id"], name: "index_group_accounts_on_group_id_and_account_id"
From c5c2585239b7b5c96b1f54b989f7538dbac73b2a Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Sat, 20 Jul 2019 02:04:08 +0300
Subject: [PATCH 31/41] group unread count
---
app/models/concerns/group_interactions.rb | 12 ++++++++++--
app/presenters/group_relationships_presenter.rb | 14 +++++++++-----
.../rest/group_relationship_serializer.rb | 6 +++++-
3 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/app/models/concerns/group_interactions.rb b/app/models/concerns/group_interactions.rb
index 4083f5c9..79b4470f 100644
--- a/app/models/concerns/group_interactions.rb
+++ b/app/models/concerns/group_interactions.rb
@@ -10,14 +10,22 @@ module GroupInteractions
end
def admin_map(target_group_ids, account_id)
- follow_mapping(GroupAccount.where(group_id: target_group_ids, account_id: account_id, role: :admin), :group_id)
- end
+ follow_mapping(GroupAccount.where(group_id: target_group_ids, account_id: account_id, role: :admin), :group_id)
+ end
+
+ def unread_count_map(target_group_ids, account_id)
+ unread_count_mapping(GroupAccount.where(group_id: target_group_ids, account_id: account_id), :unread_count)
+ end
private
def follow_mapping(query, field)
query.pluck(field).each_with_object({}) { |id, mapping| mapping[id] = true }
end
+
+ def unread_count_mapping(query, field)
+ query.pluck(:group_id, :unread_count).each_with_object({}) { |e, mapping| mapping[e[0]] = e[1] }
+ end
end
end
diff --git a/app/presenters/group_relationships_presenter.rb b/app/presenters/group_relationships_presenter.rb
index 72688cd2..76e97570 100644
--- a/app/presenters/group_relationships_presenter.rb
+++ b/app/presenters/group_relationships_presenter.rb
@@ -1,19 +1,21 @@
# frozen_string_literal: true
class GroupRelationshipsPresenter
- attr_reader :member, :admin
+ attr_reader :member, :admin, :unread_count
def initialize(group_ids, current_account_id, **options)
@group_ids = group_ids.map { |a| a.is_a?(Group) ? a.id : a }
@current_account_id = current_account_id
- @member = cached[:member].merge(Group.member_map(@uncached_group_ids, @current_account_id))
- @admin = cached[:admin].merge(Group.admin_map(@uncached_group_ids, @current_account_id))
+ @member = cached[:member].merge(Group.member_map(@uncached_group_ids, @current_account_id))
+ @admin = cached[:admin].merge(Group.admin_map(@uncached_group_ids, @current_account_id))
+ @unread_count = cached[:unread_count].merge(Group.unread_count_map(@uncached_group_ids, @current_account_id))
cache_uncached!
@member.merge!(options[:member_map] || {})
@admin.merge!(options[:admin_map] || {})
+ @unread_count.merge!(options[:unread_count_map] || {})
end
private
@@ -24,6 +26,7 @@ class GroupRelationshipsPresenter
@cached = {
member: {},
admin: {},
+ unread_count: {},
}
@uncached_group_ids = []
@@ -44,8 +47,9 @@ class GroupRelationshipsPresenter
def cache_uncached!
@uncached_group_ids.each do |group_id|
maps_for_account = {
- member: { group_id => member[group_id] },
- admin: { group_id => admin[group_id] },
+ member: { group_id => member[group_id] },
+ admin: { group_id => admin[group_id] },
+ unread_count: { group_id => unread_count[group_id] },
}
Rails.cache.write("relationship:#{@current_account_id}:group#{group_id}", maps_for_account, expires_in: 1.day)
diff --git a/app/serializers/rest/group_relationship_serializer.rb b/app/serializers/rest/group_relationship_serializer.rb
index 63c44115..a420ddbc 100644
--- a/app/serializers/rest/group_relationship_serializer.rb
+++ b/app/serializers/rest/group_relationship_serializer.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class REST::GroupRelationshipSerializer < ActiveModel::Serializer
- attributes :id, :member, :admin
+ attributes :id, :member, :admin, :unread_count
def id
object.id.to_s
@@ -14,4 +14,8 @@ class REST::GroupRelationshipSerializer < ActiveModel::Serializer
def admin
instance_options[:relationships].admin[object.id] ? true : false
end
+
+ def unread_count
+ instance_options[:relationships].unread_count[object.id] || 0
+ end
end
From 61134fb6452c146124ff402b80ff1ddba8a9621e Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Sat, 20 Jul 2019 02:36:55 +0300
Subject: [PATCH 32/41] group sidebar panel ui
---
.../features/groups/sidebar_panel/index.js | 45 +++++++++++++++++++
.../features/groups/sidebar_panel/item.js | 45 +++++++++++++++++++
app/javascript/gabsocial/pages/group_page.js | 5 ++-
app/javascript/gabsocial/pages/groups_page.js | 2 +
app/javascript/styles/application.scss | 1 +
.../components/group-sidebar-panel.scss | 29 ++++++++++++
6 files changed, 126 insertions(+), 1 deletion(-)
create mode 100644 app/javascript/gabsocial/features/groups/sidebar_panel/index.js
create mode 100644 app/javascript/gabsocial/features/groups/sidebar_panel/item.js
create mode 100644 app/javascript/styles/gabsocial/components/group-sidebar-panel.scss
diff --git a/app/javascript/gabsocial/features/groups/sidebar_panel/index.js b/app/javascript/gabsocial/features/groups/sidebar_panel/index.js
new file mode 100644
index 00000000..21880178
--- /dev/null
+++ b/app/javascript/gabsocial/features/groups/sidebar_panel/index.js
@@ -0,0 +1,45 @@
+import React from 'react';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+import { defineMessages, injectIntl } from 'react-intl';
+import { connect } from 'react-redux';
+import Item from './item';
+import Icon from 'gabsocial/components/icon';
+
+const messages = defineMessages({
+ title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups you\'re in' },
+});
+
+const mapStateToProps = (state, { id }) => ({
+ groupIds: state.getIn(['group_lists', 'member']),
+});
+
+export default @connect(mapStateToProps)
+@injectIntl
+class GroupSidebarPanel extends ImmutablePureComponent {
+ static propTypes = {
+ groupIds: ImmutablePropTypes.list,
+ }
+
+ render() {
+ const { intl, groupIds } = this.props;
+
+ // Only when there are groups to show
+ if (groupIds.count() === 0) return null;
+
+ return (
+
+
+
+ {intl.formatMessage(messages.title)}
+
+
+
+
+ {groupIds.map(groupId => )}
+
+
+
+ );
+ }
+}
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/groups/sidebar_panel/item.js b/app/javascript/gabsocial/features/groups/sidebar_panel/item.js
new file mode 100644
index 00000000..a4015c18
--- /dev/null
+++ b/app/javascript/gabsocial/features/groups/sidebar_panel/item.js
@@ -0,0 +1,45 @@
+import React from 'react';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+import { defineMessages, injectIntl } from 'react-intl';
+import { Link } from 'react-router-dom';
+import { shortNumberFormat } from '../../../utils/numbers';
+import { connect } from 'react-redux';
+
+const messages = defineMessages({
+ new_statuses: { id: 'groups.sidebar-panel.item.view', defaultMessage: 'new gabs' },
+ no_recent_activity: { id: 'groups.sidebar-panel.item.no_recent_activity', defaultMessage: 'No recent activity' },
+});
+
+const mapStateToProps = (state, { id }) => ({
+ group: state.getIn(['groups', id]),
+ relationships: state.getIn(['group_relationships', id]),
+});
+
+export default @connect(mapStateToProps)
+@injectIntl
+class Item extends ImmutablePureComponent {
+ static propTypes = {
+ group: ImmutablePropTypes.map,
+ relationships: ImmutablePropTypes.map,
+ }
+
+ render() {
+ const { intl, group, relationships } = this.props;
+
+ // Wait for relationships
+ if (!relationships) return null;
+
+ const unreadCount = relationships.get('unread_count');
+
+ return (
+
+
{group.get('title')}
+
+ {unreadCount > 0 && {shortNumberFormat(unreadCount)} {intl.formatMessage(messages.new_statuses)}}
+ {unreadCount === 0 && {intl.formatMessage(messages.no_recent_activity)}}
+
+
+ );
+ }
+}
\ No newline at end of file
diff --git a/app/javascript/gabsocial/pages/group_page.js b/app/javascript/gabsocial/pages/group_page.js
index c664a135..a6d4e329 100644
--- a/app/javascript/gabsocial/pages/group_page.js
+++ b/app/javascript/gabsocial/pages/group_page.js
@@ -8,7 +8,8 @@ import LinkFooter from '../features/ui/components/link_footer';
import PromoPanel from '../features/ui/components/promo_panel';
import HeaderContainer from '../features/groups/timeline/containers/header_container';
import GroupPanel from '../features/groups/timeline/components/panel';
-import { fetchGroup } from '../actions/groups';
+import { fetchGroup, fetchGroups } from '../actions/groups';
+import GroupSidebarPanel from '../features/groups/sidebar_panel';
const mapStateToProps = (state, { params: { id } }) => ({
group: state.getIn(['groups', id]),
@@ -27,6 +28,7 @@ class GroupPage extends ImmutablePureComponent {
componentWillMount() {
const { params: { id }, dispatch } = this.props;
+ dispatch(fetchGroups('member'));
dispatch(fetchGroup(id));
}
@@ -60,6 +62,7 @@ class GroupPage extends ImmutablePureComponent {
diff --git a/app/javascript/gabsocial/pages/groups_page.js b/app/javascript/gabsocial/pages/groups_page.js
index 141a530f..2cbaa481 100644
--- a/app/javascript/gabsocial/pages/groups_page.js
+++ b/app/javascript/gabsocial/pages/groups_page.js
@@ -7,6 +7,7 @@ import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel';
import LinkFooter from '../features/ui/components/link_footer';
import PromoPanel from '../features/ui/components/promo_panel';
import UserPanel from '../features/ui/components/user_panel';
+import GroupSidebarPanel from '../features/groups/sidebar_panel';
const mapStateToProps = state => ({
account: state.getIn(['accounts', me]),
@@ -42,6 +43,7 @@ class GroupsPage extends ImmutablePureComponent {
diff --git a/app/javascript/styles/application.scss b/app/javascript/styles/application.scss
index 9931e084..7b3c8c4e 100644
--- a/app/javascript/styles/application.scss
+++ b/app/javascript/styles/application.scss
@@ -27,6 +27,7 @@
@import 'gabsocial/components/group-card';
@import 'gabsocial/components/group-detail';
@import 'gabsocial/components/group-form';
+@import 'gabsocial/components/group-sidebar-panel';
@import 'gabsocial/polls';
@import 'gabsocial/introduction';
diff --git a/app/javascript/styles/gabsocial/components/group-sidebar-panel.scss b/app/javascript/styles/gabsocial/components/group-sidebar-panel.scss
new file mode 100644
index 00000000..a812ac12
--- /dev/null
+++ b/app/javascript/styles/gabsocial/components/group-sidebar-panel.scss
@@ -0,0 +1,29 @@
+.group-sidebar-panel {
+ &__items {
+ padding: 0 15px 15px;
+ }
+
+ &__item {
+ display: block;
+ color: $primary-text-color;
+ text-decoration: none;
+ margin-bottom: 15px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ &__title {
+ font-weight: bold;
+ }
+
+ &__meta {
+ font-size: 0.8em;
+ color: $gab-secondary-text;
+
+ &__unread {
+ color: $gab-brand-default;
+ }
+ }
+ }
+}
\ No newline at end of file
From 06e1c47ff47bd2a520087ece489f5a7f9248c36f Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Sat, 20 Jul 2019 02:45:14 +0300
Subject: [PATCH 33/41] group sidebar panel improvements
---
app/controllers/api/v1/groups_controller.rb | 2 +-
.../gabsocial/features/groups/sidebar_panel/index.js | 8 ++++++--
app/javascript/gabsocial/pages/groups_page.js | 2 --
.../styles/gabsocial/components/group-sidebar-panel.scss | 4 ++++
4 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/app/controllers/api/v1/groups_controller.rb b/app/controllers/api/v1/groups_controller.rb
index 8231ef00..837540f6 100644
--- a/app/controllers/api/v1/groups_controller.rb
+++ b/app/controllers/api/v1/groups_controller.rb
@@ -14,7 +14,7 @@ class Api::V1::GroupsController < Api::BaseController
when 'featured'
@groups = Group.where(is_featured: true).limit(25).all
when 'member'
- @groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account }).all
+ @groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account }).order('group_accounts.unread_count DESC, group_accounts.id DESC').all
when 'admin'
@groups = Group.joins(:group_accounts).where(is_archived: false, group_accounts: { account: current_account, role: :admin }).all
end
diff --git a/app/javascript/gabsocial/features/groups/sidebar_panel/index.js b/app/javascript/gabsocial/features/groups/sidebar_panel/index.js
index 21880178..88e74928 100644
--- a/app/javascript/gabsocial/features/groups/sidebar_panel/index.js
+++ b/app/javascript/gabsocial/features/groups/sidebar_panel/index.js
@@ -5,9 +5,11 @@ import { defineMessages, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import Item from './item';
import Icon from 'gabsocial/components/icon';
+import { Link } from 'react-router-dom';
const messages = defineMessages({
title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups you\'re in' },
+ show_all: { id: 'groups.sidebar-panel.show_all', defaultMessage: 'Show all' },
});
const mapStateToProps = (state, { id }) => ({
@@ -23,9 +25,10 @@ class GroupSidebarPanel extends ImmutablePureComponent {
render() {
const { intl, groupIds } = this.props;
+ const count = groupIds.count();
// Only when there are groups to show
- if (groupIds.count() === 0) return null;
+ if (count === 0) return null;
return (
@@ -36,7 +39,8 @@ class GroupSidebarPanel extends ImmutablePureComponent {
- {groupIds.map(groupId => )}
+ {groupIds.slice(0, 10).map(groupId => )}
+ {count > 10 && {intl.formatMessage(messages.show_all)}}
diff --git a/app/javascript/gabsocial/pages/groups_page.js b/app/javascript/gabsocial/pages/groups_page.js
index 2cbaa481..141a530f 100644
--- a/app/javascript/gabsocial/pages/groups_page.js
+++ b/app/javascript/gabsocial/pages/groups_page.js
@@ -7,7 +7,6 @@ import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel';
import LinkFooter from '../features/ui/components/link_footer';
import PromoPanel from '../features/ui/components/promo_panel';
import UserPanel from '../features/ui/components/user_panel';
-import GroupSidebarPanel from '../features/groups/sidebar_panel';
const mapStateToProps = state => ({
account: state.getIn(['accounts', me]),
@@ -43,7 +42,6 @@ class GroupsPage extends ImmutablePureComponent {
diff --git a/app/javascript/styles/gabsocial/components/group-sidebar-panel.scss b/app/javascript/styles/gabsocial/components/group-sidebar-panel.scss
index a812ac12..9b750f2e 100644
--- a/app/javascript/styles/gabsocial/components/group-sidebar-panel.scss
+++ b/app/javascript/styles/gabsocial/components/group-sidebar-panel.scss
@@ -1,6 +1,10 @@
.group-sidebar-panel {
&__items {
padding: 0 15px 15px;
+
+ &__show-all {
+ color: $primary-text-color;
+ }
}
&__item {
From 7bd832c9bd77ec5c9427b8162ba005d75c113690 Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Mon, 22 Jul 2019 02:50:01 +0300
Subject: [PATCH 34/41] better migrations for unread count field on group
accounts table
---
...0190721214831_add_unread_count_to_group_accounts.rb | 9 +++++++--
...4917_backfill_add_unread_count_to_group_accounts.rb | 10 ++++++++++
db/schema.rb | 2 +-
3 files changed, 18 insertions(+), 3 deletions(-)
create mode 100644 db/migrate/20190721234917_backfill_add_unread_count_to_group_accounts.rb
diff --git a/db/migrate/20190721214831_add_unread_count_to_group_accounts.rb b/db/migrate/20190721214831_add_unread_count_to_group_accounts.rb
index 8a9f19df..efe77fd7 100644
--- a/db/migrate/20190721214831_add_unread_count_to_group_accounts.rb
+++ b/db/migrate/20190721214831_add_unread_count_to_group_accounts.rb
@@ -1,5 +1,10 @@
class AddUnreadCountToGroupAccounts < ActiveRecord::Migration[5.2]
- def change
- add_column :group_accounts, :unread_count, :integer, default: 0
+ def up
+ add_column :group_accounts, :unread_count, :integer
+ change_column_default :group_accounts, :unread_count, 0
+ end
+
+ def down
+ remove_column :group_accounts, :unread_count
end
end
diff --git a/db/migrate/20190721234917_backfill_add_unread_count_to_group_accounts.rb b/db/migrate/20190721234917_backfill_add_unread_count_to_group_accounts.rb
new file mode 100644
index 00000000..e71fb1b0
--- /dev/null
+++ b/db/migrate/20190721234917_backfill_add_unread_count_to_group_accounts.rb
@@ -0,0 +1,10 @@
+class BackfillAddUnreadCountToGroupAccounts < ActiveRecord::Migration[5.2]
+ disable_ddl_transaction!
+
+ def change
+ GroupAccount.in_batches do |relation|
+ relation.update_all unread_count: 0
+ sleep(0.1)
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index b3aaf19c..d9bf6f1e 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_07_21_214831) do
+ActiveRecord::Schema.define(version: 2019_07_21_234917) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
From bd3f453c0da0eb4fa12232cab7d324bf0ba89850 Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Mon, 22 Jul 2019 03:10:42 +0300
Subject: [PATCH 35/41] fix
---
app/models/status.rb | 1 +
1 file changed, 1 insertion(+)
diff --git a/app/models/status.rb b/app/models/status.rb
index ce467daf..b259d063 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -539,5 +539,6 @@ class Status < ApplicationRecord
def increase_group_unread_counts
GroupAccount.where(group_id: group_id).where.not(account_id: account_id).update_all("unread_count = unread_count + 1")
+ Rails.cache.delete("relationship:#{account_id}:group#{group_id}")
end
end
From bf2d54201bb9c2056b4acc6fdeea0bd07c4853ab Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Mon, 22 Jul 2019 03:46:00 +0300
Subject: [PATCH 36/41] group member count optimization
---
app/models/group.rb | 1 +
app/models/group_account.rb | 10 ++++++++++
app/serializers/rest/group_serializer.rb | 4 ----
.../20190722003541_add_member_count_to_groups.rb | 10 ++++++++++
...0722003649_backfill_add_member_count_to_groups.rb | 10 ++++++++++
db/schema.rb | 3 ++-
lib/tasks/fix_group_member_counts.rake | 12 ++++++++++++
7 files changed, 45 insertions(+), 5 deletions(-)
create mode 100644 db/migrate/20190722003541_add_member_count_to_groups.rb
create mode 100644 db/migrate/20190722003649_backfill_add_member_count_to_groups.rb
create mode 100644 lib/tasks/fix_group_member_counts.rake
diff --git a/app/models/group.rb b/app/models/group.rb
index 1e3edbfb..1b03b569 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -15,6 +15,7 @@
# is_archived :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
+# member_count :integer default(0)
#
class Group < ApplicationRecord
diff --git a/app/models/group_account.rb b/app/models/group_account.rb
index 12485d98..b5aa62bc 100644
--- a/app/models/group_account.rb
+++ b/app/models/group_account.rb
@@ -21,10 +21,20 @@ class GroupAccount < ApplicationRecord
validates :account_id, uniqueness: { scope: :group_id }
after_commit :remove_relationship_cache
+ after_create :increment_member_count
+ after_destroy :decrement_member_count
private
def remove_relationship_cache
Rails.cache.delete("relationship:#{account_id}:group#{group_id}")
end
+
+ def increment_member_count
+ group&.increment!(:member_count)
+ end
+
+ def decrement_member_count
+ group&.decrement!(:member_count)
+ end
end
diff --git a/app/serializers/rest/group_serializer.rb b/app/serializers/rest/group_serializer.rb
index 52b1356b..e595bce4 100644
--- a/app/serializers/rest/group_serializer.rb
+++ b/app/serializers/rest/group_serializer.rb
@@ -22,8 +22,4 @@ class REST::GroupSerializer < ActiveModel::Serializer
full_asset_url(object.cover_image.url)
end
-
- def member_count
- object.accounts.count
- end
end
diff --git a/db/migrate/20190722003541_add_member_count_to_groups.rb b/db/migrate/20190722003541_add_member_count_to_groups.rb
new file mode 100644
index 00000000..9d0193a1
--- /dev/null
+++ b/db/migrate/20190722003541_add_member_count_to_groups.rb
@@ -0,0 +1,10 @@
+class AddMemberCountToGroups < ActiveRecord::Migration[5.2]
+ def up
+ add_column :groups, :member_count, :integer
+ change_column_default :groups, :member_count, 0
+ end
+
+ def down
+ remove_column :groups, :member_count
+ end
+end
diff --git a/db/migrate/20190722003649_backfill_add_member_count_to_groups.rb b/db/migrate/20190722003649_backfill_add_member_count_to_groups.rb
new file mode 100644
index 00000000..65a21f6c
--- /dev/null
+++ b/db/migrate/20190722003649_backfill_add_member_count_to_groups.rb
@@ -0,0 +1,10 @@
+class BackfillAddMemberCountToGroups < ActiveRecord::Migration[5.2]
+ disable_ddl_transaction!
+
+ def change
+ Group.in_batches do |relation|
+ relation.update_all member_count: 0
+ sleep(0.1)
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index d9bf6f1e..e074dea8 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_07_21_234917) do
+ActiveRecord::Schema.define(version: 2019_07_22_003649) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -358,6 +358,7 @@ ActiveRecord::Schema.define(version: 2019_07_21_234917) do
t.boolean "is_archived", default: false, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.integer "member_count", default: 0
t.index ["account_id"], name: "index_groups_on_account_id"
end
diff --git a/lib/tasks/fix_group_member_counts.rake b/lib/tasks/fix_group_member_counts.rake
new file mode 100644
index 00000000..e24ab52b
--- /dev/null
+++ b/lib/tasks/fix_group_member_counts.rake
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+task fix_group_member_counts: 'gabsocial:fix-group-member-counts'
+
+namespace :gabsocial do
+ desc 'Re-compute group member counts'
+ task :fix_group_member_counts => :environment do
+ Group.select(:id).all.each do |group|
+ group.update_column(:member_count, group.accounts.count)
+ end
+ end
+end
From ff03e6a55fd168562881ccc668eba42a807dc3f6 Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Mon, 22 Jul 2019 04:50:09 +0300
Subject: [PATCH 37/41] home feed group toggle
---
.../settings/preferences_controller.rb | 1 +
app/lib/user_settings_decorator.rb | 5 ++++
app/models/user.rb | 2 +-
app/serializers/initial_state_serializer.rb | 23 ++++++++++---------
app/views/settings/preferences/show.html.haml | 1 +
config/locales/simple_form.en.yml | 1 +
6 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb
index 930ff70e..e9d6c5d8 100644
--- a/app/controllers/settings/preferences_controller.rb
+++ b/app/controllers/settings/preferences_controller.rb
@@ -50,6 +50,7 @@ class Settings::PreferencesController < Settings::BaseController
:setting_aggregate_reblogs,
:setting_show_application,
:setting_advanced_layout,
+ :setting_group_in_home_feed,
notification_emails: %i(follow follow_request reblog favourite mention digest report pending_account),
interactions: %i(must_be_follower must_be_following)
)
diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb
index bf2e5a96..de6bf670 100644
--- a/app/lib/user_settings_decorator.rb
+++ b/app/lib/user_settings_decorator.rb
@@ -34,6 +34,7 @@ class UserSettingsDecorator
user.settings['aggregate_reblogs'] = aggregate_reblogs_preference if change?('setting_aggregate_reblogs')
user.settings['show_application'] = show_application_preference if change?('setting_show_application')
user.settings['advanced_layout'] = advanced_layout_preference if change?('setting_advanced_layout')
+ user.settings['group_in_home_feed'] = group_in_home_feed_preference if change?('setting_group_in_home_feed')
end
def merged_notification_emails
@@ -112,6 +113,10 @@ class UserSettingsDecorator
boolean_cast_setting 'setting_advanced_layout'
end
+ def group_in_home_feed_preference
+ boolean_cast_setting 'setting_group_in_home_feed'
+ end
+
def boolean_cast_setting(key)
ActiveModel::Type::Boolean.new.cast(settings[key])
end
diff --git a/app/models/user.rb b/app/models/user.rb
index ed2ce0ba..d35372f5 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -105,7 +105,7 @@ class User < ApplicationRecord
delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal,
:reduce_motion, :system_font_ui, :noindex, :theme, :display_media, :hide_network,
:expand_spoilers, :default_language, :aggregate_reblogs, :show_application,
- :advanced_layout, to: :settings, prefix: :setting, allow_nil: false
+ :advanced_layout, :group_in_home_feed, to: :settings, prefix: :setting, allow_nil: false
attr_reader :invite_code
attr_writer :external
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb
index 7ef112df..5226da10 100644
--- a/app/serializers/initial_state_serializer.rb
+++ b/app/serializers/initial_state_serializer.rb
@@ -23,17 +23,18 @@ class InitialStateSerializer < ActiveModel::Serializer
}
if object.current_account
- store[:username] = object.current_account.username
- store[:me] = object.current_account.id.to_s
- store[:unfollow_modal] = object.current_account.user.setting_unfollow_modal
- store[:boost_modal] = object.current_account.user.setting_boost_modal
- store[:delete_modal] = object.current_account.user.setting_delete_modal
- store[:auto_play_gif] = object.current_account.user.setting_auto_play_gif
- store[:display_media] = object.current_account.user.setting_display_media
- store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers
- store[:reduce_motion] = object.current_account.user.setting_reduce_motion
- store[:advanced_layout] = object.current_account.user.setting_advanced_layout
- store[:is_staff] = object.current_account.user.staff?
+ store[:username] = object.current_account.username
+ store[:me] = object.current_account.id.to_s
+ store[:unfollow_modal] = object.current_account.user.setting_unfollow_modal
+ store[:boost_modal] = object.current_account.user.setting_boost_modal
+ store[:delete_modal] = object.current_account.user.setting_delete_modal
+ store[:auto_play_gif] = object.current_account.user.setting_auto_play_gif
+ store[:display_media] = object.current_account.user.setting_display_media
+ store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers
+ store[:reduce_motion] = object.current_account.user.setting_reduce_motion
+ store[:advanced_layout] = object.current_account.user.setting_advanced_layout
+ store[:group_in_home_feed] = object.current_account.user.setting_group_in_home_feed
+ store[:is_staff] = object.current_account.user.staff?
end
store
diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml
index 35b660a6..c5522ebd 100644
--- a/app/views/settings/preferences/show.html.haml
+++ b/app/views/settings/preferences/show.html.haml
@@ -62,6 +62,7 @@
= f.input :setting_expand_spoilers, as: :boolean, wrapper: :with_label
= f.input :setting_reduce_motion, as: :boolean, wrapper: :with_label
= f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label
+ = f.input :setting_group_in_home_feed, as: :boolean, wrapper: :with_label
.actions
= f.button :button, t('generic.save_changes'), type: :submit
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index bb52e53c..6931a03d 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -105,6 +105,7 @@ en:
setting_hide_network: Hide your network
setting_noindex: Opt-out of search engine indexing
setting_reduce_motion: Reduce motion in animations
+ setting_group_in_home_feed: Show posts from your groups”
setting_show_application: Disclose application used to send gabs
setting_system_font_ui: Use system's default font
setting_theme: Site theme
From 3a59b29fddf0a1435dace262594cf50ff9da1cb0 Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Mon, 22 Jul 2019 04:52:12 +0300
Subject: [PATCH 38/41] typo
---
config/locales/simple_form.en.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 6931a03d..e284bb9d 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -105,7 +105,7 @@ en:
setting_hide_network: Hide your network
setting_noindex: Opt-out of search engine indexing
setting_reduce_motion: Reduce motion in animations
- setting_group_in_home_feed: Show posts from your groups”
+ setting_group_in_home_feed: Show posts from your groups
setting_show_application: Disclose application used to send gabs
setting_system_font_ui: Use system's default font
setting_theme: Site theme
From aefe5a44f39588b07c00752c78fb5badbd9cbcf1 Mon Sep 17 00:00:00 2001
From: 2458773093 <2458773093@protonmail.com>
Date: Mon, 22 Jul 2019 05:12:59 +0300
Subject: [PATCH 39/41] show group sidebar panel across the site
---
app/javascript/gabsocial/features/ui/index.js | 5 +++++
app/javascript/gabsocial/pages/group_page.js | 3 +--
app/javascript/gabsocial/pages/groups_page.js | 2 ++
app/javascript/gabsocial/pages/home_page.js | 2 ++
4 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/app/javascript/gabsocial/features/ui/index.js b/app/javascript/gabsocial/features/ui/index.js
index 1f299890..193bf90b 100644
--- a/app/javascript/gabsocial/features/ui/index.js
+++ b/app/javascript/gabsocial/features/ui/index.js
@@ -29,6 +29,7 @@ import GroupsPage from 'gabsocial/pages/groups_page';
import GroupPage from 'gabsocial/pages/group_page';
import SearchPage from 'gabsocial/pages/search_page';
import HomePage from 'gabsocial/pages/home_page';
+import GroupSidebarPanel from '../groups/sidebar_panel';
import {
Status,
@@ -67,6 +68,7 @@ import { previewState as previewVideoState } from './components/video_modal';
// Dummy import, to make sure that
ends up in the application bundle.
// Without this it ends up in ~8 very commonly used bundles.
import '../../components/status';
+import { fetchGroups } from '../../actions/groups';
const messages = defineMessages({
beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Gab Social.' },
@@ -120,12 +122,14 @@ const LAYOUT = {
],
RIGHT: [
//
,
+
],
},
STATUS: {
TOP: null,
LEFT: null,
RIGHT: [
+
,
,
//
,
,
@@ -370,6 +374,7 @@ class UI extends React.PureComponent {
if (me) {
this.props.dispatch(expandHomeTimeline());
this.props.dispatch(expandNotifications());
+ this.props.dispatch(fetchGroups('member'));
setTimeout(() => this.props.dispatch(fetchFilters()), 500);
}
diff --git a/app/javascript/gabsocial/pages/group_page.js b/app/javascript/gabsocial/pages/group_page.js
index a6d4e329..a2ff5e8a 100644
--- a/app/javascript/gabsocial/pages/group_page.js
+++ b/app/javascript/gabsocial/pages/group_page.js
@@ -8,7 +8,7 @@ import LinkFooter from '../features/ui/components/link_footer';
import PromoPanel from '../features/ui/components/promo_panel';
import HeaderContainer from '../features/groups/timeline/containers/header_container';
import GroupPanel from '../features/groups/timeline/components/panel';
-import { fetchGroup, fetchGroups } from '../actions/groups';
+import { fetchGroup } from '../actions/groups';
import GroupSidebarPanel from '../features/groups/sidebar_panel';
const mapStateToProps = (state, { params: { id } }) => ({
@@ -28,7 +28,6 @@ class GroupPage extends ImmutablePureComponent {
componentWillMount() {
const { params: { id }, dispatch } = this.props;
- dispatch(fetchGroups('member'));
dispatch(fetchGroup(id));
}
diff --git a/app/javascript/gabsocial/pages/groups_page.js b/app/javascript/gabsocial/pages/groups_page.js
index 141a530f..5c810a22 100644
--- a/app/javascript/gabsocial/pages/groups_page.js
+++ b/app/javascript/gabsocial/pages/groups_page.js
@@ -7,6 +7,7 @@ import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel';
import LinkFooter from '../features/ui/components/link_footer';
import PromoPanel from '../features/ui/components/promo_panel';
import UserPanel from '../features/ui/components/user_panel';
+import GroupSidebarPanel from '../features/groups/sidebar_panel';
const mapStateToProps = state => ({
account: state.getIn(['accounts', me]),
@@ -43,6 +44,7 @@ class GroupsPage extends ImmutablePureComponent {
diff --git a/app/javascript/gabsocial/pages/home_page.js b/app/javascript/gabsocial/pages/home_page.js
index 931fae4c..6667f10f 100644
--- a/app/javascript/gabsocial/pages/home_page.js
+++ b/app/javascript/gabsocial/pages/home_page.js
@@ -9,6 +9,7 @@ import PromoPanel from '../features/ui/components/promo_panel';
import UserPanel from '../features/ui/components/user_panel';
import ComposeFormContainer from '../features/compose/containers/compose_form_container';
import Avatar from '../components/avatar';
+import GroupSidebarPanel from '../features/groups/sidebar_panel';
const mapStateToProps = state => ({
account: state.getIn(['accounts', me]),
@@ -48,6 +49,7 @@ class HomePage extends ImmutablePureComponent {