diff --git a/Gemfile b/Gemfile index 7beff4ea6..2a05e06d5 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,7 @@ gem 'puma' gem 'haml-rails' gem 'pg' gem 'dotenv-rails' +gem 'font-awesome-sass' gem 'grape' gem 'grape-route-helpers' diff --git a/Gemfile.lock b/Gemfile.lock index 14c0f29c0..70b73e87c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -76,6 +76,8 @@ GEM erubis (2.7.0) execjs (2.6.0) fabrication (2.14.1) + font-awesome-sass (4.5.0) + sass (>= 3.2) fuubar (2.0.0) rspec (~> 3.0) ruby-progressbar (~> 1.4) @@ -304,6 +306,7 @@ DEPENDENCIES coffee-rails (~> 4.1.0) dotenv-rails fabrication + font-awesome-sass fuubar goldfinger grape diff --git a/app/api/mastodon/entities.rb b/app/api/mastodon/entities.rb index 975e72538..1c0e768f8 100644 --- a/app/api/mastodon/entities.rb +++ b/app/api/mastodon/entities.rb @@ -46,5 +46,9 @@ module Mastodon expose :updated_at end end + + class StreamEntry < Grape::Entity + expose :activity, using: Mastodon::Entities::Status + end end end diff --git a/app/api/mastodon/rest.rb b/app/api/mastodon/rest.rb index 25a53202b..eb5232165 100644 --- a/app/api/mastodon/rest.rb +++ b/app/api/mastodon/rest.rb @@ -3,6 +3,12 @@ module Mastodon version 'v1', using: :path format :json + helpers do + def current_user + User.first + end + end + resource :timelines do desc 'Return a public timeline' @@ -13,7 +19,7 @@ module Mastodon desc 'Return the home timeline of a logged in user' get :home do - # todo + present current_user.timeline, with: Mastodon::Entities::StreamEntry end desc 'Return the notifications timeline of a logged in user' diff --git a/app/assets/stylesheets/profile.scss b/app/assets/stylesheets/profile.scss index 22ee50876..2e5e0a6e3 100644 --- a/app/assets/stylesheets/profile.scss +++ b/app/assets/stylesheets/profile.scss @@ -1,3 +1,114 @@ -// Place all the styles related to the Profile controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ +@import url(https://fonts.googleapis.com/css?family=Noto+Sans:400,700,400italic); + +@import "font-awesome-sprockets"; +@import "font-awesome"; + +body { + font-family: 'Noto Sans', sans-serif; + background: #E0E3DA; + font-size: 13px; + line-height: 18px; +} + +.container { + width: 800px; + margin: 0 auto; +} + +.card { + padding-top: 20px; + + .name { + font-size: 24px; + line-height: 18px * 1.5; + + small { + display: block; + font-size: 14px; + color: #566270; + } + } + + .bio { + + } + + .counter { + display: block; + float: left; + width: 100px; + text-align: center; + border: 1px solid #A593E0; + color: #A593E0; + border-radius: 5px; + padding: 3px 0; + margin-right: 3px; + + .num { + display: block; + font-size: 24px; + } + } +} + +.activity-stream { + clear: both; + + .entry { + padding: 10px; + border-bottom: 1px solid #E0E3DA; + background: #FFFFF3; + + &:first-child { + border-radius: 5px 5px 0 0; + } + + &:last-child { + border-bottom: 0; + border-radius: 0 0 5px 5px; + } + } + + .header { + margin-bottom: 10px; + } + + .name { + text-decoration: none; + color: #566270; + + strong { + color: #000; + } + + &:hover { + strong { + text-decoration: underline; + } + } + } + + .content { + font-size: 16px; + } + + .time { + text-decoration: none; + color: #566270; + + &:hover { + text-decoration: underline; + } + } + + .counters { + margin-top: 15px; + color: #566270; + cursor: default; + + .counter { + display: inline-block; + margin-right: 10px; + } + } +} diff --git a/app/controllers/profile_controller.rb b/app/controllers/profile_controller.rb index 42698f7c7..30bd1a6b6 100644 --- a/app/controllers/profile_controller.rb +++ b/app/controllers/profile_controller.rb @@ -1,7 +1,17 @@ class ProfileController < ApplicationController + before_action :set_account + def show end def entry + @entry = @account.stream_entries.find(params[:id]) + @type = @entry.activity_type.downcase + end + + private + + def set_account + @account = Account.find_by!(username: params[:name], domain: nil) end end diff --git a/app/models/user.rb b/app/models/user.rb index d23f5d608..c54a5fab3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,4 +2,8 @@ class User < ActiveRecord::Base belongs_to :account, inverse_of: :user validates :account, presence: true + + def timeline + StreamEntry.where(account_id: self.account.following, activity_type: 'Status').order('id desc') + end end diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 0cb4e96e8..c46fb0b33 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -7,4 +7,5 @@ = javascript_include_tag 'application' = csrf_meta_tags %body - = yield + .container + = yield diff --git a/app/views/profile/_status.html.haml b/app/views/profile/_status.html.haml new file mode 100644 index 000000000..39e70b69c --- /dev/null +++ b/app/views/profile/_status.html.haml @@ -0,0 +1,7 @@ +%div.entry + .header + = render partial: 'status_header', locals: { status: status.reblog? ? status.reblog : status } + .content + = status.content + .counters + = render partial: 'status_footer', locals: { status: status.reblog? ? status.reblog : status } diff --git a/app/views/profile/_status_footer.html.haml b/app/views/profile/_status_footer.html.haml new file mode 100644 index 000000000..0c47ade90 --- /dev/null +++ b/app/views/profile/_status_footer.html.haml @@ -0,0 +1,7 @@ +.counter.counter-retweets + %i.fa.fa-retweet + %span.num= status.reblogs.count + +.counter.counter-favourites + %i.fa.fa-star + %span.num= status.favourites.count diff --git a/app/views/profile/_status_header.html.haml b/app/views/profile/_status_header.html.haml new file mode 100644 index 000000000..6f0e8748e --- /dev/null +++ b/app/views/profile/_status_header.html.haml @@ -0,0 +1,8 @@ += link_to (status.account.local? ? profile_url(name: status.account.username) : status.account.url), class: 'name' do + %strong= status.account.display_name.blank? ? status.account.username : status.account.display_name + = "@#{status.account.acct}" + += link_to status.local? ? status_url(name: status.account.username, id: status.stream_entry.id) : status.url, class: 'time' do + %span{ title: status.created_at } + = time_ago_in_words(status.created_at) + ago diff --git a/app/views/profile/entry.html.haml b/app/views/profile/entry.html.haml new file mode 100644 index 000000000..8d0b23607 --- /dev/null +++ b/app/views/profile/entry.html.haml @@ -0,0 +1,2 @@ +%div.activity-stream + = render partial: @type, locals: { @type.to_sym => @entry.activity } diff --git a/app/views/profile/show.html.haml b/app/views/profile/show.html.haml index dcb5764ec..c84cb7e81 100644 --- a/app/views/profile/show.html.haml +++ b/app/views/profile/show.html.haml @@ -1,2 +1,8 @@ -%h1 Profile#show -%p Find me in app/views/profile/show.html.haml +%div.card + %h1.name + = @account.display_name.blank? ? @account.username : @account.display_name + %small= "@#{@account.username}" + +%div.activity-stream + - @account.statuses.order('id desc').each do |status| + = render partial: 'status', locals: { status: status }