UI: Footer nav fixes

- moves footer nav to the header on iPads
- disables scrolling events for iPads
- removes footer nav entirely on Chrome PWAs
- toggles DiscourseHub iOS app status bar styling (dark/light) when opening/closing lightboxes and modals
This commit is contained in:
Penar Musaraj 2019-04-15 15:25:40 -04:00
parent fca3044b10
commit de10bd7fb4
9 changed files with 90 additions and 46 deletions

View File

@ -22,6 +22,7 @@ export default Ember.Component.extend({
this._super(...arguments);
this.appEvents.off("modal-body:flash", this, "_flash");
this.appEvents.off("modal-body:clearFlash", this, "_clearFlash");
this.appEvents.trigger("modal:body-dismissed");
},
_afterFirstRender() {

View File

@ -2,6 +2,8 @@ import MountWidget from "discourse/components/mount-widget";
import MobileScrollDirection from "discourse/mixins/mobile-scroll-direction";
import Scrolling from "discourse/mixins/scrolling";
import { observes } from "ember-addons/ember-computed-decorators";
import { isiPad } from "discourse/lib/utilities";
import { isAppWebview, postRNWebviewMessage } from "discourse/lib/utilities";
const MOBILE_SCROLL_DIRECTION_CHECK_THROTTLE = 150;
@ -28,22 +30,40 @@ const FooterNavComponent = MountWidget.extend(
didInsertElement() {
this._super(...arguments);
this.bindScrolling({ name: "footer-nav" });
$(window).on("resize.footer-nav-on-scroll", () => this.scrolled());
this.appEvents.on("page:changed", this, "_routeChanged");
this.appEvents.on("composer:opened", this, "_composerOpened");
this.appEvents.on("composer:closed", this, "_composerClosed");
$("body").addClass("with-footer-nav");
if (isAppWebview()) {
this.appEvents.on("modal:body-shown", this, "_modalOn");
this.appEvents.on("modal:body-dismissed", this, "_modalOff");
}
if (isiPad()) {
$("body").addClass("footer-nav-ipad");
} else {
this.bindScrolling({ name: "footer-nav" });
$(window).on("resize.footer-nav-on-scroll", () => this.scrolled());
this.appEvents.on("composer:opened", this, "_composerOpened");
this.appEvents.on("composer:closed", this, "_composerClosed");
}
},
willDestroyElement() {
this._super(...arguments);
this.unbindScrolling("footer-nav");
$(window).unbind("resize.footer-nav-on-scroll");
this.appEvents.off("page:changed", this, "_routeChanged");
this.appEvents.off("composer:opened", this, "_composerOpened");
this.appEvents.off("composer:closed", this, "_composerClosed");
$("body").removeClass("with-footer-nav");
if (isAppWebview()) {
this.appEvents.off("modal:body-shown", this, "_modalOn");
this.appEvents.off("modal:body-removed", this, "_modalOff");
}
if (isiPad()) {
$("body").removeClass("footer-nav-ipad");
} else {
this.unbindScrolling("footer-nav");
$(window).unbind("resize.footer-nav-on-scroll");
this.appEvents.off("composer:opened", this, "_composerOpened");
this.appEvents.off("composer:closed", this, "_composerClosed");
}
},
// The user has scrolled the window, or it is finished rendering and ready for processing.
@ -105,6 +125,17 @@ const FooterNavComponent = MountWidget.extend(
this.set("scrollEventDisabled", false);
},
_modalOn() {
postRNWebviewMessage(
"headerBg",
$(".modal-backdrop").css("background-color")
);
},
_modalOff() {
postRNWebviewMessage("headerBg", $(".d-header").css("background-color"));
},
goBack() {
this.set("currentRouteIndex", this.get("currentRouteIndex") - 1);
this.backForwardClicked = true;

View File

@ -1,5 +1,5 @@
import computed from "ember-addons/ember-computed-decorators";
import { isAppWebview, isiOSPWA, isChromePWA } from "discourse/lib/utilities";
import { isAppWebview, isiOSPWA } from "discourse/lib/utilities";
export default Ember.Controller.extend({
showTop: true,
@ -21,10 +21,6 @@ export default Ember.Controller.extend({
@computed
showFooterNav() {
return (
isAppWebview() ||
isiOSPWA() ||
(!this.site.isMobileDevice && isChromePWA())
);
return isAppWebview() || isiOSPWA();
}
});

View File

@ -1,5 +1,6 @@
import Mobile from "discourse/lib/mobile";
import { setResolverOption } from "discourse-common/resolver";
import { isAppWebview, postRNWebviewMessage } from "discourse/lib/utilities";
// Initializes the `Mobile` helper object.
export default {
@ -15,11 +16,11 @@ export default {
setResolverOption("mobileView", Mobile.mobileView);
if (window.ReactNativeWebView) {
if (isAppWebview()) {
Ember.run.later(() => {
let headerBg = $(".d-header").css("background-color");
window.ReactNativeWebView.postMessage(
JSON.stringify({ headerBg: headerBg })
postRNWebviewMessage(
"headerBg",
$(".d-header").css("background-color")
);
}, 500);
}

View File

@ -1,6 +1,7 @@
import loadScript from "discourse/lib/load-script";
import { escapeExpression } from "discourse/lib/utilities";
import { renderIcon } from "discourse-common/lib/icon-library";
import { isAppWebview, postRNWebviewMessage } from "discourse/lib/utilities";
export default function($elem) {
if (!$elem) {
@ -35,10 +36,23 @@ export default function($elem) {
wrap.hasClass("mfp-force-scrollbars") ? "none" : maxHeight
);
});
if (isAppWebview()) {
postRNWebviewMessage(
"headerBg",
$(".mfp-bg").css("background-color")
);
}
},
beforeClose() {
this.wrap.off("click.pinhandler");
this.wrap.removeClass("mfp-force-scrollbars");
if (isAppWebview()) {
postRNWebviewMessage(
"headerBg",
$(".d-header").css("background-color")
);
}
}
},

View File

@ -654,12 +654,10 @@ export function isAppWebview() {
return window.ReactNativeWebView !== undefined;
}
export function isChromePWA() {
// Watch out: this doesn't distinguish between mobile or desktop PWAs
return (
window.matchMedia("(display-mode: standalone)").matches &&
navigator.userAgent.match(/(Chrome)/g)
);
export function postRNWebviewMessage(prop, value) {
if (window.ReactNativeWebView !== undefined) {
window.ReactNativeWebView.postMessage(JSON.stringify({ [prop]: value }));
}
}
// This prevents a mini racer crash

View File

@ -1,5 +1,5 @@
import { createWidget } from "discourse/widgets/widget";
import { isAppWebview, isChromePWA } from "discourse/lib/utilities";
import { isAppWebview, postRNWebviewMessage } from "discourse/lib/utilities";
createWidget("footer-nav", {
tagName: "div.footer-nav-widget",
@ -43,29 +43,14 @@ createWidget("footer-nav", {
);
}
if (isChromePWA()) {
buttons.push(
this.attach("flat-button", {
action: "refresh",
icon: "sync",
className: "btn-large"
})
);
}
return buttons;
},
dismiss() {
window.ReactNativeWebView.postMessage(JSON.stringify({ dismiss: true }));
postRNWebviewMessage("dismiss", true);
},
share() {
window.ReactNativeWebView.postMessage(
JSON.stringify({ shareUrl: window.location.href })
);
},
refresh() {
window.location.reload();
postRNWebviewMessage("shareUrl", window.location.href);
}
});

View File

@ -5,7 +5,10 @@
$footer-nav-height: 55px;
body.footer-nav-visible {
padding-bottom: $footer-nav-height + 15;
#main-outlet {
padding-bottom: $footer-nav-height + 15;
}
#topic-progress-wrapper,
#reply-control.draft {
bottom: $footer-nav-height;
@ -48,8 +51,22 @@ body.footer-nav-visible {
}
@supports (-webkit-backdrop-filter: blur(10px)) {
.footer-nav {
body:not(.footer-nav-ipad) .footer-nav {
background-color: rgba($header_background, 0.7);
-webkit-backdrop-filter: blur(20px);
}
}
body.footer-nav-ipad {
padding-top: $footer-nav-height;
.footer-nav {
bottom: auto;
top: 0px;
background-color: $header_background;
z-index: z("ipad-header-nav");
}
&.docked .d-header {
margin-top: $footer-nav-height;
}
}

View File

@ -81,6 +81,7 @@ $z-layers: (
),
"fullscreen": 1150,
"mobile-composer": 1100,
"ipad-header-nav": 1020,
"header": 1000,
"footer-nav": 900,
"tooltip": 600,