@@ -14,6 +14,7 @@ gem 'puma' | |||||
gem 'haml-rails' | gem 'haml-rails' | ||||
gem 'pg' | gem 'pg' | ||||
gem 'dotenv-rails' | gem 'dotenv-rails' | ||||
gem 'font-awesome-sass' | |||||
gem 'grape' | gem 'grape' | ||||
gem 'grape-route-helpers' | gem 'grape-route-helpers' | ||||
@@ -76,6 +76,8 @@ GEM | |||||
erubis (2.7.0) | erubis (2.7.0) | ||||
execjs (2.6.0) | execjs (2.6.0) | ||||
fabrication (2.14.1) | fabrication (2.14.1) | ||||
font-awesome-sass (4.5.0) | |||||
sass (>= 3.2) | |||||
fuubar (2.0.0) | fuubar (2.0.0) | ||||
rspec (~> 3.0) | rspec (~> 3.0) | ||||
ruby-progressbar (~> 1.4) | ruby-progressbar (~> 1.4) | ||||
@@ -304,6 +306,7 @@ DEPENDENCIES | |||||
coffee-rails (~> 4.1.0) | coffee-rails (~> 4.1.0) | ||||
dotenv-rails | dotenv-rails | ||||
fabrication | fabrication | ||||
font-awesome-sass | |||||
fuubar | fuubar | ||||
goldfinger | goldfinger | ||||
grape | grape | ||||
@@ -46,5 +46,9 @@ module Mastodon | |||||
expose :updated_at | expose :updated_at | ||||
end | end | ||||
end | end | ||||
class StreamEntry < Grape::Entity | |||||
expose :activity, using: Mastodon::Entities::Status | |||||
end | |||||
end | end | ||||
end | end |
@@ -3,6 +3,12 @@ module Mastodon | |||||
version 'v1', using: :path | version 'v1', using: :path | ||||
format :json | format :json | ||||
helpers do | |||||
def current_user | |||||
User.first | |||||
end | |||||
end | |||||
resource :timelines do | resource :timelines do | ||||
desc 'Return a public timeline' | desc 'Return a public timeline' | ||||
@@ -13,7 +19,7 @@ module Mastodon | |||||
desc 'Return the home timeline of a logged in user' | desc 'Return the home timeline of a logged in user' | ||||
get :home do | get :home do | ||||
# todo | |||||
present current_user.timeline, with: Mastodon::Entities::StreamEntry | |||||
end | end | ||||
desc 'Return the notifications timeline of a logged in user' | desc 'Return the notifications timeline of a logged in user' | ||||
@@ -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; | |||||
} | |||||
} | |||||
} |
@@ -1,7 +1,17 @@ | |||||
class ProfileController < ApplicationController | class ProfileController < ApplicationController | ||||
before_action :set_account | |||||
def show | def show | ||||
end | end | ||||
def entry | 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 | ||||
end | end |
@@ -2,4 +2,8 @@ class User < ActiveRecord::Base | |||||
belongs_to :account, inverse_of: :user | belongs_to :account, inverse_of: :user | ||||
validates :account, presence: true | validates :account, presence: true | ||||
def timeline | |||||
StreamEntry.where(account_id: self.account.following, activity_type: 'Status').order('id desc') | |||||
end | |||||
end | end |
@@ -7,4 +7,5 @@ | |||||
= javascript_include_tag 'application' | = javascript_include_tag 'application' | ||||
= csrf_meta_tags | = csrf_meta_tags | ||||
%body | %body | ||||
= yield | |||||
.container | |||||
= yield |
@@ -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 } |
@@ -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 |
@@ -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 |
@@ -0,0 +1,2 @@ | |||||
%div.activity-stream | |||||
= render partial: @type, locals: { @type.to_sym => @entry.activity } |
@@ -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 } |