From ad10ea99e6cc3e21322ebe2de82833e78e7cccef Mon Sep 17 00:00:00 2001 From: aidewoode Date: Wed, 22 Jul 2020 19:36:51 +0800 Subject: [PATCH 01/33] add support for various artists album --- app/controllers/albums_controller.rb | 1 - app/controllers/application_controller.rb | 2 +- app/controllers/artists/albums_controller.rb | 20 +++++++++ .../artists/appears_on_albums_controller.rb | 8 ++++ app/controllers/artists_controller.rb | 5 ++- app/lib/black_candy_error.rb | 1 + app/models/artist.rb | 15 ++++++- app/models/media.rb | 15 ++++++- app/models/media_file.rb | 1 + app/views/artists/_albums.html.erb | 17 ++++++++ app/views/artists/_info.html.erb | 18 ++++++++ app/views/artists/albums/index.html.erb | 2 + .../artists/appears_on_albums/index.html.erb | 2 + app/views/artists/show.html.erb | 39 +++++------------- app/views/artists/show.js.erb | 1 - config/locales/en.yml | 3 ++ config/routes.rb | 6 ++- ...0200721071945_add_is_various_to_artists.rb | 5 +++ db/schema.rb | 3 +- .../artists/albums_controller_test.rb | 19 +++++++++ .../appears_on_albums_controller_test.rb | 18 ++++++++ test/fixtures/albums.yml | 3 ++ test/fixtures/artists.yml | 3 ++ test/fixtures/files/artist1_album1.flac | Bin 10001 -> 10001 bytes test/fixtures/files/artist1_album1.m4a | Bin 9312 -> 9312 bytes test/fixtures/files/artist1_album2.mp3 | Bin 38136 -> 38117 bytes test/fixtures/files/artist2_album3.oga | Bin 9862 -> 9885 bytes test/fixtures/files/artist2_album3.ogg | Bin 7075 -> 7074 bytes test/fixtures/files/artist2_album3.opus | Bin 7703 -> 7702 bytes test/fixtures/files/artist2_album3.wav | Bin 1416738 -> 1416738 bytes test/fixtures/files/artist2_album3.wma | Bin 279156 -> 279208 bytes test/fixtures/files/various_artists.mp3 | Bin 0 -> 38117 bytes test/fixtures/songs.yml | 8 ++++ test/models/artist_test.rb | 12 ++++++ test/models/concerns/searchable_test.rb | 3 +- test/models/media_file_test.rb | 11 ++++- test/models/media_test.rb | 13 +++--- 37 files changed, 209 insertions(+), 45 deletions(-) create mode 100644 app/controllers/artists/albums_controller.rb create mode 100644 app/controllers/artists/appears_on_albums_controller.rb create mode 100644 app/views/artists/_albums.html.erb create mode 100644 app/views/artists/_info.html.erb create mode 100644 app/views/artists/albums/index.html.erb create mode 100644 app/views/artists/appears_on_albums/index.html.erb delete mode 100644 app/views/artists/show.js.erb create mode 100644 db/migrate/20200721071945_add_is_various_to_artists.rb create mode 100644 test/controllers/artists/albums_controller_test.rb create mode 100644 test/controllers/artists/appears_on_albums_controller_test.rb create mode 100644 test/fixtures/files/various_artists.mp3 diff --git a/app/controllers/albums_controller.rb b/app/controllers/albums_controller.rb index b2f8332a..1f967c8a 100644 --- a/app/controllers/albums_controller.rb +++ b/app/controllers/albums_controller.rb @@ -13,7 +13,6 @@ def index def show @songs = @album.songs - AttachAlbumImageFromDiscogsJob.perform_later(@album.id) if @album.need_attach_from_discogs? end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c6494357..12ff5531 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,7 +5,7 @@ class ApplicationController < ActionController::Base before_action :find_current_user - rescue_from ActiveRecord::RecordNotFound do |exception| + rescue_from ActiveRecord::RecordNotFound, BlackCandyError::NotFound do |exception| respond_to do |format| format.js { head :not_found } format.json { head :not_found } diff --git a/app/controllers/artists/albums_controller.rb b/app/controllers/artists/albums_controller.rb new file mode 100644 index 00000000..4053f581 --- /dev/null +++ b/app/controllers/artists/albums_controller.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class Artists::AlbumsController < ApplicationController + before_action :require_login + before_action :find_artist + before_action :find_albums + + def index + raise BlackCandyError::NotFound if @albums.empty? + end + + private + def find_albums + @albums = @artist.albums + end + + def find_artist + @artist = Artist.find(params[:artist_id]) + end +end diff --git a/app/controllers/artists/appears_on_albums_controller.rb b/app/controllers/artists/appears_on_albums_controller.rb new file mode 100644 index 00000000..003eaff0 --- /dev/null +++ b/app/controllers/artists/appears_on_albums_controller.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class Artists::AppearsOnAlbumsController < Artists::AlbumsController + private + def find_albums + @albums = @artist.appears_on_albums + end +end diff --git a/app/controllers/artists_controller.rb b/app/controllers/artists_controller.rb index 103274f2..15d5db76 100644 --- a/app/controllers/artists_controller.rb +++ b/app/controllers/artists_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class ArtistsController < ApplicationController + ALBUMS_COUNT = 10 + include Pagy::Backend before_action :require_login @@ -12,7 +14,8 @@ def index def show @artist = Artist.find(params[:id]) - @pagy, @albums = pagy_countless(@artist.albums) + @albums_pagy, @albums = pagy_countless(@artist.albums, items: ALBUMS_COUNT) + @appears_on_albums_pagy, @appears_on_albums = pagy_countless(@artist.appears_on_albums, items: ALBUMS_COUNT) AttachArtistImageFromDiscogsJob.perform_later(@artist.id) if @artist.need_attach_from_discogs? end diff --git a/app/lib/black_candy_error.rb b/app/lib/black_candy_error.rb index 6b2a6bd6..71a22200 100644 --- a/app/lib/black_candy_error.rb +++ b/app/lib/black_candy_error.rb @@ -2,5 +2,6 @@ module BlackCandyError class Forbidden < StandardError; end + class NotFound < StandardError; end class InvalidFilePath < StandardError; end end diff --git a/app/models/artist.rb b/app/models/artist.rb index 3b9c61ae..9bb19a98 100644 --- a/app/models/artist.rb +++ b/app/models/artist.rb @@ -4,14 +4,17 @@ class Artist < ApplicationRecord include Searchable has_many :albums, dependent: :destroy - has_many :songs, dependent: :destroy + has_many :songs mount_uploader :image, ImageUploader search_by :name def title - is_unknown? ? I18n.t('text.unknown_artist') : name + return I18n.t('text.various_artists') if is_various? + return I18n.t('text.unknown_artist') if is_unknown? + + name end def has_image? @@ -22,6 +25,14 @@ def is_unknown? name.blank? end + def all_albums + Album.joins(:songs).where('albums.artist_id = ? OR songs.artist_id = ?', id, id).distinct + end + + def appears_on_albums + Album.joins(:songs).where('albums.artist_id != ? AND songs.artist_id = ?', id, id).distinct + end + def need_attach_from_discogs? Setting.discogs_token.present? && !has_image? && !is_unknown? end diff --git a/app/models/media.rb b/app/models/media.rb index 49c5ad79..d8b112c0 100644 --- a/app/models/media.rb +++ b/app/models/media.rb @@ -9,7 +9,13 @@ def initialize(file_path) def attach artist = Artist.find_or_create_by(name: file_info[:artist_name]) - album = Album.find_or_create_by(artist: artist, name: file_info[:album_name]) + + if various_artists? + various_artist = Artist.find_or_create_by(is_various: true) + album = Album.find_or_create_by(artist: various_artist, name: file_info[:album_name]) + else + album = Album.find_or_create_by(artist: artist, name: file_info[:album_name]) + end # Attach image from file to the album. AttachAlbumImageFromFileJob.perform_later(album.id, file_info[:file_path]) unless album.has_image? @@ -25,6 +31,11 @@ def song_info file_info.slice(:name, :tracknum, :length, :file_path) end + def various_artists? + albumartist = file_info[:albumartist_name] + albumartist.present? && (albumartist.downcase == 'various artists' || albumartist != file_info[:artist_name]) + end + class << self def sync media_hashes = MediaFile.file_paths.map do |file_path| @@ -46,7 +57,7 @@ def clean_up(media_hashes) # Clean up no content albums and artist. Album.left_outer_joins(:songs).where('songs.id is null').destroy_all - Artist.left_outer_joins(:songs).where('songs.id is null').destroy_all + Artist.left_outer_joins(:songs, :albums).where('songs.album_id is null').where('albums.id is null').destroy_all end end end diff --git a/app/models/media_file.rb b/app/models/media_file.rb index f6373103..a03aee0a 100644 --- a/app/models/media_file.rb +++ b/app/models/media_file.rb @@ -40,6 +40,7 @@ def get_tag_info(file_path) name: tag.title.presence || File.basename(file_path), album_name: tag.album.presence, artist_name: tag.artist.presence, + albumartist_name: tag.albumartist.presence, tracknum: tag.track, length: tag.duration } diff --git a/app/views/artists/_albums.html.erb b/app/views/artists/_albums.html.erb new file mode 100644 index 00000000..ef9a64c3 --- /dev/null +++ b/app/views/artists/_albums.html.erb @@ -0,0 +1,17 @@ +<% if albums.present? %> +
+
+
+
+ <%= title %> +
+
+ <% if local_assigns[:all_albums_link] && all_albums_link.present? %> + <%= link_to t('text.see_all'), all_albums_link %> + <% end %> +
+
+
+ <%= render partial: 'albums/album', collection: albums, cached: true %> +
+<% end %> diff --git a/app/views/artists/_info.html.erb b/app/views/artists/_info.html.erb new file mode 100644 index 00000000..d43f38a7 --- /dev/null +++ b/app/views/artists/_info.html.erb @@ -0,0 +1,18 @@ +<% cache artist do %> +
+
+
+ <%= image_tag image_url_for(artist), class: 'image' %> +
+
+
<%= artist.title %>
+
+ <%= artist.all_albums.size %> <%= t('label.albums') %> + , + <%= artist.songs.size %> <%= t('label.songs')%> +
+
+
+
+
+<% end %> diff --git a/app/views/artists/albums/index.html.erb b/app/views/artists/albums/index.html.erb new file mode 100644 index 00000000..9a22f7c8 --- /dev/null +++ b/app/views/artists/albums/index.html.erb @@ -0,0 +1,2 @@ +<%= render partial: 'artists/info', locals: { artist: @artist } %> +<%= render partial: 'artists/albums', locals: { title: t('label.albums'), albums: @albums } %> diff --git a/app/views/artists/appears_on_albums/index.html.erb b/app/views/artists/appears_on_albums/index.html.erb new file mode 100644 index 00000000..04722ab3 --- /dev/null +++ b/app/views/artists/appears_on_albums/index.html.erb @@ -0,0 +1,2 @@ +<%= render partial: 'artists/info', locals: { artist: @artist } %> +<%= render partial: 'artists/albums', locals: { title: t('label.appears_on'), albums: @albums } %> diff --git a/app/views/artists/show.html.erb b/app/views/artists/show.html.erb index e63069de..9e05b3b2 100644 --- a/app/views/artists/show.html.erb +++ b/app/views/artists/show.html.erb @@ -1,28 +1,11 @@ -<% cache @artist do %> -
-
-
- <%= image_tag image_url_for(@artist), class: 'image' %> -
-
-
<%= @artist.title %>
-
- <%= @albums.size %> <%= t('label.albums') %> - , - <%= @artist.songs.size %> <%= t('label.songs')%> -
-
-
-
-
-<% end %> -
-
- <%= render partial: 'albums/album', collection: @albums, cached: true %> -
-
- <% if @pagy.next %> - <%= loader_tag %> - <% end %> -
-
+<%= render partial: 'info', locals: { artist: @artist} %> + +<%= render partial: 'albums', locals: { + title: t('label.albums'), + albums: @albums, + all_albums_link: @albums_pagy.next.present? ? artist_albums_path(@artist) : '' } %> + +<%= render partial: 'albums', locals: { + title: t('label.appears_on'), + albums: @appears_on_albums, + all_albums_link: @appears_on_albums_pagy.next.present? ? artist_appears_on_albums_path(@artist) : '' } %> diff --git a/app/views/artists/show.js.erb b/app/views/artists/show.js.erb deleted file mode 100644 index 40b080ea..00000000 --- a/app/views/artists/show.js.erb +++ /dev/null @@ -1 +0,0 @@ -App.appedNextPageContentTo('#js-albums-content', '<%= j(render partial: 'albums/album', collection: @albums, cached: true) %>', '<%= pagy_next_url(@pagy) %>') diff --git a/config/locales/en.yml b/config/locales/en.yml index 3f90c95e..6d9f987d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -52,6 +52,7 @@ en: integration: 'Integration' close: 'Close' more: 'More' + appears_on: 'Appears On' error: login: 'Wrong email or password' media_path_blank: 'Media path is not exist' @@ -75,6 +76,7 @@ en: add_user: 'Add user' create_user: 'Create User' media_path: 'Media path' + various_artists: 'Various Artists' unknown_artist: 'Unknown Artist' unknown_album: 'Unknown Album' go_back: 'Go back' @@ -89,3 +91,4 @@ en: expand_player: 'Expand player' collapse_player: 'Collapse player' personal: 'Personal' + see_all: 'See All' diff --git a/config/routes.rb b/config/routes.rb index 469bbc7a..ddbf5adb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,7 +4,11 @@ resource :session, only: [:new, :create, :destroy] resource :setting, only: [:show, :update] - resources :artists, only: [:index, :show] + resources :artists, only: [:index, :show] do + resources :albums, only: [:index], module: 'artists' + resources :appears_on_albums, only: [:index], module: 'artists' + end + resources :stream, only: [:new] resources :transcoded_stream, only: [:new] resources :songs, only: [:index, :show] diff --git a/db/migrate/20200721071945_add_is_various_to_artists.rb b/db/migrate/20200721071945_add_is_various_to_artists.rb new file mode 100644 index 00000000..f879d63c --- /dev/null +++ b/db/migrate/20200721071945_add_is_various_to_artists.rb @@ -0,0 +1,5 @@ +class AddIsVariousToArtists < ActiveRecord::Migration[6.0] + def change + add_column(:artists, :is_various, :boolean, default: false) + end +end diff --git a/db/schema.rb b/db/schema.rb index b41be1ca..3c0fe5dc 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: 2020_04_25_023906) do +ActiveRecord::Schema.define(version: 2020_07_21_071945) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" @@ -31,6 +31,7 @@ t.string "image" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.boolean "is_various", default: false t.index ["name"], name: "index_artists_on_name", unique: true end diff --git a/test/controllers/artists/albums_controller_test.rb b/test/controllers/artists/albums_controller_test.rb new file mode 100644 index 00000000..db1ca0a0 --- /dev/null +++ b/test/controllers/artists/albums_controller_test.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'test_helper' + +class Artists::AlbumsControllerTest < ActionDispatch::IntegrationTest + test 'should get index' do + assert_login_access(url: artist_albums_path(artists :artist1)) do + assert_response :success + end + end + + test 'should redirect to not found page when artists have no albums' do + empty_artist = Artist.create + + assert_login_access(url: artist_albums_path(empty_artist)) do + assert_response :not_found + end + end +end diff --git a/test/controllers/artists/appears_on_albums_controller_test.rb b/test/controllers/artists/appears_on_albums_controller_test.rb new file mode 100644 index 00000000..26dd35c5 --- /dev/null +++ b/test/controllers/artists/appears_on_albums_controller_test.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'test_helper' + +class Artists::AppearsOnAlbumsControllerTest < ActionDispatch::IntegrationTest + test 'should get index' do + assert_login_access(url: artist_appears_on_albums_path(artists :artist1)) do + assert_response :success + end + end + + test 'should redirect to not found page when artists have no albums' do + assert artists(:artist2).appears_on_albums.empty? + assert_login_access(url: artist_appears_on_albums_path(artists :artist2)) do + assert_response :not_found + end + end +end diff --git a/test/fixtures/albums.yml b/test/fixtures/albums.yml index 7b220961..e005243f 100644 --- a/test/fixtures/albums.yml +++ b/test/fixtures/albums.yml @@ -7,3 +7,6 @@ album2: album3: name: 'album3' artist: 'artist2' +album4: + name: 'album4' + artist: 'various_artists' diff --git a/test/fixtures/artists.yml b/test/fixtures/artists.yml index 2a327f79..3f9354c0 100644 --- a/test/fixtures/artists.yml +++ b/test/fixtures/artists.yml @@ -3,3 +3,6 @@ artist1: artist2: name: 'artist2' + +various_artists: + is_various: true diff --git a/test/fixtures/files/artist1_album1.flac b/test/fixtures/files/artist1_album1.flac index b909d84cb91e24dc93d06213aa818cd65be1cb43..abfc5929a872f1ee8f78805d251a356b71edfdc7 100644 GIT binary patch delta 80 zcmbQ}H_>kczaXRhWC1}H5e^0h1|A@G^l=LHwN1=PD$O;VTq$@#S{Nqi7!=|e9AcYT cRFYX-V%W$aAhkJA=nwzo1R=T2zDh?}03sX}-~a#s delta 101 zcmbQ}H_>kczaXRKWC1}HS55{71|A@G^l=LHwN1=PD$O+%f$<%KLOg>*Y~3;|N=l1T ei$zhzjo=cKJp?Z>H!=upb`)Y1*zBuxgarTzxf@jg diff --git a/test/fixtures/files/artist1_album1.m4a b/test/fixtures/files/artist1_album1.m4a index c4b45e2b8aa6338fda69664fcc147ffd756ae31f..0116a948c2c4a0d97630fed7f84709efeec4fcac 100644 GIT binary patch delta 45 zcmaFh@xWt)AqV66$wnN9ndB2E+eyi67U6s=$ZDBZl$yF(P+FC7vVt_vW-}Qr4ghWL B4d(y= delta 60 zcmaFh@xWt)AqV4y$wnN9Wfc+~gF+Y>7$i~>OA>)JBM>vVWmc4w7Nr(%7UX;{$Y`;d NQQCxYvzd$*2LL6a5N-ef diff --git a/test/fixtures/files/artist1_album2.mp3 b/test/fixtures/files/artist1_album2.mp3 index b6f50282cfb1a18e94e836dd9e492b3c93ce4f94..07eb78bf11791d99d81ce11b2a7d78247e348d38 100644 GIT binary patch delta 53 zcmeydlIiJ6CN57GV-^M=(DI(hRljl083Cb?09PZR00$5!7L{Zcml$p?6nw|LIYV?p FJpiSA5F7vi delta 56 zcmaF5lIh1vCN57GV-^M=(2ASLRWImj1Y~kDFfhAiR+N+$r50~&KPRxcQ1A)!H)xO5ikG% diff --git a/test/fixtures/files/artist2_album3.oga b/test/fixtures/files/artist2_album3.oga index b97821250810cc81b3bd8cef27861c383ac7975a..2c2daee86d878b063a2bd0eb772d7782942b92a2 100644 GIT binary patch delta 68 zcmZqko$EUxl`AGdr<}2ig@K`MV!nztD+2=q4-h;0IEDJ!CgvoS<{Asb_>Ms#p1~ou QiA5!u#U(}?m)}IZ36t#vAwDR|NnecnuH$ diff --git a/test/fixtures/files/artist2_album3.ogg b/test/fixtures/files/artist2_album3.ogg index b722b1d8d9122b8749d04576eeb2cc12e3c5f5ce..7f3926f01469285e548ef2dd804ecc85d4ab8845 100644 GIT binary patch delta 58 zcmZ2%zQ}w+0KfZ}o0la2!@!4$@o^ikHgJjyGcYhX`Z$I9ItGP!28Y-t7L{Zcml$mh I5%6h;3p~NoH}05g$kxMZ^v$;_UD1>*^O`JMoIy#EGIpAVncT Wj?UhGp}tP8LAC~lo0S;9$^ZZ`9X=ZX delta 172 zcmbPcGu>u_YrRO+eLji**g=qgL1}SFVtO$z0|P@&W>P+ot6->StY^p$6yO75$Dk0; z;1JuyqLR$w5+gyNNQh^MkE<<6WqfgBZb42e4@jAhQ>d?PVop+Nt}#ekNRXqmw_m8Q ilPgP*t%2dh9ZnJ=FlA69-7+gmN{dp9H!CuJl>q?r6F|%W diff --git a/test/fixtures/files/artist2_album3.wav b/test/fixtures/files/artist2_album3.wav index e5fd98a8c51fd6b74b4a8074ed058783dc8317d6..483120d226e038601be944d49f25d35e17b2dbf3 100644 GIT binary patch delta 85 zcmZ3qCv4H4u!a`K7N!>F7M2#)7Pc1l7LFFq7OocV7M>Q~7QPn#7J(MQ7NHj57LhHY o&pWpN>JYsvAQTedYQ(_6zyZXGMJ1WVB}N+!nOLUZm@Dc90NG+2&j0`b delta 84 zcmZ3qCv4H4u!a`K7N!>F7M2#)7Pc1l7LFFq7OocV7M>Q~7QPn#7J(MQ7NHj57LhHY o&pQNNjTjghI2jn2-7+gmN{dp9w?FL=y)UrQkdbBjjk%&;0GQDms{jB1 diff --git a/test/fixtures/files/artist2_album3.wma b/test/fixtures/files/artist2_album3.wma index 88c821aec8389c22674d779757f31096c8f7aed1..ae81a47704c8f74c09ee3ab4f5c7db83c165d4a2 100644 GIT binary patch delta 110 zcmey;BDkVeP|!eaQ)yq?dBJ5j8CEeQoy++)QSiC#D+UN)VUS}8XYggvXK-Z5VMt;q rWyl4xiWo{5G8u}2BnSvFBqE6zF)%bUGPW~6XH)RB2CLm_sZpz3~ G><9p8*b$ci diff --git a/test/fixtures/files/various_artists.mp3 b/test/fixtures/files/various_artists.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..6c015a75d76d41c36977308f0d1c00464538bfd8 GIT binary patch literal 38117 zcmeI5eQ*@z9mk)&7w!_9l3)ZuZI>g+%b0shh{?%;$>kzRxaJ6lK(kllTr-REV0zy0oKzU)6&UYe&PP$pOUylxv*jD%=8Nfu(V%~$TT!$b$HVzPZ`EvQXkb>Wui90as@saaLh#ZkTvR#uKFr$}Z+S$P>@7(!;iKcaM!c6UOkB?RtpGK?@112ZCdn+$`=8m5FVrF8h53J7E)O#RVut|(PSB6ozO{@@fn&wXNSUph}UoXs9Ch@bE zea9DAwj@v#G)_qOu@HSan9uFUDo330CgDrEs)o+AoYk3J5Q1wyi z*NHAmKVqz{c-XD8ID=_vw*8T(HyX#4Y~6EP^?|OOJiqj4TKdRQw~rn({_Y7ACr!?u zQgCl!k;7H$E_+}`dBtqsoCoL5n_m+M^0jsK!s3`5Z)i+3Eqmw~PP$_|oN1{&nTw|54)tkJ}vB%l(brSQaUJlgI+BLqaj(0sgj;7x2PqfrzkK919QOOVeprcW=QL~HsFf# z0sL1XLpeddp=Cf!+AK1iT+8UV>~ziVFvr6+A1&B*a%YWjruheZbDom+?Q6=}(CW@6 zvj)B~56$ejoNw1!OllACg1kmC*xa@?Uoj_VlYxWj`ScVv*`jt+9%*XH?w)-UaM zm35fq=W9+Zs61I-Gx}6>MfshpqwVcYx-qQ_cV4{kS!LCeE6(5Bq>$E(rn^Y?Ecbx7 zg@^L@!<&@5{rS63sBhAPx3jA%;Z2He*;16V;nIaG-WSKLI9qWS{eT;o7q= z>Q@|#yr+<|^iR*W3|Ee)!)F!sBT6Q0sgEdZ>LW@w4snkezzp168BnhND0riY<_VEH z=rbIw9DE^scn{I)jp-S~M`Vv0edo7KITI$`W47fL6yE2&-{qcB;i;o$u%35jvB#Zfwpp#Zo%9x`usQk`4`EKJ_pv|pM<2a#(;k(p znL#qV3qB-6i15WbgN4Tcf19BR)%=x&=z0=0r=N1e4s+(H>zHn^PCv8vo*v*jr9-q% z?GUZAdWhE9GDPd_8=`eSSbKe4_X?|@+5q*2>-5PV=IskP+9yk&Z(`msZ>lO#2dD$o zLBD?V^Wf}r2HziifAIam_lIHud4N1X9v}~p2iN`1N7K{q5jlz+MUEmzDIkys$OGg7 z@&I{&zKUu9d4N2iT0nn*{s4J^JU||xKcE^w9v}~>7SJD{KR_NJ50D4w52yx^2gn1e z1@s5#50D4Q1LOhv1F8Y!0rG%q0sR5`1LOhn0C|A^fNB7FfIOgDK!1S#0C|8sKpvn! zpc+6PAP=Y(&>x^bKpr3ukO$}ws0NS+$OEbc^atn#| zm1eJk^aiRw|kxW=_Oo;X5z~oZ??P@ zd)>a`2i)`CHxOch-$aMsMpsKqau2&yoA|1WU6sVvPxqCyJIvL@< zF)kbp@w7wtSsQKkIdUO?Je=R> + md5_hash: 'fake_md5' + artist: 'artist1' + album: 'album4' diff --git a/test/models/artist_test.rb b/test/models/artist_test.rb index dced3c4e..c6e777c1 100644 --- a/test/models/artist_test.rb +++ b/test/models/artist_test.rb @@ -6,4 +6,16 @@ class ArtistTest < ActiveSupport::TestCase test 'should have default title when name is empty' do assert_equal 'Unknown Artist', Artist.create(name: nil).title end + + test 'should have default title when is various artist' do + assert_equal 'Various Artists', Artist.create(is_various: true).title + end + + test 'should get all albums' do + assert_equal Album.where(name: %w(album1 album2 album4)).ids.sort, artists(:artist1).all_albums.ids.sort + end + + test 'should get appears on albums' do + assert_equal Album.where(name: %w(album4)).ids.sort, artists(:artist1).appears_on_albums.ids.sort + end end diff --git a/test/models/concerns/searchable_test.rb b/test/models/concerns/searchable_test.rb index 5018fbeb..57440df9 100644 --- a/test/models/concerns/searchable_test.rb +++ b/test/models/concerns/searchable_test.rb @@ -41,7 +41,8 @@ class SearchableTest < ActiveSupport::TestCase album_serach_song_ids = Album.find_by_name('album1').songs.ids + Album.find_by_name('album2').songs.ids + - Album.find_by_name('album3').songs.ids + Album.find_by_name('album3').songs.ids + + Album.find_by_name('album4').songs.ids assert_equal album_serach_song_ids.sort, Song.search('album').ids.sort end diff --git a/test/models/media_file_test.rb b/test/models/media_file_test.rb index 3e2d7943..8d922cf7 100644 --- a/test/models/media_file_test.rb +++ b/test/models/media_file_test.rb @@ -12,7 +12,8 @@ class MediaFileTest < ActiveSupport::TestCase fixtures_file_path('artist2_album3.opus'), fixtures_file_path('artist2_album3.wma'), fixtures_file_path('artist2_album3.oga'), - fixtures_file_path('artist1_album1.m4a') + fixtures_file_path('artist1_album1.m4a'), + fixtures_file_path('various_artists.mp3') ] Setting.media_path = Rails.root.join('test', 'fixtures', 'files') @@ -62,6 +63,7 @@ class MediaFileTest < ActiveSupport::TestCase assert_equal 'mp3_sample', tag_info[:name] assert_equal 'album2', tag_info[:album_name] assert_equal 'artist1', tag_info[:artist_name] + assert_equal 'artist1', tag_info[:albumartist_name] assert_equal 1, tag_info[:tracknum] assert_equal 8, tag_info[:length] end @@ -72,6 +74,7 @@ class MediaFileTest < ActiveSupport::TestCase assert_equal 'flac_sample', tag_info[:name] assert_equal 'album1', tag_info[:album_name] assert_equal 'artist1', tag_info[:artist_name] + assert_equal 'artist1', tag_info[:albumartist_name] assert_equal 1, tag_info[:tracknum] assert_equal 8, tag_info[:length] end @@ -82,6 +85,7 @@ class MediaFileTest < ActiveSupport::TestCase assert_equal 'ogg_sample', tag_info[:name] assert_equal 'album3', tag_info[:album_name] assert_equal 'artist2', tag_info[:artist_name] + assert_equal 'artist2', tag_info[:albumartist_name] assert_equal 1, tag_info[:tracknum] assert_equal 8, tag_info[:length] end @@ -92,6 +96,7 @@ class MediaFileTest < ActiveSupport::TestCase assert_equal 'wav_sample', tag_info[:name] assert_equal 'album3', tag_info[:album_name] assert_equal 'artist2', tag_info[:artist_name] + assert_equal 'artist2', tag_info[:albumartist_name] assert_equal 1, tag_info[:tracknum] assert_equal 8, tag_info[:length] end @@ -102,6 +107,7 @@ class MediaFileTest < ActiveSupport::TestCase assert_equal 'opus_sample', tag_info[:name] assert_equal 'album3', tag_info[:album_name] assert_equal 'artist2', tag_info[:artist_name] + assert_equal 'artist2', tag_info[:albumartist_name] assert_equal 1, tag_info[:tracknum] assert_equal 8, tag_info[:length] end @@ -112,6 +118,7 @@ class MediaFileTest < ActiveSupport::TestCase assert_equal 'm4a_sample', tag_info[:name] assert_equal 'album1', tag_info[:album_name] assert_equal 'artist1', tag_info[:artist_name] + assert_equal 'artist1', tag_info[:albumartist_name] assert_equal 1, tag_info[:tracknum] assert_equal 8, tag_info[:length] end @@ -122,6 +129,7 @@ class MediaFileTest < ActiveSupport::TestCase assert_equal 'oga_sample', tag_info[:name] assert_equal 'album3', tag_info[:album_name] assert_equal 'artist2', tag_info[:artist_name] + assert_equal 'artist2', tag_info[:albumartist_name] assert_equal 1, tag_info[:tracknum] assert_equal 8, tag_info[:length] end @@ -132,6 +140,7 @@ class MediaFileTest < ActiveSupport::TestCase assert_equal 'wma_sample', tag_info[:name] assert_equal 'album3', tag_info[:album_name] assert_equal 'artist2', tag_info[:artist_name] + assert_equal 'artist2', tag_info[:albumartist_name] assert_equal 1, tag_info[:tracknum] assert_equal 8, tag_info[:length] end diff --git a/test/models/media_test.rb b/test/models/media_test.rb index 87b985d8..c4822ea3 100644 --- a/test/models/media_test.rb +++ b/test/models/media_test.rb @@ -11,25 +11,28 @@ class MediaTest < ActiveSupport::TestCase end test 'should create all records in database when synced' do - assert_equal 2, Artist.count - assert_equal 3, Album.count - assert_equal 8, Song.count + assert_equal 3, Artist.count + assert_equal 4, Album.count + assert_equal 9, Song.count end test 'should create associations between artists and albums' do assert_equal Album.where(name: %w(album1 album2)).ids.sort, Artist.find_by_name('artist1').albums.ids.sort assert_equal Album.where(name: 'album3').ids.sort, Artist.find_by_name('artist2').albums.ids.sort + assert_equal Album.where(name: 'album4').ids.sort, Artist.find_by_is_various(true).albums.ids.sort end test 'should create associations between albums and songs' do assert_equal Song.where(name: %w(flac_sample m4a_sample)).ids.sort, Album.find_by_name('album1').songs.ids.sort assert_equal Song.where(name: 'mp3_sample').ids.sort, Album.find_by_name('album2').songs.ids.sort assert_equal Song.where(name: %w(ogg_sample wav_sample opus_sample oga_sample wma_sample)).ids.sort, Album.find_by_name('album3').songs.ids.sort + assert_equal Song.where(name: %w(various_artists_sample)).ids.sort, Album.find_by_name('album4').songs.ids.sort end test 'should create associations between artists and songs' do - assert_equal Song.where(name: %w(flac_sample mp3_sample m4a_sample)).ids.sort, Artist.find_by_name('artist1').songs.ids.sort + assert_equal Song.where(name: %w(flac_sample mp3_sample m4a_sample various_artists_sample)).ids.sort, Artist.find_by_name('artist1').songs.ids.sort assert_equal Song.where(name: %w(ogg_sample wav_sample opus_sample oga_sample wma_sample)).ids.sort, Artist.find_by_name('artist2').songs.ids.sort + assert_equal [], Artist.find_by_is_various(true).songs.ids.sort end test 'should change associations when modify album info on file' do @@ -42,7 +45,7 @@ class MediaTest < ActiveSupport::TestCase end test 'should change associations when modify artist info on file' do - MediaFile.stub(:file_info, media_file_info_stub(file_fixture('artist1_album2.mp3'), artist_name: 'artist2')) do + MediaFile.stub(:file_info, media_file_info_stub(file_fixture('artist1_album2.mp3'), artist_name: 'artist2', albumartist_name: 'artist2')) do Media.sync assert_equal Album.where(name: %w(album2 album3)).ids.sort, Artist.find_by_name('artist2').albums.ids.sort From ca5ab393a2980d3d02cd9a1570ef9202486b6b15 Mon Sep 17 00:00:00 2001 From: aidewoode Date: Thu, 23 Jul 2020 21:38:32 +0800 Subject: [PATCH 02/33] fix redirect issue for 404 and 403 page --- app/controllers/application_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 12ff5531..de10c1c5 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,11 +5,11 @@ class ApplicationController < ActionController::Base before_action :find_current_user - rescue_from ActiveRecord::RecordNotFound, BlackCandyError::NotFound do |exception| + rescue_from BlackCandyError::NotFound do |exception| respond_to do |format| format.js { head :not_found } format.json { head :not_found } - format.html { redirect_to not_found_path, status: :not_found } + format.html { render template: 'errors/not_found', layout: 'error', status: :not_found } end end @@ -17,7 +17,7 @@ class ApplicationController < ActionController::Base respond_to do |format| format.js { head :forbidden } format.json { head :forbidden } - format.html { redirect_to forbidden_path, status: :forbidden } + format.html { render template: 'errors/forbidden', layout: 'error', status: :forbidden } end end From dddf0e16fbd3dbedf5aa20c25549edd681bf520d Mon Sep 17 00:00:00 2001 From: aidewoode Date: Fri, 24 Jul 2020 10:55:35 +0800 Subject: [PATCH 03/33] simplifying the call to require_login --- app/controllers/albums_controller.rb | 1 - app/controllers/application_controller.rb | 1 + app/controllers/artists/albums_controller.rb | 1 - app/controllers/artists_controller.rb | 2 -- app/controllers/errors_controller.rb | 2 ++ app/controllers/home_controller.rb | 2 -- app/controllers/playlists/songs_controller.rb | 1 - app/controllers/playlists_controller.rb | 1 - app/controllers/sessions_controller.rb | 2 ++ app/controllers/settings_controller.rb | 2 -- app/controllers/songs_controller.rb | 2 -- app/controllers/stream_controller.rb | 1 - app/controllers/users_controller.rb | 1 - 13 files changed, 5 insertions(+), 14 deletions(-) diff --git a/app/controllers/albums_controller.rb b/app/controllers/albums_controller.rb index 1f967c8a..dd4b6a56 100644 --- a/app/controllers/albums_controller.rb +++ b/app/controllers/albums_controller.rb @@ -3,7 +3,6 @@ class AlbumsController < ApplicationController include Pagy::Backend - before_action :require_login before_action :find_album, except: [:index] def index diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index de10c1c5..a7f90c41 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -4,6 +4,7 @@ class ApplicationController < ActionController::Base include SessionsHelper before_action :find_current_user + before_action :require_login rescue_from BlackCandyError::NotFound do |exception| respond_to do |format| diff --git a/app/controllers/artists/albums_controller.rb b/app/controllers/artists/albums_controller.rb index 4053f581..543e320d 100644 --- a/app/controllers/artists/albums_controller.rb +++ b/app/controllers/artists/albums_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class Artists::AlbumsController < ApplicationController - before_action :require_login before_action :find_artist before_action :find_albums diff --git a/app/controllers/artists_controller.rb b/app/controllers/artists_controller.rb index 15d5db76..3598493a 100644 --- a/app/controllers/artists_controller.rb +++ b/app/controllers/artists_controller.rb @@ -5,8 +5,6 @@ class ArtistsController < ApplicationController include Pagy::Backend - before_action :require_login - def index records = Artist.search(params[:query]).order(:name) @pagy, @artists = pagy_countless(records) diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index 55a182d0..5c329ff6 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -3,6 +3,8 @@ class ErrorsController < ApplicationController layout 'error' + skip_before_action :require_login + def forbidden render status: :forbidden end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index f6d32a1b..03e57c8b 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class HomeController < ApplicationController - before_action :require_login - def index redirect_to albums_path end diff --git a/app/controllers/playlists/songs_controller.rb b/app/controllers/playlists/songs_controller.rb index 7b48188e..a573b353 100644 --- a/app/controllers/playlists/songs_controller.rb +++ b/app/controllers/playlists/songs_controller.rb @@ -3,7 +3,6 @@ class Playlists::SongsController < ApplicationController include Pagy::Backend - before_action :require_login before_action :find_playlist before_action :find_songs, only: [:create, :destroy] diff --git a/app/controllers/playlists_controller.rb b/app/controllers/playlists_controller.rb index 9505467d..a15d9df2 100644 --- a/app/controllers/playlists_controller.rb +++ b/app/controllers/playlists_controller.rb @@ -3,7 +3,6 @@ class PlaylistsController < ApplicationController include Pagy::Backend - before_action :require_login before_action :find_playlist, only: [:destroy, :update] def index diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 76e975b8..a13ad228 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -3,6 +3,8 @@ class SessionsController < ApplicationController layout 'base' + skip_before_action :require_login + def new redirect_to root_path if logged_in? end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index facc304d..b42beafe 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class SettingsController < ApplicationController - before_action :require_login - def show end diff --git a/app/controllers/songs_controller.rb b/app/controllers/songs_controller.rb index 25745b5b..af336118 100644 --- a/app/controllers/songs_controller.rb +++ b/app/controllers/songs_controller.rb @@ -3,8 +3,6 @@ class SongsController < ApplicationController include Pagy::Backend - before_action :require_login - def index records = Song.search(params[:query]).includes(:artist, :album).order(:name) @pagy, @songs = pagy_countless(records) diff --git a/app/controllers/stream_controller.rb b/app/controllers/stream_controller.rb index d3cf00d1..674c69bf 100644 --- a/app/controllers/stream_controller.rb +++ b/app/controllers/stream_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class StreamController < ApplicationController - before_action :require_login before_action :find_stream before_action :set_header diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2f40043a..9cd61780 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true class UsersController < ApplicationController - before_action :require_login before_action :require_admin, only: [:index, :create, :new, :destroy] before_action :find_user, only: [:edit, :update, :destroy] before_action :auth_user, only: [:edit, :update] From 0f4ab0f19cffa2fad37e5379742615bebba33ecd Mon Sep 17 00:00:00 2001 From: aidewoode Date: Fri, 24 Jul 2020 16:02:52 +0800 Subject: [PATCH 04/33] remove redis-objects gem --- Gemfile | 2 -- Gemfile.lock | 3 --- config/initializers/redis.rb | 1 - docker-compose.dev.yml | 1 - docker-compose.pwd.yml | 1 - docker-compose.yml | 1 - test/test_helper.rb | 4 ---- 7 files changed, 13 deletions(-) delete mode 100644 config/initializers/redis.rb diff --git a/Gemfile b/Gemfile index 4c610db5..9a0a115b 100644 --- a/Gemfile +++ b/Gemfile @@ -23,8 +23,6 @@ gem 'sidekiq', '~> 6.0.0' gem 'turbolinks', '~> 5.2.1' # Pagination gem 'pagy', '~> 3.5.0' -# Map redis types directly to ruby objects -gem 'redis-objects', '~> 1.4' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' diff --git a/Gemfile.lock b/Gemfile.lock index 072378ae..70778747 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -187,8 +187,6 @@ GEM rb-inotify (0.10.0) ffi (~> 1.0) redis (4.1.0) - redis-objects (1.4.3) - redis (~> 4.0) request_store (1.4.1) rack (>= 1.4) rubocop (0.61.1) @@ -284,7 +282,6 @@ DEPENDENCIES puma (~> 4.3.1) rails (~> 6.0.2.1) rails-settings-cached (~> 2.1.0) - redis-objects (~> 1.4) rubocop (~> 0.61.1) selenium-webdriver (~> 3.142.6) sidekiq (~> 6.0.0) diff --git a/config/initializers/redis.rb b/config/initializers/redis.rb deleted file mode 100644 index c83cab2f..00000000 --- a/config/initializers/redis.rb +++ /dev/null @@ -1 +0,0 @@ -Redis::Objects.redis = Redis.new(url: ENV['REDIS_DATA_URL']) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 6eb000f6..094e770f 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -16,7 +16,6 @@ services: environment: DB_HOST: postgres DB_USER: postgres - REDIS_DATA_URL: redis://redis:6379/0 REDIS_SIDEKIQ_URL: redis://redis:6379/1 MEDIA_PATH: /media_data WEBPACKER_DEV_SERVER_HOST: webpacker diff --git a/docker-compose.pwd.yml b/docker-compose.pwd.yml index 5c5c362b..dc88f106 100644 --- a/docker-compose.pwd.yml +++ b/docker-compose.pwd.yml @@ -8,7 +8,6 @@ services: environment: DB_HOST: postgres DB_USER: postgres - REDIS_DATA_URL: redis://redis:6379/0 REDIS_CACHE_URL: redis://redis:6379/1 REDIS_SIDEKIQ_URL: redis://redis:6379/2 MEDIA_PATH: /media_data diff --git a/docker-compose.yml b/docker-compose.yml index bbd4ba3c..72c1e283 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,6 @@ services: environment: DB_HOST: postgres DB_USER: postgres - REDIS_DATA_URL: redis://redis:6379/0 REDIS_CACHE_URL: redis://redis:6379/1 REDIS_SIDEKIQ_URL: redis://redis:6379/2 MEDIA_PATH: /media_data diff --git a/test/test_helper.rb b/test/test_helper.rb index fe99673b..3c225cce 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -45,10 +45,6 @@ def create_tmp_file(format: '') tmp_file.unlink end - def flush_redis - Redis::Objects.redis.flushdb - end - def login(user) post session_url, params: { email: user.email, password: 'foobar' } end From 9cc17e4dc3dfff388bab81b5fcd149319afc10d6 Mon Sep 17 00:00:00 2001 From: aidewoode Date: Tue, 28 Jul 2020 08:04:39 +0800 Subject: [PATCH 05/33] update wahwah to v1.1.1 --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 9a0a115b..2ca75dee 100644 --- a/Gemfile +++ b/Gemfile @@ -14,7 +14,7 @@ gem 'jbuilder', '~> 2.9.1' # Use ActiveModel has_secure_password gem 'bcrypt', '~> 3.1.11' # Get meta data from audio file -gem 'wahwah', '~> 1.0.0' +gem 'wahwah', '~> 1.1.1' # For settings gem 'rails-settings-cached', '~> 2.1.0' # Use sidekiq for backgroud job diff --git a/Gemfile.lock b/Gemfile.lock index 70778747..153e852b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -233,7 +233,7 @@ GEM thread_safe (~> 0.1) unicode-display_width (1.4.1) uniform_notifier (1.12.1) - wahwah (1.0.0) + wahwah (1.1.1) web-console (3.7.0) actionview (>= 5.0) activemodel (>= 5.0) @@ -289,7 +289,7 @@ DEPENDENCIES spring-watcher-listen (~> 2.0.0) turbolinks (~> 5.2.1) tzinfo-data - wahwah (~> 1.0.0) + wahwah (~> 1.1.1) web-console (>= 3.3.0) webdrivers (~> 4.1.3) webmock (~> 3.6.2) From b44d4bd7cfe2ca678afcfb0e725d709a9fbfa900 Mon Sep 17 00:00:00 2001 From: aidewoode Date: Tue, 4 Aug 2020 13:56:37 +0800 Subject: [PATCH 06/33] use ITCSS structure to organize css --- app/frontend/packs/application.css | 1 - app/frontend/stylesheets/application.css | 34 +- app/frontend/stylesheets/components/box.css | 12 + app/frontend/stylesheets/components/card.css | 93 +++++ .../stylesheets/components/dialog.css | 12 + .../stylesheets/components/heading.css | 16 + app/frontend/stylesheets/components/image.css | 7 + app/frontend/stylesheets/components/line.css | 6 + app/frontend/stylesheets/components/list.css | 6 + .../{pages => components}/player.css | 46 +++ .../{pages => components}/playlist.css | 10 + app/frontend/stylesheets/components/songs.css | 49 +++ app/frontend/stylesheets/elements/link.css | 8 + app/frontend/stylesheets/elements/page.css | 6 + .../stylesheets/generic/box_sizing.css | 9 + .../stylesheets/generic/normalize.css | 349 ++++++++++++++++++ app/frontend/stylesheets/generic/reset.css | 45 +++ .../stylesheets/{ => objects}/animations.css | 0 app/frontend/stylesheets/objects/grid.css | 0 app/frontend/stylesheets/objects/layout.css | 199 ++++++++++ app/frontend/stylesheets/pages/layout.css | 69 ---- app/frontend/stylesheets/pages/songs.css | 15 - app/frontend/stylesheets/reset.css | 29 -- app/frontend/stylesheets/responsive.css | 323 ---------------- .../{settings.css => settings/global.css} | 0 .../stylesheets/settings/media_query.css | 9 + .../stylesheets/{ => settings}/theme.css | 0 .../stylesheets/{ => utilities}/display.css | 20 + app/frontend/stylesheets/utilities/flex.css | 0 .../stylesheets/{ => utilities}/helper.css | 0 app/frontend/stylesheets/utilities/sizing.css | 0 .../stylesheets/utilities/spacing.css | 0 package.json | 1 - postcss.config.js | 3 +- yarn.lock | 5 - 35 files changed, 926 insertions(+), 456 deletions(-) rename app/frontend/stylesheets/{pages => components}/player.css (74%) rename app/frontend/stylesheets/{pages => components}/playlist.css (82%) create mode 100644 app/frontend/stylesheets/components/songs.css create mode 100644 app/frontend/stylesheets/elements/link.css create mode 100644 app/frontend/stylesheets/elements/page.css create mode 100644 app/frontend/stylesheets/generic/box_sizing.css create mode 100644 app/frontend/stylesheets/generic/normalize.css create mode 100644 app/frontend/stylesheets/generic/reset.css rename app/frontend/stylesheets/{ => objects}/animations.css (100%) create mode 100644 app/frontend/stylesheets/objects/grid.css create mode 100644 app/frontend/stylesheets/objects/layout.css delete mode 100644 app/frontend/stylesheets/pages/layout.css delete mode 100644 app/frontend/stylesheets/pages/songs.css delete mode 100644 app/frontend/stylesheets/reset.css delete mode 100644 app/frontend/stylesheets/responsive.css rename app/frontend/stylesheets/{settings.css => settings/global.css} (100%) create mode 100644 app/frontend/stylesheets/settings/media_query.css rename app/frontend/stylesheets/{ => settings}/theme.css (100%) rename app/frontend/stylesheets/{ => utilities}/display.css (76%) create mode 100644 app/frontend/stylesheets/utilities/flex.css rename app/frontend/stylesheets/{ => utilities}/helper.css (100%) create mode 100644 app/frontend/stylesheets/utilities/sizing.css create mode 100644 app/frontend/stylesheets/utilities/spacing.css diff --git a/app/frontend/packs/application.css b/app/frontend/packs/application.css index e1be53c9..9dbc60a1 100644 --- a/app/frontend/packs/application.css +++ b/app/frontend/packs/application.css @@ -1,2 +1 @@ -@import 'normalize.css'; @import '../stylesheets/application.css'; diff --git a/app/frontend/stylesheets/application.css b/app/frontend/stylesheets/application.css index d9fc3f73..a93bf7f7 100644 --- a/app/frontend/stylesheets/application.css +++ b/app/frontend/stylesheets/application.css @@ -1,9 +1,17 @@ -@import 'settings.css'; -@import 'theme.css'; -@import 'reset.css'; -@import 'display.css'; -@import 'helper.css'; -@import 'animations.css'; +@import 'settings/global.css'; +@import 'settings/theme.css'; +@import 'settings/media_query.css'; + +@import 'generic/normalize.css'; +@import 'generic/reset.css'; +@import 'generic/box_sizing.css'; + +@import 'elements/page.css'; +@import 'elements/link.css'; + +@import 'objects/animations.css'; +@import 'objects/grid.css'; +@import 'objects/layout.css'; @import 'components/form.css'; @import 'components/logo.css'; @@ -24,10 +32,12 @@ @import 'components/notice.css'; @import 'components/box.css'; @import 'components/flash.css'; +@import 'components/playlist.css'; +@import 'components/player.css'; +@import 'components/songs.css'; -@import 'pages/layout.css'; -@import 'pages/playlist.css'; -@import 'pages/player.css'; -@import 'pages/songs.css'; - -@import 'responsive.css'; +@import 'utilities/display.css'; +@import 'utilities/flex.css'; +@import 'utilities/spacing.css'; +@import 'utilities/sizing.css'; +@import 'utilities/helper.css'; diff --git a/app/frontend/stylesheets/components/box.css b/app/frontend/stylesheets/components/box.css index a711ba82..d0484d16 100644 --- a/app/frontend/stylesheets/components/box.css +++ b/app/frontend/stylesheets/components/box.css @@ -14,3 +14,15 @@ text-align: center; margin-bottom: 40px; } + +@media (--narrow) { + .box--large { + max-width: 325px; + } +} + +@media (--extra-narrow) { + .box { + max-width: 290px; + } +} diff --git a/app/frontend/stylesheets/components/card.css b/app/frontend/stylesheets/components/card.css index 9336cf1c..c5d750f5 100644 --- a/app/frontend/stylesheets/components/card.css +++ b/app/frontend/stylesheets/components/card.css @@ -28,3 +28,96 @@ margin-left: 15px; margin-right: 15px; } + +@media (--extra-wide) { + .cards { + max-width: 1260px; + } + + .cards__item { + width: calc(100% / 7 - 30px); + } +} + +@media (--wide) { + .cards { + max-width: 1080px; + } + + .cards__item { + width: calc(100% / 6 - 30px); + } +} + +@media (--extra-large) { + .cards { + max-width: 900px; + } + + .cards__item { + width: calc(100% / 5 - 30px); + } +} + +@media (--large) { + .cards { + max-width: 720px; + } + + .cards__item { + width: calc(100% / 4 - 30px); + } +} + +@media (--medium) { + .cards { + max-width: 540px; + } + + .cards__item { + width: calc(100% / 3 - 30px); + } +} + +@media (--small) { + .cards { + max-width: 360px; + } + + .cards__item { + width: calc(100% / 2 - 30px); + } +} + +@media (--extra-small) { + .cards { + max-width: 540px; + } + + .cards__item { + width: calc(100% / 3 - 30px); + } +} + +@media (--narrow) { + .cards { + max-width: 340px; + } + + .cards__item { + width: calc(100% / 2 - 20px); + margin-left: 10px; + margin-right: 10px; + } +} + +@media (--extra-narrow) { + .cards { + max-width: 310px; + } + + .cards__item { + width: calc(100% / 2 - 20px); + margin-bottom: 30px; + } +} diff --git a/app/frontend/stylesheets/components/dialog.css b/app/frontend/stylesheets/components/dialog.css index cc02c2e2..ba22594b 100644 --- a/app/frontend/stylesheets/components/dialog.css +++ b/app/frontend/stylesheets/components/dialog.css @@ -36,3 +36,15 @@ .dialog .overlay { background: var(--dialog-bg-color); } + +@media (--narrow) { + .dialog { + max-width: 325px; + } +} + +@media (--extra-narrow) { + .dialog { + max-width: 290px; + } +} diff --git a/app/frontend/stylesheets/components/heading.css b/app/frontend/stylesheets/components/heading.css index cf7765a2..6ddf4500 100644 --- a/app/frontend/stylesheets/components/heading.css +++ b/app/frontend/stylesheets/components/heading.css @@ -51,3 +51,19 @@ .heading__footer { margin-left: auto; } + +@media (--narrow) { + .heading--expand { + margin: 30px 0 20px; + } +} + +@media (--extra-narrow) { + .heading__body__text--main { + margin-bottom: 10px; + } + + .heading__body__text { + margin-bottom: 5px; + } +} diff --git a/app/frontend/stylesheets/components/image.css b/app/frontend/stylesheets/components/image.css index fc6f8313..b3e1c9e4 100644 --- a/app/frontend/stylesheets/components/image.css +++ b/app/frontend/stylesheets/components/image.css @@ -18,3 +18,10 @@ width: 200px; height: 200px; } + +@media (--extra-narrow) { + .image { + width: 135px; + height: 135px; + } +} diff --git a/app/frontend/stylesheets/components/line.css b/app/frontend/stylesheets/components/line.css index 99e453dd..b5cd63fb 100644 --- a/app/frontend/stylesheets/components/line.css +++ b/app/frontend/stylesheets/components/line.css @@ -3,3 +3,9 @@ border-top: 1px solid var(--line-color); margin: 40px 0; } + +@media (--narrow) { + .line { + margin: 30px 0; + } +} diff --git a/app/frontend/stylesheets/components/list.css b/app/frontend/stylesheets/components/list.css index 974dea25..c231b30d 100644 --- a/app/frontend/stylesheets/components/list.css +++ b/app/frontend/stylesheets/components/list.css @@ -75,3 +75,9 @@ .list__item__info--action .icon:hover { color: var(--list-active-color); } + +@media (--narrow) { + .list__item { + padding: 10px 0; + } +} diff --git a/app/frontend/stylesheets/pages/player.css b/app/frontend/stylesheets/components/player.css similarity index 74% rename from app/frontend/stylesheets/pages/player.css rename to app/frontend/stylesheets/components/player.css index 50f94055..7274fe1e 100644 --- a/app/frontend/stylesheets/pages/player.css +++ b/app/frontend/stylesheets/components/player.css @@ -120,3 +120,49 @@ background: var(--player-bg-color); opacity: 0.9; } + +@media (--extra-small) { + .player__footer { + display: block !important; + } + + .player__control, + .player .heading { + padding: 20px; + } +} + +@media (--narrow) { + .player .image--small { + width: 50px; + height: 50px; + } + + .player .heading { + display: flex; + align-items: center; + } + + .player .heading, + .player__control { + padding: 12px 15px; + } + + .player .heading__body__text { + display: none; + } + + .player .heading__body__text.heading__body__text--main { + display: block; + } + + .player__timer__item { + margin-right: 2px; + } +} + +@media (--extra-narrow) { + .player__timer__item { + margin-right: 5px; + } +} diff --git a/app/frontend/stylesheets/pages/playlist.css b/app/frontend/stylesheets/components/playlist.css similarity index 82% rename from app/frontend/stylesheets/pages/playlist.css rename to app/frontend/stylesheets/components/playlist.css index 9d78fff9..5ed0fae9 100644 --- a/app/frontend/stylesheets/pages/playlist.css +++ b/app/frontend/stylesheets/components/playlist.css @@ -29,3 +29,13 @@ border-radius: var(--playlist-heading-border-radius); padding: 12px 6px 12px 8px; } + +@media (--narrow) { + .playlist__nav { + padding: 15px 15px 0; + } + + .playlist__content { + margin: 15px; + } +} diff --git a/app/frontend/stylesheets/components/songs.css b/app/frontend/stylesheets/components/songs.css new file mode 100644 index 00000000..d85b2270 --- /dev/null +++ b/app/frontend/stylesheets/components/songs.css @@ -0,0 +1,49 @@ +.songs__name { + min-width: 30%; +} + +.songs__artist { + min-width: 30%; +} + +.songs__album { + min-width: 30%; +} + +.songs__actions { + min-width: 10%; +} + +@media (--small) { + .songs__artist { + display: none; + } + + .songs__album { + display: none; + } +} + +@media (--extra-small) { + .songs__album { + display: none; + } + + .songs__name { + min-width: 50%; + } + + .songs__artist { + min-width: 40%; + } +} + +@media (--narrow) { + .songs__artist { + display: none; + } + + .songs__album { + display: none; + } +} diff --git a/app/frontend/stylesheets/elements/link.css b/app/frontend/stylesheets/elements/link.css new file mode 100644 index 00000000..cb0288c3 --- /dev/null +++ b/app/frontend/stylesheets/elements/link.css @@ -0,0 +1,8 @@ +a { + text-decoration: none; + color: var(--body-color); +} + +a:hover { + color: var(--link-active-color); +} diff --git a/app/frontend/stylesheets/elements/page.css b/app/frontend/stylesheets/elements/page.css new file mode 100644 index 00000000..1539b6ac --- /dev/null +++ b/app/frontend/stylesheets/elements/page.css @@ -0,0 +1,6 @@ +body { + font-family: var(--sans-serif-fonts); + background-color: var(--body-bg-color); + color: var(--body-color); + font-size: var(--font-size-md); +} diff --git a/app/frontend/stylesheets/generic/box_sizing.css b/app/frontend/stylesheets/generic/box_sizing.css new file mode 100644 index 00000000..474a02fa --- /dev/null +++ b/app/frontend/stylesheets/generic/box_sizing.css @@ -0,0 +1,9 @@ +html { + box-sizing: border-box; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} diff --git a/app/frontend/stylesheets/generic/normalize.css b/app/frontend/stylesheets/generic/normalize.css new file mode 100644 index 00000000..192eb9ce --- /dev/null +++ b/app/frontend/stylesheets/generic/normalize.css @@ -0,0 +1,349 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/app/frontend/stylesheets/generic/reset.css b/app/frontend/stylesheets/generic/reset.css new file mode 100644 index 00000000..99e624d5 --- /dev/null +++ b/app/frontend/stylesheets/generic/reset.css @@ -0,0 +1,45 @@ +blockquote, +dd, +dl, +figure, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +p, +pre { + margin: 0; +} + +button { + background: transparent; + border: 0; + padding: 0; +} + +ol, +ul { + margin: 0; + padding-left: 0; +} + +li > ol, +li > ul { + margin-bottom: 0; +} + +table { + border-collapse: collapse; +} + +textarea { + resize: vertical; +} + +/* Reset style for turbolinks progress bar */ +.turbolinks-progress-bar { + background-color: var(--progress-bar-bg-color); +} diff --git a/app/frontend/stylesheets/animations.css b/app/frontend/stylesheets/objects/animations.css similarity index 100% rename from app/frontend/stylesheets/animations.css rename to app/frontend/stylesheets/objects/animations.css diff --git a/app/frontend/stylesheets/objects/grid.css b/app/frontend/stylesheets/objects/grid.css new file mode 100644 index 00000000..e69de29b diff --git a/app/frontend/stylesheets/objects/layout.css b/app/frontend/stylesheets/objects/layout.css new file mode 100644 index 00000000..16cd7510 --- /dev/null +++ b/app/frontend/stylesheets/objects/layout.css @@ -0,0 +1,199 @@ +.layout { + display: flex; +} + +.layout__main { + display: flex; + flex-direction: column; + width: 100%; + min-height: 100vh; +} + +.layout__sidebar { + position: fixed; + left: 0; + top: 0; + bottom: 0; + background: var(--layout-sidebar-bg-color); + display: flex; + flex-direction: column; + transition: 0.2s; +} + +.layout__sidebar.show { + z-index: 100; + visibility: visible; + height: 100%; + opacity: 1; +} + +.layout__main__header { + position: sticky; + top: 0; + background: var(--layout-header-bg-color); + z-index: 10; + border-bottom: 1px solid var(--layout-header-border-color); +} + +.layout__main__content { + height: 100%; + margin: 25px 60px 35px; +} + +.layout__main__footer { + position: fixed; + bottom: 0; + width: 100%; +} + +.layout__nav-bar { + padding-top: 15px; + max-width: 350px; + margin: auto; +} + +.layout__search-bar { + padding: 20px; +} + +.layout__search-bar .input { + width: 350px; +} + +.layout__sidebar .input { + background: var(--layout-sidebar-input-bg-color); +} + +.layout__sidebar .input input { + background: var(--layout-sidebar-input-bg-color); +} + +@media (--extra-wide) { + .layout__sidebar { + width: 380px; + } + + .layout__main { + margin-left: 380px; + } +} + +@media (--wide) { + .layout__sidebar { + width: 370px; + } + + .layout__main { + margin-left: 370px; + } +} + +@media (--extra-large) { + .layout__sidebar { + width: 360px; + } + + .layout__main { + margin-left: 360px; + } +} + +@media (--large) { + .layout__sidebar { + width: 350px; + } + + .layout__main { + margin-left: 350px; + } + + .layout__main__content { + margin-left: 30px; + margin-right: 30px; + } +} + +@media (--medium) { + .layout__sidebar { + width: 340px; + } + + .layout__main { + margin-left: 340px; + } + + .layout__main__content { + margin-left: 25px; + margin-right: 25px; + } +} + +@media (--small) { + .layout__sidebar { + width: 330px; + } + + .layout__main { + margin-left: 330px; + } + + .layout__main__content { + margin-left: 20px; + margin-right: 20px; + } +} + +@media (--extra-small) { + .layout__sidebar { + position: fixed; + bottom: 0; + z-index: -1; + height: 100%; + width: 100%; + visibility: hidden; + opacity: 0; + } + + .layout__main { + margin-left: 0; + } + + .layout__main__footer { + display: block !important; + } + + .layout__main__content { + margin-left: 10px; + margin-right: 10px; + margin-bottom: 70px; + } +} + +@media (--narrow) { + .layout__search-bar { + padding: 15px 10px; + } + + .layout__search-bar .input { + width: 260px; + } + + .layout__nav-bar { + max-width: 340px; + padding-top: 6px; + } +} + +@media (--extra-narrow) { + .layout__search-bar .input { + width: 220px; + } + + .layout__search-bar .input input { + width: 75%; + } + + .layout__nav-bar { + max-width: 300px; + } +} diff --git a/app/frontend/stylesheets/pages/layout.css b/app/frontend/stylesheets/pages/layout.css deleted file mode 100644 index b67e957f..00000000 --- a/app/frontend/stylesheets/pages/layout.css +++ /dev/null @@ -1,69 +0,0 @@ -.layout { - display: flex; -} - -.layout__main { - display: flex; - flex-direction: column; - width: 100%; - min-height: 100vh; -} - -.layout__sidebar { - position: fixed; - left: 0; - top: 0; - bottom: 0; - background: var(--layout-sidebar-bg-color); - display: flex; - flex-direction: column; - transition: 0.2s; -} - -.layout__sidebar.show { - z-index: 100; - visibility: visible; - height: 100%; - opacity: 1; -} - -.layout__main__header { - position: sticky; - top: 0; - background: var(--layout-header-bg-color); - z-index: 10; - border-bottom: 1px solid var(--layout-header-border-color); -} - -.layout__main__content { - height: 100%; - margin: 25px 60px 35px; -} - -.layout__main__footer { - position: fixed; - bottom: 0; - width: 100%; -} - -.layout__nav-bar { - padding-top: 15px; - max-width: 350px; - margin: auto; -} - -.layout__search-bar { - padding: 20px; -} - -.layout__search-bar .input { - width: 350px; -} - -.layout__sidebar .input { - background: var(--layout-sidebar-input-bg-color); -} - -.layout__sidebar .input input { - background: var(--layout-sidebar-input-bg-color); -} diff --git a/app/frontend/stylesheets/pages/songs.css b/app/frontend/stylesheets/pages/songs.css deleted file mode 100644 index fee1e156..00000000 --- a/app/frontend/stylesheets/pages/songs.css +++ /dev/null @@ -1,15 +0,0 @@ -.songs__name { - min-width: 30%; -} - -.songs__artist { - min-width: 30%; -} - -.songs__album { - min-width: 30%; -} - -.songs__actions { - min-width: 10%; -} diff --git a/app/frontend/stylesheets/reset.css b/app/frontend/stylesheets/reset.css deleted file mode 100644 index bcfa157b..00000000 --- a/app/frontend/stylesheets/reset.css +++ /dev/null @@ -1,29 +0,0 @@ -html { - box-sizing: border-box; - font-size: var(--font-size-md); -} - -*, -*:before, -*:after { - box-sizing: inherit; -} - -body { - font-family: var(--sans-serif-fonts); - background-color: var(--body-bg-color); - color: var(--body-color); -} - -a { - text-decoration: none; - color: var(--body-color); -} - -a:hover { - color: var(--link-active-color); -} - -.turbolinks-progress-bar { - background-color: var(--progress-bar-bg-color); -} diff --git a/app/frontend/stylesheets/responsive.css b/app/frontend/stylesheets/responsive.css deleted file mode 100644 index ccbad1c0..00000000 --- a/app/frontend/stylesheets/responsive.css +++ /dev/null @@ -1,323 +0,0 @@ -@media screen and (min-width: 1880px) { - .layout__sidebar { - width: 380px; - } - - .layout__main { - margin-left: 380px; - } - - .cards { - max-width: 1260px; - } - - .cards__item { - width: calc(100% / 7 - 30px); - } -} - -@media screen and (max-width: 1880px) { - .layout__sidebar { - width: 370px; - } - - .layout__main { - margin-left: 370px; - } - - .cards { - max-width: 1080px; - } - - .cards__item { - width: calc(100% / 6 - 30px); - } -} - -@media screen and (max-width: 1630px) { - .layout__sidebar { - width: 360px; - } - - .layout__main { - margin-left: 360px; - } - - .cards { - max-width: 900px; - } - - .cards__item { - width: calc(100% / 5 - 30px); - } -} - -@media screen and (max-width: 1380px) { - .layout__sidebar { - width: 350px; - } - - .layout__main { - margin-left: 350px; - } - - .layout__main__content { - margin-left: 30px; - margin-right: 30px; - } - - .cards { - max-width: 720px; - } - - .cards__item { - width: calc(100% / 4 - 30px); - } -} - -@media screen and (max-width: 1130px) { - .layout__sidebar { - width: 340px; - } - - .layout__main { - margin-left: 340px; - } - - .layout__main__content { - margin-left: 25px; - margin-right: 25px; - } - - .cards { - max-width: 540px; - } - - .cards__item { - width: calc(100% / 3 - 30px); - } -} - -@media screen and (max-width: 930px) { - .layout__sidebar { - width: 330px; - } - - .layout__main { - margin-left: 330px; - } - - .layout__main__content { - margin-left: 20px; - margin-right: 20px; - } - - .cards { - max-width: 360px; - } - - .cards__item { - width: calc(100% / 2 - 30px); - } - - .songs__artist { - display: none; - } - - .songs__album { - display: none; - } -} - -@media screen and (max-width: 730px) { - .layout__sidebar { - position: fixed; - bottom: 0; - z-index: -1; - height: 100%; - width: 100%; - visibility: hidden; - opacity: 0; - } - - .layout__main { - margin-left: 0; - } - - .layout__main__footer { - display: block !important; - } - - .layout__main__content { - margin-left: 10px; - margin-right: 10px; - margin-bottom: 70px; - } - - .player__footer { - display: block !important; - } - - .cards { - max-width: 540px; - } - - .cards__item { - width: calc(100% / 3 - 30px); - } - - .display__medium-width { - max-width: 500px; - } - - .songs__album { - display: none; - } - - .songs__name { - min-width: 50%; - } - - .songs__artist { - min-width: 40%; - } - - .player__control, - .player .heading { - padding: 20px; - } -} - -@media screen and (max-width: 560px) { - .cards { - max-width: 340px; - } - - .cards__item { - width: calc(100% / 2 - 20px); - margin-left: 10px; - margin-right: 10px; - } - - .layout__search-bar { - padding: 15px 10px; - } - - .layout__search-bar .input { - width: 260px; - } - - .layout__nav-bar { - max-width: 340px; - padding-top: 6px; - } - - .display__medium-width, - .display__small-width, - .dialog, - .box--large { - max-width: 325px; - } - - .line { - margin: 30px 0; - } - - .heading--expand { - margin: 30px 0 20px; - } - - .songs__artist { - display: none; - } - - .songs__album { - display: none; - } - - .playlist__nav { - padding: 15px 15px 0; - } - - .playlist__content { - margin: 15px; - } - - .list__item { - padding: 10px 0; - } - - .player .image--small { - width: 50px; - height: 50px; - } - - .player .heading { - display: flex; - align-items: center; - } - - .player .heading, - .player__control { - padding: 12px 15px; - } - - .player .heading__body__text { - display: none; - } - - .player .heading__body__text.heading__body__text--main { - display: block; - } - - .player__timer__item { - margin-right: 2px; - } -} - -@media screen and (max-width: 360px) { - .image { - width: 135px; - height: 135px; - } - - .cards { - max-width: 310px; - } - - .cards__item { - width: calc(100% / 2 - 20px); - margin-bottom: 30px; - } - - .layout__search-bar .input { - width: 220px; - } - - .layout__search-bar .input input { - width: 75%; - } - - .layout__nav-bar { - max-width: 300px; - } - - .display__medium-width, - .display__small-width, - .dialog, - .box { - max-width: 290px; - } - - .player__timer__item { - margin-right: 5px; - } - - .heading__body__text--main { - margin-bottom: 10px; - } - - .heading__body__text { - margin-bottom: 5px; - } -} diff --git a/app/frontend/stylesheets/settings.css b/app/frontend/stylesheets/settings/global.css similarity index 100% rename from app/frontend/stylesheets/settings.css rename to app/frontend/stylesheets/settings/global.css diff --git a/app/frontend/stylesheets/settings/media_query.css b/app/frontend/stylesheets/settings/media_query.css new file mode 100644 index 00000000..45c677c2 --- /dev/null +++ b/app/frontend/stylesheets/settings/media_query.css @@ -0,0 +1,9 @@ +@custom-media --extra-wide (min-width: 1880px); +@custom-media --wide (max-width: 1880px); +@custom-media --extra-large (max-width: 1630px); +@custom-media --large (max-width: 1380px); +@custom-media --medium (max-width: 1130px); +@custom-media --small (max-width: 930px); +@custom-media --extra-small (max-width: 730px); +@custom-media --narrow (max-width: 560px); +@custom-media --extra-narrow (max-width: 360px); diff --git a/app/frontend/stylesheets/theme.css b/app/frontend/stylesheets/settings/theme.css similarity index 100% rename from app/frontend/stylesheets/theme.css rename to app/frontend/stylesheets/settings/theme.css diff --git a/app/frontend/stylesheets/display.css b/app/frontend/stylesheets/utilities/display.css similarity index 76% rename from app/frontend/stylesheets/display.css rename to app/frontend/stylesheets/utilities/display.css index 0e903cf2..ebdeb829 100644 --- a/app/frontend/stylesheets/display.css +++ b/app/frontend/stylesheets/utilities/display.css @@ -61,3 +61,23 @@ max-width: 650px; margin: auto; } + +@media (--extra-small) { + .display__medium-width { + max-width: 500px; + } +} + +@media (--narrow) { + .display__medium-width, + .display__small-width { + max-width: 325px; + } +} + +@media (--extra-narrow) { + .display__medium-width, + .display__small-width { + max-width: 290px; + } +} diff --git a/app/frontend/stylesheets/utilities/flex.css b/app/frontend/stylesheets/utilities/flex.css new file mode 100644 index 00000000..e69de29b diff --git a/app/frontend/stylesheets/helper.css b/app/frontend/stylesheets/utilities/helper.css similarity index 100% rename from app/frontend/stylesheets/helper.css rename to app/frontend/stylesheets/utilities/helper.css diff --git a/app/frontend/stylesheets/utilities/sizing.css b/app/frontend/stylesheets/utilities/sizing.css new file mode 100644 index 00000000..e69de29b diff --git a/app/frontend/stylesheets/utilities/spacing.css b/app/frontend/stylesheets/utilities/spacing.css new file mode 100644 index 00000000..e69de29b diff --git a/package.json b/package.json index aa1e26d5..3679de71 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "@rails/ujs": "^6.0.1", "@rails/webpacker": "^5.1.1", "howler": "^2.1.2", - "normalize.css": "^8.0.1", "stimulus": "^1.1.0", "turbolinks": "^5.2.0" }, diff --git a/postcss.config.js b/postcss.config.js index 5b9e05e8..3365e9ac 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -8,7 +8,8 @@ module.exports = { }, stage: 3, features: { - 'color-mod-function': true + 'color-mod-function': true, + 'custom-media-queries': true } } } diff --git a/yarn.lock b/yarn.lock index 2d3987c1..acb84c93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5604,11 +5604,6 @@ normalize-url@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== -normalize.css@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/normalize.css/-/normalize.css-8.0.1.tgz#9b98a208738b9cc2634caacbc42d131c97487bf3" - integrity sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg== - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" From 515af55e833fb553fb892848318531e48e1a719c Mon Sep 17 00:00:00 2001 From: aidewoode Date: Tue, 11 Aug 2020 12:03:41 +0800 Subject: [PATCH 07/33] implement new css layout style --- .../controllers/flash_controller.js | 2 +- .../controllers/mini_player_controller.js | 2 +- .../controllers/player_controller.js | 2 +- app/frontend/stylesheets/application.css | 9 +- app/frontend/stylesheets/components/card.css | 5 +- app/frontend/stylesheets/components/flash.css | 6 - .../stylesheets/components/loader.css | 1 - .../stylesheets/components/sidebar.css | 53 +++++ .../stylesheets/objects/animations.css | 14 ++ app/frontend/stylesheets/objects/flex.css | 100 +++++++++ app/frontend/stylesheets/objects/grid.css | 66 ++++++ app/frontend/stylesheets/objects/layout.css | 199 ------------------ app/frontend/stylesheets/settings/global.css | 8 + app/frontend/stylesheets/settings/theme.css | 9 +- app/frontend/stylesheets/tools/display.css | 9 + app/frontend/stylesheets/tools/grid.css | 92 ++++++++ app/frontend/stylesheets/tools/spacing.css | 61 ++++++ .../stylesheets/utilities/display.css | 38 ++++ app/frontend/stylesheets/utilities/flex.css | 0 .../stylesheets/utilities/overflow.css | 7 + app/frontend/stylesheets/utilities/sizing.css | 19 ++ .../stylesheets/utilities/spacing.css | 8 + app/helpers/application_helper.rb | 2 +- app/views/albums/_album.html.erb | 16 +- app/views/albums/index.html.erb | 2 +- app/views/layouts/_main.html.erb | 28 ++- app/views/layouts/_sidebar.html.erb | 8 +- app/views/layouts/application.html.erb | 14 +- app/views/layouts/base.html.erb | 2 +- app/views/shared/_flash.html.erb | 2 +- app/views/shared/_nav_bar.html.erb | 2 +- app/views/shared/_player.html.erb | 2 +- app/views/shared/_playlist.html.erb | 8 +- app/views/shared/_search_bar.html.erb | 7 +- package.json | 1 + postcss.config.js | 1 + yarn.lock | 73 ++++++- 37 files changed, 617 insertions(+), 261 deletions(-) create mode 100644 app/frontend/stylesheets/components/sidebar.css create mode 100644 app/frontend/stylesheets/objects/flex.css delete mode 100644 app/frontend/stylesheets/objects/layout.css create mode 100644 app/frontend/stylesheets/tools/display.css create mode 100644 app/frontend/stylesheets/tools/grid.css create mode 100644 app/frontend/stylesheets/tools/spacing.css delete mode 100644 app/frontend/stylesheets/utilities/flex.css create mode 100644 app/frontend/stylesheets/utilities/overflow.css diff --git a/app/frontend/javascripts/controllers/flash_controller.js b/app/frontend/javascripts/controllers/flash_controller.js index 88a298a7..93d7b7ba 100644 --- a/app/frontend/javascripts/controllers/flash_controller.js +++ b/app/frontend/javascripts/controllers/flash_controller.js @@ -10,6 +10,6 @@ export default class extends Controller { this.remove(); }, { once: true }); - this.element.classList.add('flash__body--close'); + this.element.classList.add('o-animation-fadeOutUp'); } } diff --git a/app/frontend/javascripts/controllers/mini_player_controller.js b/app/frontend/javascripts/controllers/mini_player_controller.js index 462bce8c..1b409041 100644 --- a/app/frontend/javascripts/controllers/mini_player_controller.js +++ b/app/frontend/javascripts/controllers/mini_player_controller.js @@ -32,7 +32,7 @@ export default class extends Controller { } expand() { - document.querySelector('#js-sidebar').classList.add('show'); + document.querySelector('#js-sidebar').classList.add('c-sidebar--show'); document.body.classList.add('noscroll'); } diff --git a/app/frontend/javascripts/controllers/player_controller.js b/app/frontend/javascripts/controllers/player_controller.js index c62f955d..4678c48c 100644 --- a/app/frontend/javascripts/controllers/player_controller.js +++ b/app/frontend/javascripts/controllers/player_controller.js @@ -96,7 +96,7 @@ export default class extends Controller { } collapse() { - document.querySelector('#js-sidebar').classList.remove('show'); + document.querySelector('#js-sidebar').classList.remove('c-sidebar--show'); document.body.classList.remove('noscroll'); } diff --git a/app/frontend/stylesheets/application.css b/app/frontend/stylesheets/application.css index a93bf7f7..604d9607 100644 --- a/app/frontend/stylesheets/application.css +++ b/app/frontend/stylesheets/application.css @@ -2,6 +2,10 @@ @import 'settings/theme.css'; @import 'settings/media_query.css'; +@import 'tools/grid.css'; +@import 'tools/spacing.css'; +@import 'tools/display.css'; + @import 'generic/normalize.css'; @import 'generic/reset.css'; @import 'generic/box_sizing.css'; @@ -11,7 +15,7 @@ @import 'objects/animations.css'; @import 'objects/grid.css'; -@import 'objects/layout.css'; +@import 'objects/flex.css'; @import 'components/form.css'; @import 'components/logo.css'; @@ -35,9 +39,10 @@ @import 'components/playlist.css'; @import 'components/player.css'; @import 'components/songs.css'; +@import 'components/sidebar.css'; @import 'utilities/display.css'; -@import 'utilities/flex.css'; @import 'utilities/spacing.css'; @import 'utilities/sizing.css'; @import 'utilities/helper.css'; +@import 'utilities/overflow.css'; diff --git a/app/frontend/stylesheets/components/card.css b/app/frontend/stylesheets/components/card.css index c5d750f5..774ee92e 100644 --- a/app/frontend/stylesheets/components/card.css +++ b/app/frontend/stylesheets/components/card.css @@ -1,11 +1,10 @@ .cards { - display: flex; - flex-wrap: wrap; margin: auto; } .cards__item { margin: 0 15px 50px; + width: 150px; } .cards__item__body { @@ -29,6 +28,7 @@ margin-right: 15px; } +/* @media (--extra-wide) { .cards { max-width: 1260px; @@ -121,3 +121,4 @@ margin-bottom: 30px; } } +*/ diff --git a/app/frontend/stylesheets/components/flash.css b/app/frontend/stylesheets/components/flash.css index 916e56ee..b7e428f6 100644 --- a/app/frontend/stylesheets/components/flash.css +++ b/app/frontend/stylesheets/components/flash.css @@ -17,12 +17,6 @@ font-size: 14px; text-align: center; border-radius: var(--flash-border-radius); - animation-duration: 0.25s; - animation-name: fadeInDown; -} - -.flash__body--close { - animation-name: fadeOutUp; } .flash__body--error { diff --git a/app/frontend/stylesheets/components/loader.css b/app/frontend/stylesheets/components/loader.css index 68f61554..ce6ee1df 100644 --- a/app/frontend/stylesheets/components/loader.css +++ b/app/frontend/stylesheets/components/loader.css @@ -4,7 +4,6 @@ border-radius: 50%; width: 40px; height: 40px; - animation: spin 0.9s linear infinite; } .loader--small { diff --git a/app/frontend/stylesheets/components/sidebar.css b/app/frontend/stylesheets/components/sidebar.css new file mode 100644 index 00000000..c610da8d --- /dev/null +++ b/app/frontend/stylesheets/components/sidebar.css @@ -0,0 +1,53 @@ +.c-sidebar { + width: 360px; + background: var(--sidebar-bg-color); +} + +@media (--extra-wide) { + .c-sidebar { + width: 380px; + } +} + +@media (--wide) { + .c-sidebar { + width: 370px; + } +} + +@media (--large) { + .c-sidebar { + width: 350px; + } +} + +@media (--medium) { + .c-sidebar { + width: 340px; + } +} + +@media (--small) { + .c-sidebar { + width: 330px; + } +} + +@media (--extra-small) { + .c-sidebar { + position: fixed; + bottom: 0; + z-index: -1; + height: 100%; + width: 100%; + visibility: hidden; + opacity: 0; + } + + .c-sidebar--show { + z-index: 100; + visibility: visible; + height: 100%; + opacity: 1; + } +} diff --git a/app/frontend/stylesheets/objects/animations.css b/app/frontend/stylesheets/objects/animations.css index 51d77227..eca39bc5 100644 --- a/app/frontend/stylesheets/objects/animations.css +++ b/app/frontend/stylesheets/objects/animations.css @@ -25,3 +25,17 @@ 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } + +.o-animation-fadeInDown { + animation-duration: 0.25s; + animation-name: fadeInDown; +} + +.o-animation-fadeOutUp { + animation-duration: 0.25s; + animation-name: fadeOutUp; +} + +.o-animation-spin { + animation: spin 0.9s linear infinite; +} diff --git a/app/frontend/stylesheets/objects/flex.css b/app/frontend/stylesheets/objects/flex.css new file mode 100644 index 00000000..3285b2f2 --- /dev/null +++ b/app/frontend/stylesheets/objects/flex.css @@ -0,0 +1,100 @@ +.o-flex { + display: flex !important; +} + +.o-flex > .o-flex__item { + display: block; + appearance: none; +} + +.o-flex-inline { + display: inline-flex; +} + +.o-flex--column { + flex-direction: column; +} + +.o-flex--row-reverse { + flex-direction: row-reverse; +} + +.o-flex--column-reverse { + flex-direction: column-reverse; +} + +.o-flex--justify-start { + justify-content: flex-start; +} + +.o-flex--justify-end { + justify-content: flex-end; +} + +.o-flex--justify-center { + justify-content: center; +} + +.o-flex--justify-between { + justify-content: space-between; +} + +.o-flex--justify-around { + justify-content: space-around; +} + +.o-flex--align-start { + align-items: flex-start; +} + +.o-flex--align-end { + align-items: flex-end; +} + +.o-flex--align-center { + align-items: center; +} + +.o-flex--align-baseline { + align-items: baseline; +} + +.o-flex--align-stretch { + align-items: stretch; +} + +.o-flex__item--align-start { + align-self: flex-start; +} + +.o-flex__item--align-end { + align-self: flex-end; +} + +.o-flex__item--align-center { + align-self: center; +} + +.o-flex__item--align-baseline { + align-self: baseline; +} + +.o-flex__item--align-stretch { + align-self: stretch; +} + +.o-flex__item--shrink-0 { + flex-shrink: 0; +} + +.o-flex__item--shrink-1 { + flex-shrink: 1; +} + +.o-flex__item--grow-0 { + flex-grow: 0; +} + +.o-flex__item--grow-1 { + flex-grow: 1; +} diff --git a/app/frontend/stylesheets/objects/grid.css b/app/frontend/stylesheets/objects/grid.css index e69de29b..a6f72587 100644 --- a/app/frontend/stylesheets/objects/grid.css +++ b/app/frontend/stylesheets/objects/grid.css @@ -0,0 +1,66 @@ +/* Base on Raster grid subsystem (rsms.me/raster) */ + +.o-grid { + display: grid !important; + --grid-tc: repeat(4, 1fr); + grid-template-columns: var(--grid-tc); + --grid-cs: 1; /* column start */ + --grid-ce: -1 /* column end */ +} + +/* o-cell -- cell or column */ +.o-grid > .o-grid__item { + display: block; + appearance: none; + overflow: hidden +} + +.o-grid--justify-items-center { + justify-items: center; +} + +.o-grid--align-items-center { + align-items: center; +} + +.o-grid__item--justify-end { + justify-self: end; +} + +@mixin grid; + +@media (--extra-wide) { + @mixin grid -extra-wide; +} + +@media (--wide) { + @mixin grid -wide; +} + +@media (--extra-large) { + @mixin grid -extra-large; +} + +@media (--large) { + @mixin grid -large; +} + +@media (--medium) { + @mixin grid -medium; +} + +@media (--small) { + @mixin grid -small; +} + +@media (--extra-small) { + @mixin grid -extra-small; +} + +@media (--narrow) { + @mixin grid -narrow; +} + +@media (--extra-narrow) { + @mixin grid -extra-narrow; +} diff --git a/app/frontend/stylesheets/objects/layout.css b/app/frontend/stylesheets/objects/layout.css deleted file mode 100644 index 16cd7510..00000000 --- a/app/frontend/stylesheets/objects/layout.css +++ /dev/null @@ -1,199 +0,0 @@ -.layout { - display: flex; -} - -.layout__main { - display: flex; - flex-direction: column; - width: 100%; - min-height: 100vh; -} - -.layout__sidebar { - position: fixed; - left: 0; - top: 0; - bottom: 0; - background: var(--layout-sidebar-bg-color); - display: flex; - flex-direction: column; - transition: 0.2s; -} - -.layout__sidebar.show { - z-index: 100; - visibility: visible; - height: 100%; - opacity: 1; -} - -.layout__main__header { - position: sticky; - top: 0; - background: var(--layout-header-bg-color); - z-index: 10; - border-bottom: 1px solid var(--layout-header-border-color); -} - -.layout__main__content { - height: 100%; - margin: 25px 60px 35px; -} - -.layout__main__footer { - position: fixed; - bottom: 0; - width: 100%; -} - -.layout__nav-bar { - padding-top: 15px; - max-width: 350px; - margin: auto; -} - -.layout__search-bar { - padding: 20px; -} - -.layout__search-bar .input { - width: 350px; -} - -.layout__sidebar .input { - background: var(--layout-sidebar-input-bg-color); -} - -.layout__sidebar .input input { - background: var(--layout-sidebar-input-bg-color); -} - -@media (--extra-wide) { - .layout__sidebar { - width: 380px; - } - - .layout__main { - margin-left: 380px; - } -} - -@media (--wide) { - .layout__sidebar { - width: 370px; - } - - .layout__main { - margin-left: 370px; - } -} - -@media (--extra-large) { - .layout__sidebar { - width: 360px; - } - - .layout__main { - margin-left: 360px; - } -} - -@media (--large) { - .layout__sidebar { - width: 350px; - } - - .layout__main { - margin-left: 350px; - } - - .layout__main__content { - margin-left: 30px; - margin-right: 30px; - } -} - -@media (--medium) { - .layout__sidebar { - width: 340px; - } - - .layout__main { - margin-left: 340px; - } - - .layout__main__content { - margin-left: 25px; - margin-right: 25px; - } -} - -@media (--small) { - .layout__sidebar { - width: 330px; - } - - .layout__main { - margin-left: 330px; - } - - .layout__main__content { - margin-left: 20px; - margin-right: 20px; - } -} - -@media (--extra-small) { - .layout__sidebar { - position: fixed; - bottom: 0; - z-index: -1; - height: 100%; - width: 100%; - visibility: hidden; - opacity: 0; - } - - .layout__main { - margin-left: 0; - } - - .layout__main__footer { - display: block !important; - } - - .layout__main__content { - margin-left: 10px; - margin-right: 10px; - margin-bottom: 70px; - } -} - -@media (--narrow) { - .layout__search-bar { - padding: 15px 10px; - } - - .layout__search-bar .input { - width: 260px; - } - - .layout__nav-bar { - max-width: 340px; - padding-top: 6px; - } -} - -@media (--extra-narrow) { - .layout__search-bar .input { - width: 220px; - } - - .layout__search-bar .input input { - width: 75%; - } - - .layout__nav-bar { - max-width: 300px; - } -} diff --git a/app/frontend/stylesheets/settings/global.css b/app/frontend/stylesheets/settings/global.css index ff8fcaf9..bf60b866 100644 --- a/app/frontend/stylesheets/settings/global.css +++ b/app/frontend/stylesheets/settings/global.css @@ -7,6 +7,14 @@ --sans-serif-fonts: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Fira Sans", "Droid Sans", "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Hiragino Sans GB W3", "Microsoft YaHei", "Wenquanyi Micro Hei", sans-serif; --monospace-fonts: 'Menlo', 'Monaco', 'Consolas', "Courier New", monospace; + /* Spacing */ + --spacing-tiny: 6px; + --spacing-narrow: 12px; + --spacing-small: 18px; + --spacing-medium: 24px; + --spacing-large: 36px; + --spacing-wide: 48px; + /* Border radius */ --border-radius-md: 4px; --border-radius-sm: 2px; diff --git a/app/frontend/stylesheets/settings/theme.css b/app/frontend/stylesheets/settings/theme.css index 1caab683..de767840 100644 --- a/app/frontend/stylesheets/settings/theme.css +++ b/app/frontend/stylesheets/settings/theme.css @@ -27,11 +27,13 @@ html { --body-color: var(--black); /* Layout */ - --layout-sidebar-bg-color: var(--grey-lightest); --layout-sidebar-input-bg-color: var(--grey-light); --layout-header-bg-color: var(--white); --layout-header-border-color: var(--grey-lighter); + /* Sidebar */ + --sidebar-bg-color: var(--grey-lightest); + /* Progress bar */ --progress-bar-bg-color: var(--purple); @@ -134,11 +136,14 @@ html[data-color-scheme='dark'] { --body-color: var(--white); /* Layout */ - --layout-sidebar-bg-color: var(--black); --layout-sidebar-input-bg-color: var(--black-lighter); --layout-header-bg-color: var(--black-light); --layout-header-border-color: var(--black-dark); + /* Sidebar */ + --sidebar-bg-color: var(--black); + + /* Progress bar */ --progress-bar-bg-color: var(--purple); diff --git a/app/frontend/stylesheets/tools/display.css b/app/frontend/stylesheets/tools/display.css new file mode 100644 index 00000000..f516b94a --- /dev/null +++ b/app/frontend/stylesheets/tools/display.css @@ -0,0 +1,9 @@ +@define-mixin display $responsivePostfix { + .u-display-none$(responsivePostfix) { + display: none !important; + } + + .u-display-block$(responsivePostfix) { + display: block !important; + } +} diff --git a/app/frontend/stylesheets/tools/grid.css b/app/frontend/stylesheets/tools/grid.css new file mode 100644 index 00000000..948af74c --- /dev/null +++ b/app/frontend/stylesheets/tools/grid.css @@ -0,0 +1,92 @@ +@define-mixin grid $responsivePostfix { + .o-grid[cols$(responsivePostfix)="1"] { --grid-tc: repeat(1, 1fr) } + .o-grid[cols$(responsivePostfix)="2"] { --grid-tc: repeat(2, 1fr) } + .o-grid[cols$(responsivePostfix)="3"] { --grid-tc: repeat(3, 1fr) } + .o-grid[cols$(responsivePostfix)="4"] { --grid-tc: repeat(4, 1fr) } + .o-grid[cols$(responsivePostfix)="5"] { --grid-tc: repeat(5, 1fr) } + .o-grid[cols$(responsivePostfix)="6"] { --grid-tc: repeat(6, 1fr) } + .o-grid[cols$(responsivePostfix)="7"] { --grid-tc: repeat(7, 1fr) } + .o-grid[cols$(responsivePostfix)="8"] { --grid-tc: repeat(8, 1fr) } + + /* span=start... */ + .o-grid > .o-grid__item[span$(responsivePostfix)^="1"] { --grid-cs: 1 } + .o-grid > .o-grid__item[span$(responsivePostfix)^="2"] { --grid-cs: 2 } + .o-grid > .o-grid__item[span$(responsivePostfix)^="3"] { --grid-cs: 3 } + .o-grid > .o-grid__item[span$(responsivePostfix)^="4"] { --grid-cs: 4 } + .o-grid > .o-grid__item[span$(responsivePostfix)^="5"] { --grid-cs: 5 } + .o-grid > .o-grid__item[span$(responsivePostfix)^="6"] { --grid-cs: 6 } + .o-grid > .o-grid__item[span$(responsivePostfix)^="7"] { --grid-cs: 7 } + .o-grid > .o-grid__item[span$(responsivePostfix)^="8"] { --grid-cs: 8 } + + /* span=...+width, span=...-end */ + .o-grid > .o-grid__item[span$(responsivePostfix)$="+1"], + .o-grid > .o-grid__item[span$(responsivePostfix)="1"] { + --grid-ce: 1 + } + + .o-grid > .o-grid__item[span$(responsivePostfix)$="+2"], + .o-grid > .o-grid__item[span$(responsivePostfix)$="-1"], + .o-grid > .o-grid__item[span$(responsivePostfix)="2"] { + --grid-ce: 2 + } + + .o-grid > .o-grid__item[span$(responsivePostfix)$="+3"], + .o-grid > .o-grid__item[span$(responsivePostfix)$="-2"], + .o-grid > .o-grid__item[span$(responsivePostfix)="3"] { + --grid-ce: 3 + } + + .o-grid > .o-grid__item[span$(responsivePostfix)$="+4"], + .o-grid > .o-grid__item[span$(responsivePostfix)$="-3"], + .o-grid > .o-grid__item[span$(responsivePostfix)="4"] { + --grid-ce: 4 + } + + .o-grid > .o-grid__item[span$(responsivePostfix)$="+5"], + .o-grid > .o-grid__item[span$(responsivePostfix)$="-4"], + .o-grid > .o-grid__item[span$(responsivePostfix)="5"] { + --grid-ce: 5 + } + + .o-grid > .o-grid__item[span$(responsivePostfix)$="+6"], + .o-grid > .o-grid__item[span$(responsivePostfix)$="-5"], + .o-grid > .o-grid__item[span$(responsivePostfix)="6"] { + --grid-ce: 6 + } + + .o-grid > .o-grid__item[span$(responsivePostfix)$="+7"], + .o-grid > .o-grid__item[span$(responsivePostfix)$="-6"], + .o-grid > .o-grid__item[span$(responsivePostfix)="7"] { + --grid-ce: 7 + } + + .o-grid > .o-grid__item[span$(responsivePostfix)$="+8"], + .o-grid > .o-grid__item[span$(responsivePostfix)$="-7"], + .o-grid > .o-grid__item[span$(responsivePostfix)="8"] { + --grid-ce: 8 + } + + .o-grid > .o-grid__item[span$(responsivePostfix)$="-8"] { + --grid-ce: 9 + } + + /* connect vars */ + .o-grid > .o-grid__item[span$(responsivePostfix)] { + grid-column-end: span var(--grid-ce) + } + + .o-grid > .o-grid__item[span$(responsivePostfix)*="+"], + .o-grid > .o-grid__item[span$(responsivePostfix)*="-"], + .o-grid > .o-grid__item[span$(responsivePostfix)*=".."] { + grid-column-start: var(--grid-cs) + } + + .o-grid > .o-grid__item[span$(responsivePostfix)*="-"], + .o-grid > .o-grid__item[span$(responsivePostfix)*=".."] { + grid-column-end: var(--grid-ce) + } + + .o-grid > .o-grid__item[span$(responsivePostfix)="row"] { + grid-column: 1 / -1 + } +} diff --git a/app/frontend/stylesheets/tools/spacing.css b/app/frontend/stylesheets/tools/spacing.css new file mode 100644 index 00000000..99fee98d --- /dev/null +++ b/app/frontend/stylesheets/tools/spacing.css @@ -0,0 +1,61 @@ +@define-mixin spacing $name, $size { + .u-m-$(name) { + margin: $size !important; + } + + .u-mt-$(name) { + margin-top: $size !important; + } + + .u-mb-$(name) { + margin-bottom: $size !important; + } + + .u-ml-$(name) { + margin-left: $size !important; + } + + .u-mr-$(name) { + margin-right: $size !important; + } + + .u-mx-$(name) { + margin-left: $size !important; + margin-right: $size !important; + } + + .u-my-$(name) { + margin-top: $size !important; + margin-bottom: $size !important; + } + + .u-p-$(name) { + padding: $size !important; + } + + .u-pt-$(name) { + padding-top: $size !important; + } + + .u-pb-$(name) { + padding-bottom: $size !important; + } + + .u-pl-$(name) { + padding-left: $size !important; + } + + .u-pr-$(name) { + padding-right: $size !important; + } + + .u-px-$(name) { + padding-left: $size !important; + padding-right: $size !important; + } + + .u-py-$(name) { + padding-top: $size !important; + padding-bottom: $size !important; + } +} diff --git a/app/frontend/stylesheets/utilities/display.css b/app/frontend/stylesheets/utilities/display.css index ebdeb829..d3f3138c 100644 --- a/app/frontend/stylesheets/utilities/display.css +++ b/app/frontend/stylesheets/utilities/display.css @@ -1,3 +1,41 @@ +@mixin display; + +@media (--extra-wide) { + @mixin display \@extra-wide; +} + +@media (--wide) { + @mixin display \@wide; +} + +@media (--extra-large) { + @mixin display \@extra-large; +} + +@media (--large) { + @mixin display \@large; +} + +@media (--medium) { + @mixin display \@medium; +} + +@media (--small) { + @mixin display \@small; +} + +@media (--extra-small) { + @mixin display \@extra-small; +} + +@media (--narrow) { + @mixin display \@narrow; +} + +@media (--extra-narrow) { + @mixin display \@extra-narrow; +} + .display__full-page-center { height: 100vh; display: flex; diff --git a/app/frontend/stylesheets/utilities/flex.css b/app/frontend/stylesheets/utilities/flex.css deleted file mode 100644 index e69de29b..00000000 diff --git a/app/frontend/stylesheets/utilities/overflow.css b/app/frontend/stylesheets/utilities/overflow.css new file mode 100644 index 00000000..2ceb263d --- /dev/null +++ b/app/frontend/stylesheets/utilities/overflow.css @@ -0,0 +1,7 @@ +.u-overflow-hidden { + overflow: hidden !important; +} + +.u-overflow-auto { + overflow: auto !important; +} diff --git a/app/frontend/stylesheets/utilities/sizing.css b/app/frontend/stylesheets/utilities/sizing.css index e69de29b..05ab5b03 100644 --- a/app/frontend/stylesheets/utilities/sizing.css +++ b/app/frontend/stylesheets/utilities/sizing.css @@ -0,0 +1,19 @@ +.u-vw-100 { + width: 100vw !important; +} + +.u-vh-100 { + height: 100vh !important; +} + +.u-w-100 { + width: 100% !important; +} + +.u-h-100 { + height: 100% !important; +} + +.u-h-0 { + height: 0 !important; +} diff --git a/app/frontend/stylesheets/utilities/spacing.css b/app/frontend/stylesheets/utilities/spacing.css index e69de29b..6eb04849 100644 --- a/app/frontend/stylesheets/utilities/spacing.css +++ b/app/frontend/stylesheets/utilities/spacing.css @@ -0,0 +1,8 @@ +@mixin spacing 0, 0; +@mixin spacing tiny, var(--spacing-tiny); +@mixin spacing narrow, var(--spacing-narrow); +@mixin spacing small, var(--spacing-small); +@mixin spacing medium, var(--spacing-medium); +@mixin spacing large, var(--spacing-large); +@mixin spacing wide, var(--spacing-wide); +@mixin spacing auto, auto; diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f12628e1..2f3f2fa7 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -32,7 +32,7 @@ def image_url_for(object, size: '') def loader_tag(size: '', expand: false) size_class = size.blank? ? '' : "loader--#{size}" - raw "
" + raw "
" end def empty_alert_tag(has_icon: false) diff --git a/app/views/albums/_album.html.erb b/app/views/albums/_album.html.erb index 0966acfe..284a9f08 100644 --- a/app/views/albums/_album.html.erb +++ b/app/views/albums/_album.html.erb @@ -1,9 +1,11 @@ -
- <%= link_to album_path(album) do %> - <%= image_tag image_url_for(album), class: 'image' %> - <% end %> -
- <%= link_to album.title, album_path(album), class: 'cards__item__title text-truncate' %> -

<%= album.artist.title %>

+
+
+ <%= link_to album_path(album) do %> + <%= image_tag image_url_for(album), class: 'image' %> + <% end %> +
+ <%= link_to album.title, album_path(album), class: 'cards__item__title text-truncate' %> +

<%= album.artist.title %>

+
diff --git a/app/views/albums/index.html.erb b/app/views/albums/index.html.erb index b8a8ae39..62faafa1 100644 --- a/app/views/albums/index.html.erb +++ b/app/views/albums/index.html.erb @@ -2,7 +2,7 @@ <%= empty_alert_tag has_icon: true %> <% else %>
-
+
<%= render partial: 'album', collection: @albums, cached: true %>
diff --git a/app/views/layouts/_main.html.erb b/app/views/layouts/_main.html.erb index 15c91ef6..67a358fe 100644 --- a/app/views/layouts/_main.html.erb +++ b/app/views/layouts/_main.html.erb @@ -1,15 +1,13 @@ -
-
-
- <%= render 'shared/flash' %> -
- <%= render 'shared/search_bar' %> - <%= render 'shared/nav_bar' %> -
-
- <%= yield %> -
-
- <%= render 'shared/mini_player' %> -
-
+
+
+ <%= render 'shared/flash' %> +
+ <%= render 'shared/search_bar' %> + <%= render 'shared/nav_bar' %> +
+
+ <%= yield %> +
+
+ <%= render 'shared/mini_player' %> +
diff --git a/app/views/layouts/_sidebar.html.erb b/app/views/layouts/_sidebar.html.erb index eb1ddf05..4d2ce79d 100644 --- a/app/views/layouts/_sidebar.html.erb +++ b/app/views/layouts/_sidebar.html.erb @@ -1,4 +1,6 @@ - +
+
+ <%= render 'shared/playlist' %> +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 79d9ba7d..59f9a31d 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,9 +1,13 @@ <% content_for :body do %> -
- <%= render 'layouts/sidebar' %> - <%= render 'layouts/main' do %> - <%= yield %> - <% end %> +
+ +
+ <%= render 'layouts/main' do %> + <%= yield %> + <% end %> +
- diff --git a/app/views/shared/_playlist.html.erb b/app/views/shared/_playlist.html.erb index 671dbf73..33c41ec1 100644 --- a/app/views/shared/_playlist.html.erb +++ b/app/views/shared/_playlist.html.erb @@ -1,11 +1,9 @@ -
+
<%= render 'playlists/nav' %>
-
-
-
-
+
+
diff --git a/app/views/shared/_search_bar.html.erb b/app/views/shared/_search_bar.html.erb index a8b99904..55c1824c 100644 --- a/app/views/shared/_search_bar.html.erb +++ b/app/views/shared/_search_bar.html.erb @@ -1,7 +1,4 @@ -