mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 17:46:05 -05:00
Stop using user agent to detect mobile devices. Use a media query and yepnope to load the appropriate css and customizations.
This commit is contained in:
parent
17110ead98
commit
ca5d4d5e54
8 changed files with 95 additions and 148 deletions
|
@ -5,30 +5,19 @@
|
||||||
@module Mobile
|
@module Mobile
|
||||||
**/
|
**/
|
||||||
Discourse.Mobile = {
|
Discourse.Mobile = {
|
||||||
isMobileDevice: false,
|
|
||||||
mobileView: false,
|
mobileView: false,
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
var $html = $('html');
|
var $html = $('html');
|
||||||
this.isMobileDevice = $html.hasClass('mobile-device');
|
|
||||||
this.mobileView = $html.hasClass('mobile-view');
|
this.mobileView = $html.hasClass('mobile-view');
|
||||||
|
|
||||||
if (localStorage && localStorage.mobileView) {
|
|
||||||
var savedValue = (localStorage.mobileView === 'true' ? true : false);
|
|
||||||
if (savedValue !== this.mobileView) {
|
|
||||||
this.reloadPage(savedValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleMobileView: function() {
|
toggleMobileView: function() {
|
||||||
if (localStorage) {
|
if (localStorage) {
|
||||||
localStorage.mobileView = !this.mobileView;
|
localStorage.mobileView = !this.mobileView;
|
||||||
}
|
}
|
||||||
this.reloadPage(!this.mobileView);
|
window.location.reload();
|
||||||
},
|
|
||||||
|
|
||||||
reloadPage: function(mobile) {
|
|
||||||
window.location.assign(window.location.pathname + '?mobile_view=' + (mobile ? '1' : '0'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,7 +26,6 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
before_filter :set_locale
|
before_filter :set_locale
|
||||||
before_filter :set_mobile_view
|
|
||||||
before_filter :inject_preview_style
|
before_filter :inject_preview_style
|
||||||
before_filter :disable_customization
|
before_filter :disable_customization
|
||||||
before_filter :block_if_maintenance_mode
|
before_filter :block_if_maintenance_mode
|
||||||
|
@ -120,10 +119,6 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_mobile_view
|
|
||||||
session[:mobile_view] = params[:mobile_view] if params.has_key?(:mobile_view)
|
|
||||||
end
|
|
||||||
|
|
||||||
def inject_preview_style
|
def inject_preview_style
|
||||||
style = request['preview-style']
|
style = request['preview-style']
|
||||||
session[:preview_style] = style if style
|
session[:preview_style] = style if style
|
||||||
|
|
|
@ -19,10 +19,6 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def html_classes
|
|
||||||
"#{mobile_view? ? 'mobile-view' : 'desktop-view'} #{mobile_device? ? 'mobile-device' : 'not-mobile-device'}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def escape_unicode(javascript)
|
def escape_unicode(javascript)
|
||||||
if javascript
|
if javascript
|
||||||
javascript = javascript.dup.force_encoding("utf-8")
|
javascript = javascript.dup.force_encoding("utf-8")
|
||||||
|
@ -115,18 +111,8 @@ module ApplicationHelper
|
||||||
"#{Discourse::base_uri}/login"
|
"#{Discourse::base_uri}/login"
|
||||||
end
|
end
|
||||||
|
|
||||||
def mobile_view?
|
def stylesheet_filenames(target=:desktop)
|
||||||
return false unless SiteSetting.enable_mobile_theme
|
[asset_path("#{target}.css"), customization_disabled? ? nil : SiteCustomization.custom_stylesheet_path(session[:preview_style], target)].compact
|
||||||
if session[:mobile_view]
|
|
||||||
session[:mobile_view] == '1'
|
|
||||||
else
|
|
||||||
mobile_device?
|
|
||||||
end
|
|
||||||
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/)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def customization_disabled?
|
def customization_disabled?
|
||||||
|
|
|
@ -83,6 +83,12 @@ class SiteCustomization < ActiveRecord::Base
|
||||||
style.stylesheet_link_tag(target).html_safe if style
|
style.stylesheet_link_tag(target).html_safe if style
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.custom_stylesheet_path(preview_style, target=:desktop)
|
||||||
|
preview_style ||= enabled_style_key
|
||||||
|
style = lookup_style(preview_style)
|
||||||
|
style.stylesheet_relative_path(target) if style
|
||||||
|
end
|
||||||
|
|
||||||
def self.custom_header(preview_style, target=:desktop)
|
def self.custom_header(preview_style, target=:desktop)
|
||||||
preview_style ||= enabled_style_key
|
preview_style ||= enabled_style_key
|
||||||
style = lookup_style(preview_style)
|
style = lookup_style(preview_style)
|
||||||
|
@ -175,14 +181,18 @@ class SiteCustomization < ActiveRecord::Base
|
||||||
return "" unless stylesheet.present?
|
return "" unless stylesheet.present?
|
||||||
return @stylesheet_link_tag if @stylesheet_link_tag
|
return @stylesheet_link_tag if @stylesheet_link_tag
|
||||||
ensure_stylesheets_on_disk!
|
ensure_stylesheets_on_disk!
|
||||||
@stylesheet_link_tag = "<link class=\"custom-css\" rel=\"stylesheet\" href=\"/#{CACHE_PATH}#{stylesheet_filename}?#{stylesheet_hash}\" type=\"text/css\" media=\"screen\">"
|
@stylesheet_link_tag = "<link class=\"custom-css\" rel=\"stylesheet\" href=\"#{stylesheet_relative_path(:desktop)}\" type=\"text/css\" media=\"screen\">"
|
||||||
end
|
end
|
||||||
|
|
||||||
def mobile_stylesheet_link_tag
|
def mobile_stylesheet_link_tag
|
||||||
return "" unless mobile_stylesheet.present?
|
return "" unless mobile_stylesheet.present?
|
||||||
return @mobile_stylesheet_link_tag if @mobile_stylesheet_link_tag
|
return @mobile_stylesheet_link_tag if @mobile_stylesheet_link_tag
|
||||||
ensure_stylesheets_on_disk!
|
ensure_stylesheets_on_disk!
|
||||||
@mobile_stylesheet_link_tag = "<link class=\"custom-css\" rel=\"stylesheet\" href=\"/#{CACHE_PATH}#{stylesheet_filename(:mobile)}?#{stylesheet_hash(:mobile)}\" type=\"text/css\" media=\"screen\">"
|
@mobile_stylesheet_link_tag = "<link class=\"custom-css\" rel=\"stylesheet\" href=\"#{stylesheet_relative_path(:mobile)}\" type=\"text/css\" media=\"screen\">"
|
||||||
|
end
|
||||||
|
|
||||||
|
def stylesheet_relative_path(target=:desktop)
|
||||||
|
"/#{CACHE_PATH}#{stylesheet_filename(target)}?#{stylesheet_hash(target)}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,42 @@
|
||||||
<%- unless SiteCustomization.override_default_style(session[:preview_style]) %>
|
<%- unless SiteCustomization.override_default_style(session[:preview_style]) %>
|
||||||
<% if mobile_view? %>
|
|
||||||
<%= stylesheet_link_tag "mobile" %>
|
<script type="text/javascript">
|
||||||
<% else %>
|
(function() {
|
||||||
<%= stylesheet_link_tag "desktop" %>
|
var h = document.getElementsByTagName('html')[0],
|
||||||
<% end %>
|
isMobileView = (localStorage && localStorage.mobileView) ? (localStorage.mobileView === 'true') :
|
||||||
|
Modernizr.mq("only screen and (max-width: 480px), only screen and (max-device-width: 480px)");
|
||||||
|
|
||||||
|
h.className += (isMobileView ? ' mobile-view' : ' desktop-view');
|
||||||
|
Modernizr.load({
|
||||||
|
test: isMobileView,
|
||||||
|
yep: <%= stylesheet_filenames(:mobile).inspect.html_safe %>,
|
||||||
|
nope: <%= stylesheet_filenames(:desktop).inspect.html_safe %>,
|
||||||
|
complete: function() {
|
||||||
|
// CSS file(s) have loaded.
|
||||||
|
$(function() {
|
||||||
|
setTimeout(function() {
|
||||||
|
// Use setTimeout to make this happen in the next event loop.
|
||||||
|
// Trying to avoid a FOUC (flash of unstyled content).
|
||||||
|
if (isMobileView) {
|
||||||
|
$('#custom-mobile-header').show();
|
||||||
|
} else {
|
||||||
|
$('#custom-desktop-header').show();
|
||||||
|
}
|
||||||
|
$('#js-app').attr('style', ''); // Show everything.
|
||||||
|
$(window).trigger('scroll.discourse-dock'); // Calc header div positions now that they're visible.
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
<%- end %>
|
<%- end %>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<%= stylesheet_link_tag "desktop" %>
|
||||||
|
</noscript>
|
||||||
|
|
||||||
<%- if staff? %>
|
<%- if staff? %>
|
||||||
<%= stylesheet_link_tag "admin"%>
|
<%= stylesheet_link_tag "admin"%>
|
||||||
<%-end%>
|
<%-end%>
|
||||||
|
|
||||||
<%- unless customization_disabled? %>
|
|
||||||
<%= SiteCustomization.custom_stylesheet(session[:preview_style], mobile_view? ? :mobile : :desktop) %>
|
|
||||||
<%- end %>
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="<%= SiteSetting.default_locale %>" class="<%= html_classes %>">
|
<html lang="<%= SiteSetting.default_locale %>">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title><%= content_for?(:title) ? yield(:title) + ' - ' + SiteSetting.title : SiteSetting.title %></title>
|
<title><%= content_for?(:title) ? yield(:title) + ' - ' + SiteSetting.title : SiteSetting.title %></title>
|
||||||
|
@ -20,48 +20,55 @@
|
||||||
<%= javascript_include_tag "admin"%>
|
<%= javascript_include_tag "admin"%>
|
||||||
<%- end %>
|
<%- end %>
|
||||||
|
|
||||||
<%= render :partial => "common/special_font_face" %>
|
|
||||||
<%= render :partial => "common/discourse_stylesheet" %>
|
<%= render :partial => "common/discourse_stylesheet" %>
|
||||||
|
<%= render :partial => "common/special_font_face" %>
|
||||||
|
|
||||||
<%= discourse_csrf_tags %>
|
<%= discourse_csrf_tags %>
|
||||||
|
|
||||||
<%= yield :head %>
|
<%= yield :head %>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body class="css-loading">
|
||||||
<!--[if IE 9]><script type="text/javascript">ie = "new";</script><![endif]-->
|
<!--[if IE 9]><script type="text/javascript">ie = "new";</script><![endif]-->
|
||||||
|
|
||||||
<%- unless customization_disabled? %>
|
<div id="js-app" style="display: none;">
|
||||||
<%= SiteCustomization.custom_header(session[:preview_style], mobile_view? ? :mobile : :desktop) %>
|
<%- unless customization_disabled? %>
|
||||||
<%- end %>
|
<div id='custom-desktop-header' style='display: none;'>
|
||||||
|
<%= SiteCustomization.custom_header(session[:preview_style], :desktop) %>
|
||||||
|
</div>
|
||||||
|
<div id='custom-mobile-header' style='display: none;'>
|
||||||
|
<%= SiteCustomization.custom_header(session[:preview_style], :mobile) %>
|
||||||
|
</div>
|
||||||
|
<%- end %>
|
||||||
|
|
||||||
<section id='main'>
|
<section id='main'>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<% unless current_user %>
|
<% unless current_user %>
|
||||||
<form id='hidden-login-form' method="post" action="<%=login_path%>" style="display: none;">
|
<form id='hidden-login-form' method="post" action="<%=login_path%>" style="display: none;">
|
||||||
<input name="username" type="text" id="signin_username">
|
<input name="username" type="text" id="signin_username">
|
||||||
<input name="password" type="password" id="signin_password">
|
<input name="password" type="password" id="signin_password">
|
||||||
<input name="redirect" type="hidden">
|
<input name="redirect" type="hidden">
|
||||||
<input type="submit" id="signin-button" value="Log In">
|
<input type="submit" id="signin-button" value="Log In">
|
||||||
</form>
|
</form>
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%- if @preloaded.present? %>
|
|
||||||
<script>
|
|
||||||
<%- @preloaded.each do |key, json| %>
|
|
||||||
PreloadStore.store("<%= key %>",<%= escape_unicode(json) %>);
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</script>
|
|
||||||
<%- end %>
|
|
||||||
|
|
||||||
<%= yield :data %>
|
<%- if @preloaded.present? %>
|
||||||
|
<script>
|
||||||
|
<%- @preloaded.each do |key, json| %>
|
||||||
|
PreloadStore.store("<%= key %>",<%= escape_unicode(json) %>);
|
||||||
|
<% end %>
|
||||||
|
</script>
|
||||||
|
<%- end %>
|
||||||
|
|
||||||
<footer id='bottom'></footer>
|
<%= yield :data %>
|
||||||
|
|
||||||
<%= render :partial => "common/discourse_javascript" %>
|
<footer id='bottom'></footer>
|
||||||
|
|
||||||
<%= render_google_analytics_code %>
|
<%= render :partial => "common/discourse_javascript" %>
|
||||||
|
|
||||||
|
<%= render_google_analytics_code %>
|
||||||
|
</div>
|
||||||
|
|
||||||
<noscript data-path="<%= request.env['PATH_INFO'] %>">
|
<noscript data-path="<%= request.env['PATH_INFO'] %>">
|
||||||
<header class="d-header">
|
<header class="d-header">
|
||||||
|
|
|
@ -11,78 +11,4 @@ describe ApplicationHelper do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "mobile_view?" do
|
|
||||||
context "enable_mobile_theme is true" do
|
|
||||||
before do
|
|
||||||
SiteSetting.stubs(:enable_mobile_theme).returns(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "is true if mobile_view is '1' in the session" do
|
|
||||||
session[:mobile_view] = '1'
|
|
||||||
helper.mobile_view?.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it "is false if mobile_view is '0' in the session" do
|
|
||||||
session[:mobile_view] = '0'
|
|
||||||
helper.mobile_view?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
context "mobile_view is not set" do
|
|
||||||
it "is false if user agent is not mobile" do
|
|
||||||
controller.request.stubs(:user_agent).returns('Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36')
|
|
||||||
helper.mobile_view?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
it "is true for iPhone" do
|
|
||||||
controller.request.stubs(:user_agent).returns('Mozilla/5.0 (iPhone; U; ru; CPU iPhone OS 4_2_1 like Mac OS X; ru) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148a Safari/6533.18.5')
|
|
||||||
helper.mobile_view?.should be_true
|
|
||||||
end
|
|
||||||
|
|
||||||
it "is false for iPad" do
|
|
||||||
controller.request.stubs(:user_agent).returns("Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3")
|
|
||||||
helper.mobile_view?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
it "is false for Nexus 10 tablet" do
|
|
||||||
controller.request.stubs(:user_agent).returns("Mozilla/5.0 (Linux; Android 4.2.1; Nexus 10 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19")
|
|
||||||
helper.mobile_view?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
it "is true for Nexus 7 tablet" do
|
|
||||||
controller.request.stubs(:user_agent).returns("Mozilla/5.0 (Linux; Android 4.1.2; Nexus 7 Build/JZ054K) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19")
|
|
||||||
helper.mobile_view?.should be_true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "enable_mobile_theme is false" do
|
|
||||||
before do
|
|
||||||
SiteSetting.stubs(:enable_mobile_theme).returns(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "is false if mobile_view is '1' in the session" do
|
|
||||||
session[:mobile_view] = '1'
|
|
||||||
helper.mobile_view?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
it "is false if mobile_view is '0' in the session" do
|
|
||||||
session[:mobile_view] = '0'
|
|
||||||
helper.mobile_view?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
context "mobile_view is not set" do
|
|
||||||
it "is false if user agent is not mobile" do
|
|
||||||
controller.request.stubs(:user_agent).returns('Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36')
|
|
||||||
helper.mobile_view?.should be_false
|
|
||||||
end
|
|
||||||
|
|
||||||
it "is false for iPhone" do
|
|
||||||
controller.request.stubs(:user_agent).returns('Mozilla/5.0 (iPhone; U; ru; CPU iPhone OS 4_2_1 like Mac OS X; ru) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148a Safari/6533.18.5')
|
|
||||||
helper.mobile_view?.should be_false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
|
|
||||||
var $buo = function() {
|
var $buo = function() {
|
||||||
|
|
||||||
var badAndroid = false, ua = null;
|
var badAndroid = false,
|
||||||
|
haveJquery = (typeof($) !== 'undefined'),
|
||||||
|
ua = null;
|
||||||
|
|
||||||
// Sometimes we have to resort to parsing the user agent string. :(
|
// Sometimes we have to resort to parsing the user agent string. :(
|
||||||
if (navigator && navigator.userAgent) {
|
if (navigator && navigator.userAgent) {
|
||||||
|
@ -53,6 +55,11 @@ var $buo = function() {
|
||||||
// shift the body down to make room for our notification div
|
// shift the body down to make room for our notification div
|
||||||
document.body.style.marginTop = (div.clientHeight) + "px";
|
document.body.style.marginTop = (div.clientHeight) + "px";
|
||||||
|
|
||||||
|
if (!haveJquery) {
|
||||||
|
var h = document.getElementsByTagName('html')[0];
|
||||||
|
h.className = h.className.replace(/(\s|^)css-loading(\s|$)/g, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$bu=$buo();
|
$bu=$buo();
|
||||||
|
|
Loading…
Reference in a new issue