diff --git a/Gemfile b/Gemfile index b4ce0aea8..48bdbaee3 100644 --- a/Gemfile +++ b/Gemfile @@ -36,6 +36,7 @@ gem 'onebox' gem 'simple_form' gem 'will_paginate', '~> 3.0.6' gem 'rack-attack' +gem 'turbolinks', '~> 5.0.0.beta' group :development, :test do gem 'rspec-rails' diff --git a/Gemfile.lock b/Gemfile.lock index d535d1617..d17b63a1b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -293,6 +293,9 @@ GEM thor (0.19.1) thread_safe (0.3.5) tilt (2.0.2) + turbolinks (5.0.0.beta2) + turbolinks-source + turbolinks-source (5.0.0.beta3) tzinfo (1.2.2) thread_safe (~> 0.1) uglifier (2.7.2) @@ -362,6 +365,7 @@ DEPENDENCIES simple_form simplecov therubyracer + turbolinks (~> 5.0.0.beta) uglifier (>= 1.3.0) web-console (~> 2.0) webmock diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 646c5aba4..e07c5a830 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -12,4 +12,5 @@ // //= require jquery //= require jquery_ujs +//= require turbolinks //= require_tree . diff --git a/app/assets/javascripts/statuses.coffee b/app/assets/javascripts/statuses.coffee new file mode 100644 index 000000000..24f83d18b --- /dev/null +++ b/app/assets/javascripts/statuses.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/dashboard.scss b/app/assets/stylesheets/dashboard.scss index afb718c90..d8f26f6c5 100644 --- a/app/assets/stylesheets/dashboard.scss +++ b/app/assets/stylesheets/dashboard.scss @@ -200,6 +200,15 @@ box-shadow: 0 0 15px rgba(0, 0, 0, 0.2); } } + + hr { + clear: both; + border: 0; + padding: 0; + width: 100%; + height: 0; + margin: 30px 0; + } } .dashboard__top-bar { diff --git a/app/assets/stylesheets/statuses.scss b/app/assets/stylesheets/statuses.scss new file mode 100644 index 000000000..bb9365adc --- /dev/null +++ b/app/assets/stylesheets/statuses.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the statuses controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb new file mode 100644 index 000000000..a5cb3eae1 --- /dev/null +++ b/app/controllers/statuses_controller.rb @@ -0,0 +1,18 @@ +class StatusesController < ApplicationController + layout 'dashboard' + + before_action :authenticate_user! + + def create + status = PostStatusService.new.(current_user.account, status_params[:text]) + redirect_to root_path + rescue ActiveRecord::RecordInvalid + redirect_to root_path + end + + private + + def status_params + params.require(:status).permit(:text) + end +end diff --git a/app/helpers/statuses_helper.rb b/app/helpers/statuses_helper.rb new file mode 100644 index 000000000..62fedd9b3 --- /dev/null +++ b/app/helpers/statuses_helper.rb @@ -0,0 +1,2 @@ +module StatusesHelper +end diff --git a/app/models/status.rb b/app/models/status.rb index 2fdd8d123..58d25546c 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -13,6 +13,7 @@ class Status < ActiveRecord::Base validates :account, presence: true validates :uri, uniqueness: true, unless: 'local?' + validates :text, presence: true, if: Proc.new { |s| s.local? && !s.reblog? } scope :with_counters, -> { select('statuses.*, (select count(r.id) from statuses as r where r.reblog_of_id = statuses.id) as reblogs_count, (select count(f.id) from favourites as f where f.status_id = statuses.id) as favourites_count') } scope :with_includes, -> { includes(:account, reblog: :account, thread: :account) } diff --git a/app/services/follow_remote_account_service.rb b/app/services/follow_remote_account_service.rb index 2f842e329..01e07e2e9 100644 --- a/app/services/follow_remote_account_service.rb +++ b/app/services/follow_remote_account_service.rb @@ -7,7 +7,10 @@ class FollowRemoteAccountService < BaseService # @return [Account] def call(uri, subscribe = true) username, domain = uri.split('@') - account = Account.where(username: username, domain: domain).first + + return Account.find_local(username) if domain == Rails.configuration.x.local_domain + + account = Account.find_by(username: username, domain: domain) if account.nil? account = Account.new(username: username, domain: domain) diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index a3213a685..70f91d4a3 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -1,3 +1,11 @@ += simple_form_for Status.new, url: statuses_path, method: :post do |f| + = f.input :text, required: true, autofocus: true, label: false, placeholder: 'What are you up to?' + + .form-actions + = f.button :submit, 'Post update' + +%hr/ + %h3 OAuth2 %p All API methods require a valid access token. @@ -83,6 +91,15 @@ %samp /api/accounts/:id/unfollow .description Unfollows target account from the user's account. Returns the target account. + %li + .address + %samp.method GET + %samp /api/accounts/lookup + .options + Options: + %samp usernames + .description + Returns accounts for a comma-separated list of usernames %h3 Follows %ul.api-descriptions diff --git a/config/routes.rb b/config/routes.rb index f40746f30..f595438b7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -21,7 +21,8 @@ Rails.application.routes.draw do end end - resource :settings, only: [:show, :update] + resource :settings, only: [:show, :update] + resources :statuses, only: [:create] namespace :api do # PubSubHubbub diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb new file mode 100644 index 000000000..05566a30e --- /dev/null +++ b/spec/controllers/statuses_controller_spec.rb @@ -0,0 +1,24 @@ +require 'rails_helper' + +RSpec.describe StatusesController, type: :controller do + let(:user) { Fabricate(:user) } + + before do + sign_in :user, user + end + + describe 'POST #create' do + before do + stub_request(:post, "https://pubsubhubbub.superfeedr.com/").to_return(:status => 200, :body => "", :headers => {}) + post :create, status: { text: 'Hello world' } + end + + it 'redirects back to homepage' do + expect(response).to redirect_to(root_path) + end + + it 'creates a new status' do + expect(user.account.statuses.count).to eq 1 + end + end +end diff --git a/spec/helpers/statuses_helper_spec.rb b/spec/helpers/statuses_helper_spec.rb new file mode 100644 index 000000000..db312abdd --- /dev/null +++ b/spec/helpers/statuses_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the StatusesHelper. For example: +# +# describe StatusesHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe StatusesHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end