about summary refs log tree commit diff
path: root/app/models
diff options
context:
space:
mode:
authormultiple creatures <dev@multiple-creature.party>2019-05-05 23:04:23 -0500
committermultiple creatures <dev@multiple-creature.party>2019-05-21 03:16:22 -0500
commita47b1daaebea09ca07ca93079e530f26cfeef914 (patch)
tree04f08b28710732d1a9747c64537cd75162a651ca /app/models
parent992218f05f76106857f2cb5a72c0bb4510aa4563 (diff)
Implement scoped tags; use `local:` and `self:` scopes for community and personal tags, respectively.
Diffstat (limited to 'app/models')
-rw-r--r--app/models/status.rb29
-rw-r--r--app/models/tag.rb15
2 files changed, 38 insertions, 6 deletions
diff --git a/app/models/status.rb b/app/models/status.rb
index 0baa5c98b..6c16046a5 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -379,8 +379,8 @@ class Status < ApplicationRecord
       apply_timeline_filters(query, account, local_only)
     end
 
-    def as_tag_timeline(tag, account = nil, local_only = false)
-      query = browsable_timeline_scope(local_only).tagged_with(tag)
+    def as_tag_timeline(tag, account = nil, local_only = false, priv = false)
+      query = tag_timeline_scope(account, local_only, priv).tagged_with(tag)
       apply_timeline_filters(query, account, local_only)
     end
 
@@ -465,9 +465,28 @@ class Status < ApplicationRecord
 
     def browsable_timeline_scope(local_only = false)
       starting_scope = local_only ? Status.network : Status
-      starting_scope
-        .public_browsable
-        .without_reblogs
+      starting_scope = starting_scope.public_browsable
+      if Setting.show_reblogs_in_public_timelines
+        starting_scope
+      else
+        starting_scope.without_reblogs
+      end
+    end
+
+    def tag_timeline_scope(account = nil, local_only = false, priv = false)
+      if priv
+        return Status.none if account.nil?
+        starting_scope = account.statuses
+      else
+        starting_scope = local_only ? Status.network : Status
+        starting_scope = scope.public_browsable
+      end
+
+      if Setting.show_reblogs_in_public_timelines
+        starting_scope
+      else
+        starting_scope.without_reblogs
+      end
     end
 
     def apply_timeline_filters(query, account, local_only)
diff --git a/app/models/tag.rb b/app/models/tag.rb
index ecfe4f7e8..04b902885 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -7,6 +7,8 @@
 #  name       :string           default(""), not null
 #  created_at :datetime         not null
 #  updated_at :datetime         not null
+#  local      :boolean          default(FALSE), not null
+#  private    :boolean          default(FALSE), not null
 #
 
 class Tag < ApplicationRecord
@@ -17,7 +19,7 @@ class Tag < ApplicationRecord
   has_many :featured_tags, dependent: :destroy, inverse_of: :tag
   has_one :account_tag_stat, dependent: :destroy
 
-  HASHTAG_NAME_RE = '[[:word:]_\-]*[[:alpha:]_·\-][[:word:]_\-]*'
+  HASHTAG_NAME_RE = '[[:word:]:_\-]*[[:alpha:]:_·\-][[:word:]:_\-]*'
   HASHTAG_RE = /(?:^|[^\/\)\w])#(#{HASHTAG_NAME_RE})/i
 
   validates :name, presence: true, uniqueness: true, format: { with: /\A#{HASHTAG_NAME_RE}\z/i }
@@ -26,6 +28,11 @@ class Tag < ApplicationRecord
   scope :hidden, -> { where(account_tag_stats: { hidden: true }) }
   scope :most_used, ->(account) { joins(:statuses).where(statuses: { account: account }).group(:id).order(Arel.sql('count(*) desc')) }
 
+  scope :only_local, -> { where(local: true) }
+  scope :only_global, -> { where(local: false) }
+  scope :only_private, -> { where(private: true) }
+  scope :only_public, -> { where(private: false) }
+
   delegate :accounts_count,
            :accounts_count=,
            :increment_count!,
@@ -33,6 +40,7 @@ class Tag < ApplicationRecord
            :hidden?,
            to: :account_tag_stat
 
+  before_create :set_scope
   after_save :save_account_tag_stat
 
   def account_tag_stat
@@ -88,4 +96,9 @@ class Tag < ApplicationRecord
     return unless account_tag_stat&.changed?
     account_tag_stat.save
   end
+
+  def set_scope
+    self.private = true if name.starts_with?('self', '_self')
+    self.local = true if self.private || name.starts_with?('local', '_local')
+  end
 end