diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 68b4a82d482..40a8f63d8af 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -4,6 +4,7 @@ require_dependency 'guardian' require_dependency 'unread' require_dependency 'age_words' require_dependency 'configurable_urls' +require_dependency 'mobile_detection' module ApplicationHelper include CurrentUser @@ -109,21 +110,16 @@ module ApplicationHelper end def mobile_view? - return false unless SiteSetting.enable_mobile_theme - if session[:mobile_view] - session[:mobile_view] == '1' - else - mobile_device? - end + MobileDetection.resolve_mobile_view!(request.user_agent,params,session) end def mobile_device? - # TODO: this is dumb. user agent matching is a doomed approach. a better solution is coming. - request.user_agent =~ /Mobile|webOS|Nexus 7/ and !(request.user_agent =~ /iPad/) + MobileDetection.mobile_device?(request.user_agent) end def customization_disabled? controller.class.name.split("::").first == "Admin" || session[:disable_customization] end + end diff --git a/config/initializers/99-rack-cache.rb b/config/initializers/99-anon-cache.rb similarity index 58% rename from config/initializers/99-rack-cache.rb rename to config/initializers/99-anon-cache.rb index ed2439eb14f..d2c90beee87 100644 --- a/config/initializers/99-rack-cache.rb +++ b/config/initializers/99-anon-cache.rb @@ -7,6 +7,7 @@ enabled = if Rails.configuration.respond_to?(:enable_anon_caching) end if !ENV['DISCOURSE_DISABLE_ANON_CACHE'] && enabled - Rails.configuration.middleware.insert 0, Middleware::AnonymousCache + # in an ideal world this is position 0, but mobile detection uses ... session and request and params + Rails.configuration.middleware.insert_after ActionDispatch::ParamsParser, Middleware::AnonymousCache end diff --git a/lib/middleware/anonymous_cache.rb b/lib/middleware/anonymous_cache.rb index bb1d6412423..0eb7ae65894 100644 --- a/lib/middleware/anonymous_cache.rb +++ b/lib/middleware/anonymous_cache.rb @@ -1,3 +1,5 @@ +require_dependency "mobile_detection" + module Middleware class AnonymousCache @@ -10,8 +12,19 @@ module Middleware @env = env end + def is_mobile? + @is_mobile ||= + begin + session = @env["rack.session"] + params = ActionDispatch::Request.new(@env).params + user_agent = @env["HTTP_USER_AGENT"] + + MobileDetection.resolve_mobile_view!(user_agent,params,session) ? :true : :false + end == :true + end + def cache_key - @cache_key ||= "ANON_CACHE_#{@env["HTTP_HOST"]}#{@env["REQUEST_URI"]}" + @cache_key ||= "ANON_CACHE_#{@env["HTTP_HOST"]}#{@env["REQUEST_URI"]}|m=#{is_mobile?}" end def cache_key_body diff --git a/lib/mobile_detection.rb b/lib/mobile_detection.rb new file mode 100644 index 00000000000..c06a9c24c8a --- /dev/null +++ b/lib/mobile_detection.rb @@ -0,0 +1,19 @@ +module MobileDetection + def self.mobile_device?(user_agent) + # TODO: this is dumb. user agent matching is a doomed approach. a better solution is coming. + user_agent =~ /Mobile|webOS|Nexus 7/ && !(user_agent =~ /iPad/) + end + + # we need this as a reusable chunk that is called from the cache + def self.resolve_mobile_view!(user_agent, params, session) + return false unless SiteSetting.enable_mobile_theme + + session[:mobile_view] = params[:mobile_view] if params.has_key?(:mobile_view) + + if session[:mobile_view] + session[:mobile_view] == '1' + else + mobile_device?(user_agent) + end + end +end