Remove :runtime_banner feature flag (#13662)
* Removes :runtime_banner feature flag + repositioning * Switch to https://udl.forem.com + fix spec * Fix URL specs * Adds data_update_script to remove feature flag * Fix banner overlay on reactions for small screens + iPad max width * Append -only to Runtime Filter CSS * Add import to fix assets:precompile * Implement design update * Apply suggestions from code review Co-authored-by: Lisa Sy <lisasyis@gmail.com> * Add ; * Trigger Travis Co-authored-by: Lisa Sy <lisasyis@gmail.com>
This commit is contained in:
parent
1862eb5cde
commit
7845423bb9
12 changed files with 135 additions and 65 deletions
|
|
@ -1,4 +1,5 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="24" height="24" rx="3" fill="#D55D5E"/>
|
||||
<path d="M16.499 4.741H7.5a.501.501 0 0 0-.5.502V6.74c0 .277.225.501.501.501H16.5a.501.501 0 0 0 .5-.501V5.243a.501.501 0 0 0-.501-.502zm0 4.839H7.5a.501.501 0 0 0-.501.501v1.498c0 .276.225.501.501.501h9a.501.501 0 0 0 .501-.501V10.08a.501.501 0 0 0-.501-.501zM7.47 14a.47.47 0 0 0-.47.469v4.062a.47.47 0 0 0 .47.469h1.562a.468.468 0 0 0 .468-.469v-4.062A.47.47 0 0 0 9.032 14H7.47z" fill="#F6CBF7"/>
|
||||
<svg width="32" height="31" viewBox="0 0 32 31" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.44 23.363a.5.5 0 0 1 .59.286c.712 1.893 2.765 2.915 4.713 2.393 1.938-.553 3.206-2.465 2.876-4.46a.474.474 0 0 1 .368-.543l1.628-.437a.508.508 0 0 1 .607.35l.008.032c.642 3.416-1.444 6.743-4.778 7.705-3.352.898-6.813-.909-7.933-4.196a.488.488 0 0 1 .31-.63l.032-.009 1.579-.491z" fill="#E9F0E8"/>
|
||||
<path d="M12.828 11.415a.5.5 0 0 1-.59-.287c-.713-1.893-2.766-2.915-4.713-2.393-1.971.562-3.206 2.465-2.877 4.461a.474.474 0 0 1-.367.543l-1.628.436a.508.508 0 0 1-.607-.35l-.009-.032c-.642-3.416 1.444-6.742 4.779-7.704 3.352-.898 6.812.908 7.933 4.196a.488.488 0 0 1-.31.63l-.032.008-1.58.492z" fill="#4CFCA7"/>
|
||||
<path d="m22.142 8.509-1.691.453a.508.508 0 0 1-.607-.35l-.692-2.582a.508.508 0 0 1 .35-.607l1.724-.462a.508.508 0 0 0 .35-.606l-.435-1.626a.486.486 0 0 0-.607-.35l-4.269 1.178a.508.508 0 0 0-.35.606l.563 2.105.692 2.582.692 2.582.026.096L19.81 18.7c.068.255.32.427.575.359l1.596-.428a.508.508 0 0 0 .35-.607l-1.597-5.961c-.051-.192.042-.353.234-.405l1.884-.504a.508.508 0 0 0 .35-.607l-.435-1.626c-.086-.319-.37-.482-.625-.413zm2.155-.133a.526.526 0 0 1 .255-.581c.746-.405 1.157-1.301.934-2.13-.222-.83-.993-1.408-1.834-1.354a.463.463 0 0 1-.502-.344l-.436-1.626c-.068-.255.095-.538.342-.638l.064-.017a4.412 4.412 0 0 1 4.92 3.295c.59 2.2-.511 4.476-2.605 5.345a.513.513 0 0 1-.654-.27l-.017-.063-.467-1.617z" fill="#FBC1F5"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 565 B After Width: | Height: | Size: 1.4 KiB |
|
|
@ -56,7 +56,7 @@ function initializeRuntimeBanner() {
|
|||
// Constants - they will become dynamic (configurable by creators) in upcoming releases
|
||||
const FOREM_IOS_SCHEME = 'com.forem.app';
|
||||
const FOREM_APP_STORE_URL =
|
||||
'https://apps.apple.com/us/app/dev-community/id1439094790';
|
||||
'https://apps.apple.com/us/app/forem/id1536933197';
|
||||
const FOREM_GOOGLE_PLAY_URL =
|
||||
'https://play.google.com/store/apps/details?id=to.dev.dev_android';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
@import 'variables';
|
||||
@import '_mixins';
|
||||
@import 'config/import';
|
||||
|
||||
.runtime-banner {
|
||||
display: flex;
|
||||
|
|
@ -7,20 +8,56 @@
|
|||
left: var(--su-4);
|
||||
right: var(--su-4);
|
||||
position: fixed;
|
||||
bottom: calc(var(--su-9) + env(safe-area-inset-bottom));
|
||||
bottom: calc(var(--su-2) + env(safe-area-inset-bottom));
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
padding: var(--su-1);
|
||||
max-width: calc(100% - var(--su-4) * 2);
|
||||
padding: var(--su-3);
|
||||
max-width: calc(min(100% - var(--su-4) * 2, 750px));
|
||||
z-index: var(--z-popover);
|
||||
border-radius: var(--radius);
|
||||
background: var(--snackbar-bg);
|
||||
background: #012026;
|
||||
color: var(--snackbar-color);
|
||||
font-size: var(--fs-s);
|
||||
|
||||
:any-link {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
a {
|
||||
svg {
|
||||
border: 1px solid #ffffff;
|
||||
box-sizing: border-box;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
div > span:first-child {
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
color: #ffffff;
|
||||
margin-bottom: var(--su-1);
|
||||
}
|
||||
|
||||
div > span:last-child {
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
color: #ffffff;
|
||||
opacity: 0.65;
|
||||
}
|
||||
}
|
||||
|
||||
// Close button
|
||||
button > svg {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
// Larger devices (i.e. iPad) display the reactions to the left instead of the
|
||||
// bottom of the screen. Because of this we only need to move the banner higher
|
||||
// up to avoid blocking the reaction buttons when size is <= $breakpoint-m
|
||||
@media (max-width: $breakpoint-m) {
|
||||
div[data-current-page='stories-show'] .runtime-banner {
|
||||
bottom: calc(var(--su-9) + env(safe-area-inset-bottom));
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-deep-link-banner {
|
||||
|
|
|
|||
|
|
@ -8,89 +8,89 @@
|
|||
// More thorough context can be found in: https://github.com/forem/rfcs/pull/27
|
||||
|
||||
// Elements with all of these classes are not visible by default
|
||||
.ForemWebView,
|
||||
.ForemWebView-iOS,
|
||||
.ForemWebView-Android,
|
||||
.PWA,
|
||||
.PWA-iOS,
|
||||
.PWA-Android,
|
||||
.PWA-Windows,
|
||||
.PWA-Linux,
|
||||
.PWA-macOS,
|
||||
.Browser,
|
||||
.Browser-iOS,
|
||||
.Browser-Android,
|
||||
.Browser-macOS,
|
||||
.Browser-Windows,
|
||||
.Browser-Linux {
|
||||
.ForemWebView-only,
|
||||
.ForemWebView-iOS-only,
|
||||
.ForemWebView-Android-only,
|
||||
.PWA-only,
|
||||
.PWA-iOS-only,
|
||||
.PWA-Android-only,
|
||||
.PWA-Windows-only,
|
||||
.PWA-Linux-only,
|
||||
.PWA-macOS-only,
|
||||
.Browser-only,
|
||||
.Browser-iOS-only,
|
||||
.Browser-Android-only,
|
||||
.Browser-macOS-only,
|
||||
.Browser-Windows-only,
|
||||
.Browser-Linux-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Elements with class 'ForemWebView' should be visible on any attribute that
|
||||
// matches that Medium regardless of OS
|
||||
body[data-runtime='ForemWebView-iOS'] .ForemWebView,
|
||||
body[data-runtime='ForemWebView-Android'] .ForemWebView {
|
||||
body[data-runtime='ForemWebView-iOS'] .ForemWebView-only,
|
||||
body[data-runtime='ForemWebView-Android'] .ForemWebView-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
|
||||
// Elements that need to match both 'ForemWebView' Medium and OS
|
||||
body[data-runtime='ForemWebView-iOS'] .ForemWebView-iOS {
|
||||
body[data-runtime='ForemWebView-iOS'] .ForemWebView-iOS-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
body[data-runtime='ForemWebView-Android'] .ForemWebView-Android {
|
||||
body[data-runtime='ForemWebView-Android'] .ForemWebView-Android-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
|
||||
// Elements with class 'Browser' should be visible on any attribute that
|
||||
// matches that Medium regardless of OS
|
||||
body[data-runtime='Browser-Android'] .Browser,
|
||||
body[data-runtime='Browser-iOS'] .Browser,
|
||||
body[data-runtime='Browser-Linux'] .Browser,
|
||||
body[data-runtime='Browser-Windows'] .Browser,
|
||||
body[data-runtime='Browser-macOS'] .Browser {
|
||||
body[data-runtime='Browser-Android'] .Browser-only,
|
||||
body[data-runtime='Browser-iOS'] .Browser-only,
|
||||
body[data-runtime='Browser-Linux'] .Browser-only,
|
||||
body[data-runtime='Browser-Windows'] .Browser-only,
|
||||
body[data-runtime='Browser-macOS'] .Browser-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
|
||||
// Elements that need to match both 'Browser' Medium and OS
|
||||
body[data-runtime='Browser-Android'] .Browser-Android {
|
||||
body[data-runtime='Browser-Android'] .Browser-Android-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
body[data-runtime='Browser-iOS'] .Browser-iOS {
|
||||
body[data-runtime='Browser-iOS'] .Browser-iOS-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
body[data-runtime='Browser-Linux'] .Browser-Linux {
|
||||
body[data-runtime='Browser-Linux'] .Browser-Linux-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
body[data-runtime='Browser-Windows'] .Browser-Windows {
|
||||
body[data-runtime='Browser-Windows'] .Browser-Windows-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
body[data-runtime='Browser-macOS'] .Browser-macOS {
|
||||
body[data-runtime='Browser-macOS'] .Browser-macOS-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
|
||||
// Elements with class 'PWA' should be visible on any attribute that
|
||||
// matches that Medium regardless of OS
|
||||
body[data-runtime='PWA-Android'] .PWA,
|
||||
body[data-runtime='PWA-iOS'] .PWA,
|
||||
body[data-runtime='PWA-Linux'] .PWA,
|
||||
body[data-runtime='PWA-Windows'] .PWA,
|
||||
body[data-runtime='PWA-macOS'] .PWA {
|
||||
body[data-runtime='PWA-Android'] .PWA-only,
|
||||
body[data-runtime='PWA-iOS'] .PWA-only,
|
||||
body[data-runtime='PWA-Linux'] .PWA-only,
|
||||
body[data-runtime='PWA-Windows'] .PWA-only,
|
||||
body[data-runtime='PWA-macOS'] .PWA-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
|
||||
// Elements that need to match both 'PWA' Medium and OS
|
||||
body[data-runtime='PWA-Android'] .PWA-Android {
|
||||
body[data-runtime='PWA-Android'] .PWA-Android-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
body[data-runtime='PWA-iOS'] .PWA-iOS {
|
||||
body[data-runtime='PWA-iOS'] .PWA-iOS-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
body[data-runtime='PWA-Linux'] .PWA-Linux {
|
||||
body[data-runtime='PWA-Linux'] .PWA-Linux-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
body[data-runtime='PWA-Windows'] .PWA-Windows {
|
||||
body[data-runtime='PWA-Windows'] .PWA-Windows-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
body[data-runtime='PWA-macOS'] .PWA-macOS {
|
||||
body[data-runtime='PWA-macOS'] .PWA-macOS-only {
|
||||
display: var(--runtime-display, block);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ module URL
|
|||
# @param path [String] the target path to deep link
|
||||
def self.deep_link(path)
|
||||
target_path = CGI.escape(url("/r/mobile?deep_link=#{path}"))
|
||||
"https://forem-udl-server.herokuapp.com/?r=#{target_path}"
|
||||
"https://udl.forem.com/?r=#{target_path}"
|
||||
end
|
||||
|
||||
def self.organization(organization)
|
||||
|
|
|
|||
|
|
@ -104,19 +104,20 @@
|
|||
</div>
|
||||
<% end %>
|
||||
<%= yield %>
|
||||
<% if FeatureFlag.enabled?(:runtime_banner) || ENV['E2E'] == 'true' %>
|
||||
<div class="Browser-iOS">
|
||||
<div class="runtime-banner">
|
||||
<a href="<%= URL.deep_link(request.path) %>" target="_blank" class="flex items-center flex-1">
|
||||
<%= inline_svg_tag("logo-forem-app.svg", aria_hidden: true, class: "crayons-icon crayons-icon--default", width: 32, height: 32) %>
|
||||
<span class="ml-2">Open with the Forem app...</span>
|
||||
</a>
|
||||
<button type="button" class="runtime-banner__dismiss crayons-btn crayons-btn--ghost crayons-btn--icon crayons-btn--inverted crayons-btn--s pl-2">
|
||||
<%= inline_svg_tag("x.svg", aria: true, class: "crayons-icon", title: "Dismiss banner: Open with the Forem app") %>
|
||||
</button>
|
||||
</div>
|
||||
<div class="Browser-iOS-only">
|
||||
<div class="runtime-banner">
|
||||
<a href="<%= URL.deep_link(request.path) %>" target="_blank" class="flex items-center flex-1">
|
||||
<%= inline_svg_tag("logo-forem-app.svg", aria_hidden: true, class: "crayons-icon crayons-icon--default", width: 32, height: 32) %>
|
||||
<div class="flex flex-col pl-3">
|
||||
<span class="">Forem</span>
|
||||
<span class="">Open with the Forem app</span>
|
||||
</div>
|
||||
</a>
|
||||
<button type="button" class="runtime-banner__dismiss crayons-btn crayons-btn--ghost crayons-btn--icon crayons-btn--inverted crayons-btn--s">
|
||||
<%= inline_svg_tag("x.svg", aria: true, class: "crayons-icon", title: "Dismiss banner: Open with the Forem app") %>
|
||||
</button>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% unless internal_navigation? %>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
module DataUpdateScripts
|
||||
class RemoveRuntimeBannerFeatureFlag
|
||||
def run
|
||||
FeatureFlag.remove(:runtime_banner)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
require "rails_helper"
|
||||
require Rails.root.join(
|
||||
"lib/data_update_scripts/20210506052235_remove_runtime_banner_feature_flag.rb",
|
||||
)
|
||||
|
||||
describe DataUpdateScripts::RemoveRuntimeBannerFeatureFlag do
|
||||
it "removes the :runtime_banner flag" do
|
||||
FeatureFlag.enable(:runtime_banner)
|
||||
|
||||
described_class.new.run
|
||||
|
||||
expect(FeatureFlag.exist?(:runtime_banner)).to be(false)
|
||||
end
|
||||
|
||||
it "works if the flag is not available" do
|
||||
described_class.new.run
|
||||
|
||||
expect(FeatureFlag.exist?(:runtime_banner)).to be(false)
|
||||
end
|
||||
end
|
||||
|
|
@ -105,11 +105,11 @@ RSpec.describe URL, type: :lib do
|
|||
|
||||
describe ".deep_link" do
|
||||
it "returns the correct URL for the root path" do
|
||||
expect(described_class.deep_link("/")).to eq("https://forem-udl-server.herokuapp.com/?r=https%3A%2F%2Fdev.to%2Fr%2Fmobile%3Fdeep_link%3D%2F")
|
||||
expect(described_class.deep_link("/")).to eq("https://udl.forem.com/?r=https%3A%2F%2Fdev.to%2Fr%2Fmobile%3Fdeep_link%3D%2F")
|
||||
end
|
||||
|
||||
it "returns the correct URL for an explicit path" do
|
||||
expect(described_class.deep_link("/sloan")).to eq("https://forem-udl-server.herokuapp.com/?r=https%3A%2F%2Fdev.to%2Fr%2Fmobile%3Fdeep_link%3D%2Fsloan")
|
||||
expect(described_class.deep_link("/sloan")).to eq("https://udl.forem.com/?r=https%3A%2F%2Fdev.to%2Fr%2Fmobile%3Fdeep_link%3D%2Fsloan")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,13 @@ RSpec.describe "ChatChannels", type: :request do
|
|||
|
||||
it "have no active channel" do
|
||||
expect(response).not_to(redirect_to(connect_path(invite_channel.slug)))
|
||||
expect(response.body).not_to include(invite_channel.slug)
|
||||
# The slug will be rendered by the mobile runtime banner because the
|
||||
# request is made directly to "/connect/#{invite_channel.slug}", that's
|
||||
# why we can't simply check that the slug isn't included in
|
||||
# `response.body`. We can check using a regex to make sure the channel
|
||||
# doesn't exist within the chat (after chat DOM element appears but also
|
||||
# before the runtime banner starts).
|
||||
expect(response.body).not_to match(/<div id="chat".*#{invite_channel.slug}.*<div class="runtime-banner"/)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,6 @@ RSpec.describe "Registrations", type: :request do
|
|||
context "with the creator_onboarding feature flag" do
|
||||
before do
|
||||
allow(FeatureFlag).to receive(:enabled?).with(:creator_onboarding).and_return(true)
|
||||
allow(FeatureFlag).to receive(:enabled?).with(:runtime_banner).and_return(false)
|
||||
allow(Settings::General).to receive(:waiting_on_first_user).and_return(true)
|
||||
allow(Settings::UserExperience).to receive(:public).and_return(false)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ RSpec.describe "User edits their profile", type: :system do
|
|||
describe "editing admin created profile fields" do
|
||||
before do
|
||||
allow(FeatureFlag).to receive(:enabled?).with(:profile_admin).and_return(true)
|
||||
allow(FeatureFlag).to receive(:enabled?).with(:runtime_banner).and_return(false)
|
||||
Profile.refresh_attributes!
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue