From 8c586c4567c1e70d9629399948dac6768522c750 Mon Sep 17 00:00:00 2001 From: danielgrippi Date: Mon, 19 Sep 2011 23:40:18 -0700 Subject: [PATCH] added html5 boilerplate meta tags to mobile; stripped functionality to add back --- app/controllers/likes_controller.rb | 5 +- app/controllers/status_messages_controller.rb | 23 +- app/views/aspects/index.mobile.haml | 11 +- app/views/comments/_comment.mobile.haml | 11 +- app/views/layouts/application.mobile.haml | 86 +--- app/views/people/show.mobile.haml | 6 +- app/views/posts/show.mobile.haml | 26 +- app/views/reshares/_reshare.mobile.haml | 1 - app/views/shared/_footer.mobile.haml | 16 +- app/views/shared/_publisher.mobile.haml | 62 +-- app/views/shared/_stream_element.mobile.haml | 50 ++- .../status_messages/_status_message.html.haml | 19 + .../_status_message.mobile.haml | 7 + app/views/status_messages/new.mobile.haml | 5 + config/assets.yml | 13 +- public/images/icons/comment_mobile_grey.png | Bin 0 -> 770 bytes public/images/icons/heart_mobile_grey.png | Bin 0 -> 1317 bytes public/images/icons/heart_mobile_red.png | Bin 0 -> 1320 bytes public/images/icons/pencil_mobile_grey.png | Bin 0 -> 1316 bytes public/javascripts/custom-mobile-scripting.js | 38 ++ public/stylesheets/sass/mobile.sass | 253 +++++++----- public/stylesheets/sass/mobile.scss | 382 ++++++++++++++++++ .../vendor/html5-boilerplate-mobile.css | 315 +++++++++++++++ 23 files changed, 1034 insertions(+), 295 deletions(-) create mode 100644 app/views/status_messages/_status_message.html.haml create mode 100644 app/views/status_messages/_status_message.mobile.haml create mode 100644 app/views/status_messages/new.mobile.haml create mode 100644 public/images/icons/comment_mobile_grey.png create mode 100644 public/images/icons/heart_mobile_grey.png create mode 100644 public/images/icons/heart_mobile_red.png create mode 100644 public/images/icons/pencil_mobile_grey.png create mode 100644 public/stylesheets/sass/mobile.scss create mode 100644 public/stylesheets/vendor/html5-boilerplate-mobile.css diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb index 1d647adb8..233e1dc2c 100644 --- a/app/controllers/likes_controller.rb +++ b/app/controllers/likes_controller.rb @@ -21,6 +21,7 @@ class LikesController < ApplicationController format.js { render 'likes/update', :status => 201 } format.html { render :nothing => true, :status => 201 } format.mobile { redirect_to post_path(@like.post_id) } + format.json { render :nothing => true, :status => 201 } end else render :nothing => true, :status => 422 @@ -34,13 +35,15 @@ class LikesController < ApplicationController if @like = Like.where(:id => params[:id], :author_id => current_user.person.id).first current_user.retract(@like) respond_to do |format| - format.all { } + format.any { } format.js { render 'likes/update' } + format.json { render :nothing => true, :status => :ok} end else respond_to do |format| format.mobile { redirect_to :back } format.js { render :nothing => true, :status => 403 } + format.json { render :nothing => true, :status => 403} end end end diff --git a/app/controllers/status_messages_controller.rb b/app/controllers/status_messages_controller.rb index d10d3f593..c4f0ab3a4 100644 --- a/app/controllers/status_messages_controller.rb +++ b/app/controllers/status_messages_controller.rb @@ -11,18 +11,21 @@ class StatusMessagesController < ApplicationController # Called when a user clicks "Mention" on a profile page # @option [Integer] person_id The id of the person to be mentioned def new - @person = Person.find(params[:person_id]) - @aspect = :profile - @contact = current_user.contact_for(@person) - @aspects_with_person = [] - if @contact - @aspects_with_person = @contact.aspects - @aspect_ids = @aspects_with_person.map(&:id) - @contacts_of_contact = @contact.contacts + if params[:person_id] && @person = Person.where(params[:person_id]).first + @aspect = :profile + @contact = current_user.contact_for(@person) + @aspects_with_person = [] + if @contact + @aspects_with_person = @contact.aspects + @aspect_ids = @aspects_with_person.map(&:id) + @contacts_of_contact = @contact.contacts - render :layout => nil + render :layout => nil + end else - redirect_to :back + @aspect = :all + @aspects = current_user.aspects + @aspect_ids = @aspects.map{ |a| a.id } end end diff --git a/app/views/aspects/index.mobile.haml b/app/views/aspects/index.mobile.haml index 4f13e4ea2..0d7ebde86 100644 --- a/app/views/aspects/index.mobile.haml +++ b/app/views/aspects/index.mobile.haml @@ -2,19 +2,18 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -#aspect_header +%h2 - if @stream.for_all_aspects? = t('all_aspects') - else = @stream.aspect - = link_to t('.post_a_message'), '#publisher_page', :id => 'publisher_button' - + = link_to 'Post', new_status_message_path, :id => 'publisher_button' #main_stream.stream = render 'shared/stream', :posts => @stream.posts -if @stream.posts.length > 0 #pagination %a.more-link.paginate{:href => next_page_path} - %h2= t("more") -- content_for :subpages do - = render 'shared/publisher', :aspect_ids => @stream.aspect_ids, :selected_aspects => @stream.aspects, :aspect => @stream.aspect + %h1 + = t("more") + diff --git a/app/views/comments/_comment.mobile.haml b/app/views/comments/_comment.mobile.haml index a7adc99a1..84e31ea81 100644 --- a/app/views/comments/_comment.mobile.haml +++ b/app/views/comments/_comment.mobile.haml @@ -4,16 +4,17 @@ %li.comment{:data=>{:guid=>comment.id}, :class => ("hidden" if(defined? hidden))} .right - %span.time - = comment.created_at ? time_ago_in_words(comment.created_at) : time_ago_in_words(Time.now) -#.controls -#= link_to image_tag('deletelabel.png'), comment, :confirm => t('are_you_sure'), :method => :delete, :class => "delete comment_delete", :title => t('delete') - - = person_image_link(comment.author) .content .from + = person_image_link(comment.author) = person_link(comment.author) - %div{ :class => direction_for(comment.text) } + .info + %span.time.timeago{:datetime => comment.created_at} + = comment.created_at ? time_ago_in_words(comment.created_at) : time_ago_in_words(Time.now) + + %div{:class => direction_for(comment.text)} = markdownify(comment, :youtube_maps => comment[:youtube_titles]) diff --git a/app/views/layouts/application.mobile.haml b/app/views/layouts/application.mobile.haml index b247e7758..f75d1b4fd 100644 --- a/app/views/layouts/application.mobile.haml +++ b/app/views/layouts/application.mobile.haml @@ -9,16 +9,19 @@ DIASPORA* %meta{"http-equiv"=>"Content-Type", :content=>"text/html; charset=utf-8"}/ - = include_javascripts :mobile - %meta{'name' =>'viewport', 'content' => "width=device-width, minimum-scale=1, maximum-scale=1"} + %meta{:name =>'viewport', :content => "width=device-width, minimum-scale=1, maximum-scale=1"} + %meta{:name => "HandheldFriendly", :content => "True"} + %meta{:name => "MobileOptimized", :content => "320"} + %meta{'http-equiv' => "cleartype", :content => 'on'} + = include_javascripts :mobile -if current_user :javascript Diaspora.I18n.loadLocale(#{get_javascript_strings_for(current_user.language).to_json}, "#{current_user.language}"); =include_stylesheets :mobile = csrf_meta_tag - + - if rtl? = include_stylesheets :rtl, :media => 'all' @@ -26,15 +29,10 @@ -if AppConfig[:google_a_site] :javascript - var _gaq = _gaq || []; - _gaq.push(['_setAccount', '#{AppConfig[:google_a_site]}']); - _gaq.push(['_trackPageview']); - - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); + var _gaq=[["_setAccount","#{AppConfig[:google_a_site]}"],["_trackPageview"]]; + (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.async=1; + g.src=("https:"==location.protocol?"//ssl":"//www")+".google-analytics.com/ga.js"; + s.parentNode.insertBefore(g,s)}(document,"script")); -if AppConfig[:piwik_id] :javascript @@ -49,64 +47,18 @@ %body - #content{:data => {:role => 'page', :theme => 'c'}} - #header - - if current_user - .right - = link_to(image_tag('icons/list_white.png'), '#menu', :id => "menu_button") - = link_to(image_tag('icons/search_white.png'), people_path) - = link_to(image_tag('white@2x.png', :height => 22, :width => 136, :id => 'header_title'), aspects_path) + %header + /- if current_user + / /= link_to(image_tag('icons/list_white.png'), '#menu', :id => "menu_button") + / /= link_to(image_tag('icons/search_white.png'), people_path, :class => "right") + = link_to(image_tag('white@2x.png', :height => 22, :width => 136, :id => 'header_title'), aspects_path) + + - if flash.present? %p - flash.each do |name, msg| = content_tag :div, msg, :id => "flash_#{name}" - = yield + = yield - = render :partial =>'shared/footer' if user_signed_in? - - -if current_user - #menu{:data => {:role => 'page', :theme => 'c'}} - #header - .right - = link_to(image_tag('icons/search_white.png'), people_path) - = link_to(image_tag('white.png'), aspects_path) - - #content{:data => {:role => 'content'}} - - %h2 - = current_user.name - - %ul{:data => {:role => 'listview', :inset => 'true'}} - %li - = link_to t('notifications.index.notifications'), notifications_path - .ui-li-count - = @notification_count - %li - = link_to t('conversations.index.message_inbox'), conversations_path - .ui-li-count - = @unread_message_count - - - - - if AppConfig[:open_invitations] - %h4 - = t('shared.invitations.invite_your_friends') - %ul{:data => {:role => 'listview', :inset => 'true'}} - %li - = link_to t('.by_email'), new_user_invitation_path - - %h4 - = t('.your_aspects') - - %ul{:data => {:role => 'listview', :inset => 'true'}} - %li - = link_to t('all_aspects'), aspects_path - - for aspect in all_aspects - %li - = link_to aspect, aspects_path('a_ids[]' => aspect.id) - - - = render :partial =>'shared/footer' - - = yield :subpages + /= render :partial =>'shared/footer' if user_signed_in? diff --git a/app/views/people/show.mobile.haml b/app/views/people/show.mobile.haml index 05948258f..29f6b259c 100644 --- a/app/views/people/show.mobile.haml +++ b/app/views/people/show.mobile.haml @@ -10,10 +10,10 @@ = person_image_tag @person, :thumb_medium .content - %h3 + %h2 = @person.name - .description - = @person.diaspora_handle + - if user_signed_in? && current_user.person == @person + = link_to t('people.profile_sidebar.edit_my_profile'), edit_profile_path, :class => 'button creation' - if user_signed_in? && !(@contact.persisted? || current_user.person == @person) - if @incoming_request diff --git a/app/views/posts/show.mobile.haml b/app/views/posts/show.mobile.haml index 50a06979f..2d6d0fa58 100644 --- a/app/views/posts/show.mobile.haml +++ b/app/views/posts/show.mobile.haml @@ -2,30 +2,8 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -#show_content{:data=>{:guid=>@post.id}} - = render 'shared/author_info', :person => @post.author, :post => @post - - - if @post.activity_streams? - = image_tag @post.image_url - - elsif reshare?(@post) - = render 'reshares/reshare', :reshare => @post, :post => @post.root - - else - %p - = markdownify(@post, :youtube_maps => @post[:youtube_titles]) - - - for photo in @post.photos - = link_to (image_tag photo.url(:thumb_small), :class => 'thumb_small'), photo.url(:thumb_medium) - - .info - %span.time - = t('ago', :time => time_ago_in_words(@post.created_at)) - - %br - - if user_signed_in? - - if current_user.owns? @post - = link_to t('delete'), post_path(@post), :confirm => t('are_you_sure'), :method => :delete - - else - = link_to t('hide'), post_visibility_path(:id => "42", :post_id => @post.id), :confirm => t('are_you_sure'), :method => :put, :remote => true += render :partial => 'shared/stream_element', + :locals => {:post => @post, :commenting_disabled => defined?(@commenting_disabled)} .stream.show{:data=>{:guid=>@post.id}} = render "comments/comments", :post => @post, :comments => @post.comments, :comments_expanded => true diff --git a/app/views/reshares/_reshare.mobile.haml b/app/views/reshares/_reshare.mobile.haml index 796689b6f..22d620165 100644 --- a/app/views/reshares/_reshare.mobile.haml +++ b/app/views/reshares/_reshare.mobile.haml @@ -8,7 +8,6 @@ .content .from = person_link(post.author, :class => "hovercardable") - - if post.activity_streams? = link_to image_tag(post.image_url, 'data-small-photo' => post.image_url, 'data-full-photo' => post.image_url, :class => 'stream-photo'), post.object_url, :class => "stream-photo-link" diff --git a/app/views/shared/_footer.mobile.haml b/app/views/shared/_footer.mobile.haml index 579751148..2f8a2badb 100644 --- a/app/views/shared/_footer.mobile.haml +++ b/app/views/shared/_footer.mobile.haml @@ -1,12 +1,4 @@ -#footer{:data => {:role => 'footer'}} - - .inset - %b= t('.your_aspects') - %div{:data => {:role => 'controlgroup', :type => 'horizontal'}} - - for aspect in all_aspects - = link_to aspect, aspects_path('a_ids[]' => aspect.id) - | - .ui-bar - = link_to t('.logged_in_as', :name => current_user.name), current_user.person - = link_to t('layouts.application.toggle'), toggle_mobile_path - = link_to t('layouts.header.logout'), destroy_user_session_path +%footer + = link_to t('.logged_in_as', :name => current_user.name), current_user.person + = link_to t('layouts.application.toggle'), toggle_mobile_path + = link_to t('layouts.header.logout'), destroy_user_session_path diff --git a/app/views/shared/_publisher.mobile.haml b/app/views/shared/_publisher.mobile.haml index 752816c6a..ffffa05a9 100644 --- a/app/views/shared/_publisher.mobile.haml +++ b/app/views/shared/_publisher.mobile.haml @@ -2,52 +2,26 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -:javascript - $(document).ready(function(){ - $("#status_message_text").bind("focus", function(){ - $("#publisher fieldset:first").removeClass('hidden'); - }); - }); += form_for StatusMessage.new, {:data => {:ajax => false}} do |status| + = status.text_area :text, :placeholder => t('.whats_on_your_mind'), :style => "width:300px", :rows => 4 -#publisher_page{:data => {:role => 'page', :theme => 'c'}} - #header - - if current_user - .left - = link_to(image_tag('icons/list_white.png'), '/aspects/#menu', :id => "menu_button") + - for aspect_id in aspect_ids + = hidden_field_tag 'aspect_ids[]', aspect_id.to_s - .right - = link_to(image_tag('icons/search_white.png'), people_path) - = link_to(image_tag('white.png'), aspects_path) - %div{:data => {:role => 'content'}} - = form_for StatusMessage.new, {:data => {:ajax => false}} do |status| - #publisher_text - = t('.whats_on_your_mind') + %fieldset + - unless aspect == :all + %input{:type => 'checkbox', :name => 'status_message[public]', :id => 'public', :class => 'custom', :value => 'true'} + %label{:for => 'public'} + = t('.make_public') + - unless current_user.services.empty? + %div{:data => {:role => 'fieldcontain'}} + %label{:for => 'services', :class => 'select'} + choose services - = status.text_area :text + - current_user.services.each do |service| + %input{:type => 'checkbox', :name => "services[]", :id => "#{service.provider}", :class => 'custom', :value => "#{service.provider}"} + %label{:for => "#{service.provider}"} + = "#{service.provider}" - - for aspect_id in aspect_ids - = hidden_field_tag 'aspect_ids[]', aspect_id.to_s - - - %fieldset - - unless aspect_ids - %input{:type => 'checkbox', :name => 'status_message[public]', :id => 'public', :class => 'custom', :value => 'true'} - %label{:for => 'public'} - = t('.make_public') - - unless current_user.services.empty? - %div{:data => {:role => 'fieldcontain'}} - %label{:for => 'services', :class => 'select'} - choose services - - - current_user.services.each do |service| - %input{:type => 'checkbox', :name => "services[]", :id => "#{service.provider}", :class => 'custom', :value => "#{service.provider}"} - %label{:for => "#{service.provider}"} - = "#{service.provider}" - -#%select{:name => 'services', :multiple => 'multiple', :id => "services"} - -#%option - -#Choose a Service - -#- current_user.services.each do |service| - -#%option{:value => "#{service.provider}"} - -#= service.provider.titleize - = status.submit t('.share'), 'data-theme' => 'c' + = status.submit t('.share') diff --git a/app/views/shared/_stream_element.mobile.haml b/app/views/shared/_stream_element.mobile.haml index 0462a8e50..4967542b7 100644 --- a/app/views/shared/_stream_element.mobile.haml +++ b/app/views/shared/_stream_element.mobile.haml @@ -3,27 +3,49 @@ -# the COPYRIGHT file. .stream_element{:data=>{:guid=>post.id}} - = person_image_link(post.author, :size => :thumb_small) + + .photo_area + - if post.is_a?(StatusMessage) && post.photos.size > 0 + - photos = post.photos + .photo_attachments + .big_stream_photo + = link_to (image_tag photos.first.url(:thumb_large), :class => "stream-photo", 'data-small-photo' => photos.first.url(:thumb_medium), 'data-full-photo' => photos.first.url), photo_path(photos.first), :class => "stream-photo-link" + - if photos.size > 1 + - if photos.size >= 8 + - for photo in photos[1..8] + = link_to (image_tag photo.url(:thumb_small), :class => 'stream-photo thumb_small', 'data-small-photo' => photo.url(:thumb_medium), 'data-full-photo' => photo.url), photo_path(photo), :class => 'stream-photo-link' + - else + - for photo in photos[1..photos.size] + = link_to (image_tag photo.url(:thumb_small), :class => 'stream-photo thumb_small', 'data-small-photo' => photo.url(:thumb_medium), 'data-full-photo' => photo.url), photo_path(photo), :class => 'stream-photo-link' + - elsif post.activity_streams? + = image_tag post.image_url + .content .from + = person_image_link(post.author, :size => :thumb_small) = person_link(post.author) + .info + %span.time{:integer => post.created_at.to_i} + = t('ago', :time => time_ago_in_words(post.created_at)) + %span.via + - if post.activity_streams? + = t('.via', :link => link_to("#{post.provider_display_name}", post.actor_url)).html_safe - - if post.activity_streams? - = image_tag post.image_url - - elsif reshare?(post) + - if reshare?(post) = render 'reshares/reshare', :reshare => post, :post => post.root - - else + - elsif post.is_a?(StatusMessage) = render 'status_messages/status_message', :post => post, :photos => post.photos - .info - %span.time{:integer => post.created_at.to_i} - = t('ago', :time => time_ago_in_words(post.created_at)) - %span.via - - if post.activity_streams? - = t('.via', :link => link_to("#{post.provider_display_name}", post.actor_url)).html_safe + .bottom_bar + .floater + /= link_to "reshare" + = link_to '', post_path(post), :class => "image_link comment_action" - = link_to "#{t('comments', :count => post.comments.length)} →", post_path(post), :class => 'comment_link right' - - if post.activity_streams? - %br + - if current_user.liked?(post) + = link_to '', '#', :class => "image_link like_action active", 'data-post-id' => post.id, 'data-like-id' => current_user.like_for(post).id + - else + = link_to '', '#', :class => "image_link like_action inactive", 'data-post-id' => post.id + + = link_to "#{t('comments', :count => post.comments.length)}", post_path(post), :class => 'comment_link' diff --git a/app/views/status_messages/_status_message.html.haml b/app/views/status_messages/_status_message.html.haml new file mode 100644 index 000000000..ec8343327 --- /dev/null +++ b/app/views/status_messages/_status_message.html.haml @@ -0,0 +1,19 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + + +- if photos.size > 0 + .photo_attachments + .big_stream_photo + = link_to (image_tag photos.first.url(:scaled_full), :class => "stream-photo", 'data-small-photo' => photos.first.url(:thumb_medium), 'data-full-photo' => photos.first.url), photo_path(photos.first), :class => "stream-photo-link" + - if photos.size > 1 + - if photos.size >= 8 + - for photo in photos[1..8] + = link_to (image_tag photo.url(:thumb_small), :class => 'stream-photo thumb_small', 'data-small-photo' => photo.url(:thumb_medium), 'data-full-photo' => photo.url), photo_path(photo), :class => 'stream-photo-link' + - else + - for photo in photos[1..photos.size] + = link_to (image_tag photo.url(:thumb_small), :class => 'stream-photo thumb_small', 'data-small-photo' => photo.url(:thumb_medium), 'data-full-photo' => photo.url), photo_path(photo), :class => 'stream-photo-link' + +%div{:class => direction_for(post.text)} + != markdownify(post, :youtube_maps => post[:youtube_titles]) diff --git a/app/views/status_messages/_status_message.mobile.haml b/app/views/status_messages/_status_message.mobile.haml new file mode 100644 index 000000000..2fa37d692 --- /dev/null +++ b/app/views/status_messages/_status_message.mobile.haml @@ -0,0 +1,7 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + + +%div{:class => direction_for(post.text)} + != markdownify(post, :youtube_maps => post[:youtube_titles]) diff --git a/app/views/status_messages/new.mobile.haml b/app/views/status_messages/new.mobile.haml new file mode 100644 index 000000000..91786f0ec --- /dev/null +++ b/app/views/status_messages/new.mobile.haml @@ -0,0 +1,5 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + += render :partial => 'shared/publisher', :locals => {:aspect => @aspects.first, :for_all_aspects => true, :aspect_ids => @aspect_ids, :selected_aspects => @aspects} diff --git a/config/assets.yml b/config/assets.yml index 28a860bff..3282968eb 100644 --- a/config/assets.yml +++ b/config/assets.yml @@ -44,12 +44,12 @@ javascripts: mobile: - public/javascripts/vendor/jquery162.min.js - public/javascripts/custom-mobile-scripting.js - - public/javascripts/vendor/jquery.mobile-1.0b2.min.js - - public/javascripts/jquery.infinitescroll-custom.js + #- public/javascripts/vendor/jquery.mobile-1.0b2.min.js + #- public/javascripts/jquery.infinitescroll-custom.js - public/javascripts/diaspora.js - public/javascripts/helpers/i18n.js - - public/javascripts/widgets/infinite-scroll.js - - public/javascripts/rails.js + #- public/javascripts/widgets/infinite-scroll.js + #- public/javascripts/rails.js mailchimp: - public/javascripts/vendor/mailchimp/jquery.form.js @@ -89,6 +89,7 @@ stylesheets: - public/stylesheets/rtl.css mobile: - - public/stylesheets/vendor/jquery.mobile-1.0b2.min.css + #- public/stylesheets/vendor/jquery.mobile-1.0b2.min.css + - public/stylesheets/vendor/html5-boilerplate-mobile.css - public/stylesheets/mobile.css - + diff --git a/public/images/icons/comment_mobile_grey.png b/public/images/icons/comment_mobile_grey.png new file mode 100644 index 0000000000000000000000000000000000000000..9053269aa3013a88e75045fffc1314835d93bb7b GIT binary patch literal 770 zcmeAS@N?(olHy`uVBq!ia0vp^sX!dg!3HE{&vj=4Db50q$YKTtZeb8+WSBKa0w^e1 z;u=vBoS#-wo>-L1;Fyx1l&avFo0y&&l$w}QS$HzlhJk^p-_yl0q~g|_x&48U0tDKd zc|F*xL_L^iE@oNZ?9QIfextEOK>Grp-XyjqObeM;FqFTawo~9qzoCls=UU^L7Flk8 zYxmXuK2o`Ud))fPMk$eIJr5KLWtOMTdp%dnRprhpU;U|tu20lAPw;+f)4k-m*OHDN zh3$q)TEZq`mY$lLO34c5wLjW)wA0nX1uWOg*M4~9u+mGg$js#Wl_ER4pf|$vPpmbo z6Ma5QS2Ju=NlVP6(A+g!Do;({l=Ra}Ajo?9wBPUMC@oGoBXjAFO!CkF`thIo_U*Av zpJEbsY~9ixU2|nsg(I$#+&@2wo;bo$RDlyamLQ2J9i%WbU$wS3$seW z*&9t=H~c9V@86dAucId`HN<8`Lb_}I?+wb!>=dniuWj7>t~5Q9PtM}JOwsR^d*9_A zdBLpp%;Q=eMiP=E5kL$hbrK2yeB{Qvwn{WZ}KE1mSG<)5l%wO921Bj(?i zFOvVXQI-4N(}jY8E2nJgIHR?1#yndio2TaM)^2(Gb;{9l@k?f!+OH$_ZJn^qlQZ>| zanQNrcUP+KS6nJ5=X%0<`mgl&L2)h~FK#V5wt31--7w`PKVEKe61Q4w<|$dW^m11B zl)&k&6;q5X%hu@yy~?kxcYom4RTjljsFGUj^IAyOZi&K?g;Oqk^*cR#ir?Rf7dKCd xTz9!j;a~sCuTK+HPj5>6IRAXY>~cmn2Hri#Kh65*tOHEH44$rjF6*2UngBWMOA7!1 literal 0 HcmV?d00001 diff --git a/public/images/icons/heart_mobile_grey.png b/public/images/icons/heart_mobile_grey.png new file mode 100644 index 0000000000000000000000000000000000000000..9e5ce387c799b31842aaafe0aa52b505fb503d3f GIT binary patch literal 1317 zcmV+=1={+FP)|NV+;xG_Z+`y)TI2D9#fMq*y2Z0JgDp=A%s36b*sUUV52&rI62c&|mh8^dK zhm9@tm@#wD(cvQxMst1VAzSjr*VmWwf!Ej9p8mMR(KCLu!m;l6`%6U>hW#my5@7S% zr~MbMNWn>DdJOdV)#6VJJ#sx3F-f9i|4F3iiNKXK)?=v0l>>V|^qA@Ks3*7%KmOA)cBN!`1%E@P(3pQ*`lLhl0F@5a>5v2;2X&DwG{0 z1(V{EfaH(G=-#2^&)xp2@U1DcdU+)gAJBu4BBThK z<`jV_MQ{WwA%&$0zzxIUxm;l2l_SR$EOEk!y8^q=YfQ zVXJNUk}wt^Y*~?l@*9eu+g-?Q&%SK^fVchvxR*Q?UpK-O{iVE;Vk{B7i_dHEt_iW~ z@vKO}<|mWI^7+NCsLo=F;$uC zHzYaVvW-WbkIsaUQQgt*WJp0`W@kXm2AD8*0= zOkggA5F({R!~`KE7%3efCKw?>NnuP(P(p%}!jPEYghU~Q5iwB+iAD+oVxkcel@x=R zdt!v#$0Q_3^VqP#1Se2ly=+XCPn^GD8QuB=`_V3f?y4gchs zV#(W?@O2=ZP4vf~nqPqjttTAk#+Hb> b{s}MurKtU_i?V0!00000NkvXXu0mjf$vAL- literal 0 HcmV?d00001 diff --git a/public/images/icons/heart_mobile_red.png b/public/images/icons/heart_mobile_red.png new file mode 100644 index 0000000000000000000000000000000000000000..e2b5dc42b4980044bd89fdcda16985f7da83e37f GIT binary patch literal 1320 zcmV+@1=sqCP)|NVc<1i2v{@{1%U`+*N8-Q#F>42mHLIrC&AQg~w5Go+9fKb7j4#MZ|539+J zIm*K?MY3k>x##HQgGWYledi%t^4aI-r}BZnH#YPz*J(eL!qGbO`r09vjl{D33tjBi;_Ppyc*W*!7aMJ=2 zB<;5%1t*i}ap%!z3vieZa?t)qJ#IbPKLa1x*dJL;Xo@-E&hv!~4$JWSToRJof9u)) zJ6ro}D+RBvWy5&u3J|x)`l`!LAS1@m63YHjUDebg1(P5ovu^b5o;ly>Jr1%{=)Eul7Cfn@l%I_RS6-`Z@dt;|3^_M zJ4y;B#WexRSH0!WYW^x8jFO z2m{>hFH%aPcp~YD{kuwGe3gAwW5lbi+G>e9ppqOf%9A1UWvp9^dO`N zDT2B=MIcHMR3H;lh$>|xZXkv2g5+BKKniOhB@;i;$|?E%6bNCmbRQlc=V^M8C;FB6 zg9KJ)Ni3uYDS|Rm%%@o(;eQvu1jD<|C-HtqzZAa&#nNmZbIiprLGk7P{l``%gar;= z`$_>kihqJ&$L~>*galzi*8wTGdvzf`Y88w9UBkzg?i2A-t2prY0V(+8x2UB(m1LEq zh+4v`q>vO*OE{I3DMi#0NF}ADAd3&;J1=-BJ7=cq!3k(;-o=M*yZ5Rly_6KJpQqwS zr>H!`tnMjBD;4HQrmi8?gbb^GsqS-MWA%Sep1>X-=tt#*6iiA|jh$F+)jdS6(HW8w z#{7n@rr}G%SPNmxiWHRJSp3}VLT-BYW#b3D^%uasH??+lYz=4SQITwK+FW^saTL=5YyE)vY9VJoK{~w>S3JpB0-d5 zC%K}calOb|kXk-~tOV1xuE z#USRM7$Nr|32CKytl40K6DYioapJR6XQ32BG2n=a5JE^PhGIgzlnp-Wzt zN;%TYxT?%1)Cpms6hko(&TL=QynVLU$NltPD#cLD3iC|U0^kkv$BN5bS-pV3D4CyY z{>d}NlD9MA>qt0D^vAD~Ux5d$6OMCZOG-(eVU<7Fhp&P>GcfWDd=5Ah!d@wRsu@#R eP&^g?1Q-A{BqNSjK54rE0000p#3yU0KoG>xO z{%_mq-D)#L+V2XvI@E0ok#j#I5IU2!DeAW+Y^K!6=y;Lk2 zFw1!*w-Dp9nmI)o0tZZ5E}3{dPfS{>Ft@E!w7EpAE$~{GqZOy{>4TSeE?Lf~dDp#o z>3WG2V^;eEXKqi~sje`$V}?xXGfofngnQ>~F10_&*!h7$<;SX=&E7VG4Dk+4y)zzJ zR<->Es@NbHTxQB$|M{3)BMWD}<8D#-~#6BZ;?Z4C8UUUv=9*SlS-C)m-rLtqaUPU{_;Wj}YhL2cJ3lL(Qc2K`gk zYseRuhJLEj71^5Gb;+zP-}+Gb_8oU`tXI*Bm-u?4)c605=~j-8M{1VWO5`@3sMFQ{ zc6#T=?`%&G7?_8AtLCi;`*bIw?x&d9DaOQQ*55i8r-$ZzSiHa6rKP`!L*npM^JTuF ziE)eGNTwzJ_+KHq;!%?`^G?qI^MG$0#wK^Bmxk<{5qnE>%CtnWPiNnIZ@;cGRX43X z^W#5*0I9Z}3v0Y?zxMq8-Gi;8^I@G$NJx3u#Ybl!6!J5ld2hXI@3P+q80@+H*Js@J zR1eHLpkrYqb*FvP)olAfNj2^jZGp9>0aJaY@AYolcGQBa*}1TxQpazu$%IpGKb|k+ zt(%}R%^;FHRe$N_2O_!$7eyR66Rovx4VSm?v%^hphAp1C#|7J-7EOI&A}?ms#dt>i zl>eRV;+aC3ix2Xz^Sb6qrjIt%Q~Yff+8B0Tf# z&vLEy)vF#E^@nfil?+(LAEos6#0{mY3K^r@rXOn34X>Q~X|Nzi{=h~CUY`5gZgtGt zs^~G#>-ph^AYPM6tInnseU4i6{9wV(gnbIhJR;jy>E>7aEPfs+=R1x2-Yz>HjWUPi zms{tW@3^`4vxP%p|GZ8Y|NYON&3nqD9w7Bj!e>#H_U!t5GR%xiEf*|&uwzc&zxQX< z18#NB3u#~z%defy&+PSEmYHpr!ArmA_Gg*9=Jhf9Km4%w!ZnAR_5pU!G+&49KiAIq z^n+~k*`M341D*QfwL}d|m)?Twc^~B&*%