зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 11b5fa2ce936 (bug 1893007) for causing multiple weather related failures
This commit is contained in:
Родитель
d4d6b5f89e
Коммит
32333031ed
|
@ -166,11 +166,6 @@ for (const type of [
|
|||
"WEATHER_LOAD_ERROR",
|
||||
"WEATHER_OPEN_PROVIDER_URL",
|
||||
"WEATHER_UPDATE",
|
||||
"WEATHER_SEARCH_ACTIVE",
|
||||
"WEATHER_LOCATION_DATA_UPDATE",
|
||||
"WEATHER_QUERY_UPDATE",
|
||||
"WEATHER_LOCATION_SEARCH_UPDATE",
|
||||
"WEATHER_LOCATION_SUGGESTIONS_UPDATE",
|
||||
"WEBEXT_CLICK",
|
||||
"WEBEXT_DISMISS",
|
||||
]) {
|
||||
|
|
|
@ -105,19 +105,10 @@ export const INITIAL_STATE = {
|
|||
wallpaperList: [],
|
||||
},
|
||||
Weather: {
|
||||
// do we have the data from WeatherFeed yet?
|
||||
initialized: false,
|
||||
lastUpdated: null,
|
||||
query: "",
|
||||
suggestions: [],
|
||||
locationData: {
|
||||
city: "",
|
||||
adminArea: "",
|
||||
country: "",
|
||||
},
|
||||
// Display search input in Weather widget
|
||||
searchActive: false,
|
||||
locationSearchString: "",
|
||||
suggestedLocations: [],
|
||||
lastUpdated: null,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -875,17 +866,8 @@ function Weather(prevState = INITIAL_STATE.Weather, action) {
|
|||
...prevState,
|
||||
suggestions: action.data.suggestions,
|
||||
lastUpdated: action.data.date,
|
||||
locationData: action.data.locationData || prevState.locationData,
|
||||
initialized: true,
|
||||
};
|
||||
case at.WEATHER_SEARCH_ACTIVE:
|
||||
return { ...prevState, searchActive: action.data };
|
||||
case at.WEATHER_LOCATION_SEARCH_UPDATE:
|
||||
return { ...prevState, locationSearchString: action.data };
|
||||
case at.WEATHER_LOCATION_SUGGESTIONS_UPDATE:
|
||||
return { ...prevState, suggestedLocations: action.data };
|
||||
case at.WEATHER_LOCATION_DATA_UPDATE:
|
||||
return { ...prevState, locationData: action.data };
|
||||
default:
|
||||
return prevState;
|
||||
}
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
|
||||
|
||||
function LocationSearch({ outerClassName }) {
|
||||
// should be the location object from suggestedLocations
|
||||
const [selectedLocation, setSelectedLocation] = useState("");
|
||||
const suggestedLocations = useSelector(
|
||||
state => state.Weather.suggestedLocations
|
||||
);
|
||||
const locationSearchString = useSelector(
|
||||
state => state.Weather.locationSearchString
|
||||
);
|
||||
const [userInput, setUserInput] = useState(locationSearchString || "");
|
||||
const inputRef = useRef(null);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedLocation) {
|
||||
dispatch(
|
||||
ac.AlsoToMain({
|
||||
type: at.WEATHER_LOCATION_DATA_UPDATE,
|
||||
data: {
|
||||
city: selectedLocation.localized_name,
|
||||
adminName: selectedLocation.administrative_area,
|
||||
country: selectedLocation.country,
|
||||
},
|
||||
})
|
||||
);
|
||||
dispatch(ac.SetPref("weather.query", selectedLocation.key));
|
||||
dispatch(
|
||||
ac.BroadcastToContent({
|
||||
type: at.WEATHER_SEARCH_ACTIVE,
|
||||
data: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [selectedLocation, dispatch]);
|
||||
|
||||
// when component mounts, set focus to input
|
||||
useEffect(() => {
|
||||
inputRef?.current?.focus();
|
||||
}, [inputRef]);
|
||||
|
||||
function handleChange(event) {
|
||||
const { value } = event.target;
|
||||
setUserInput(value);
|
||||
// if the user input contains less than three characters and suggestedLocations is not an empty array,
|
||||
// reset suggestedLocations to [] so there arent incorrect items in the datalist
|
||||
if (value.length < 3 && suggestedLocations.length) {
|
||||
dispatch(
|
||||
ac.AlsoToMain({
|
||||
type: at.WEATHER_LOCATION_SUGGESTIONS_UPDATE,
|
||||
data: [],
|
||||
})
|
||||
);
|
||||
}
|
||||
// find match in suggestedLocation array
|
||||
const match = suggestedLocations?.find(({ key }) => key === value);
|
||||
if (match) {
|
||||
setSelectedLocation(match);
|
||||
setUserInput(
|
||||
`${match.localized_name}, ${match.administrative_area.localized_name}`
|
||||
);
|
||||
} else if (value.length >= 3 && !match) {
|
||||
dispatch(
|
||||
ac.AlsoToMain({
|
||||
type: at.WEATHER_LOCATION_SEARCH_UPDATE,
|
||||
data: value,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function handleCloseSearch() {
|
||||
dispatch(
|
||||
ac.BroadcastToContent({
|
||||
type: at.WEATHER_SEARCH_ACTIVE,
|
||||
data: false,
|
||||
})
|
||||
);
|
||||
setUserInput("");
|
||||
}
|
||||
|
||||
function handleKeyDown(e) {
|
||||
if (e.key === "Escape") {
|
||||
handleCloseSearch();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${outerClassName} location-search`}>
|
||||
<div className="location-input-wrapper">
|
||||
<div className="search-icon" />
|
||||
<input
|
||||
ref={inputRef}
|
||||
list="merino-location-list"
|
||||
type="text"
|
||||
placeholder="Search location"
|
||||
onChange={handleChange}
|
||||
value={userInput}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<button className="close-icon" onClick={handleCloseSearch} />
|
||||
<datalist id="merino-location-list">
|
||||
{(suggestedLocations || []).map(location => (
|
||||
<option value={location.key} key={location.key}>
|
||||
{location.localized_name},{" "}
|
||||
{location.administrative_area.localized_name}
|
||||
</option>
|
||||
))}
|
||||
</datalist>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { LocationSearch };
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import { connect } from "react-redux";
|
||||
import { LinkMenu } from "content-src/components/LinkMenu/LinkMenu";
|
||||
import { LocationSearch } from "content-src/components/Weather/LocationSearch";
|
||||
import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
|
||||
import React from "react";
|
||||
|
||||
|
@ -193,7 +192,7 @@ export class _Weather extends React.PureComponent {
|
|||
|
||||
const { showContextMenu } = this.state;
|
||||
|
||||
const { props } = this;
|
||||
const WEATHER_SUGGESTION = this.props.Weather.suggestions?.[0];
|
||||
|
||||
const {
|
||||
className,
|
||||
|
@ -201,24 +200,21 @@ export class _Weather extends React.PureComponent {
|
|||
dispatch,
|
||||
eventSource,
|
||||
shouldSendImpressionStats,
|
||||
Prefs,
|
||||
Weather,
|
||||
} = props;
|
||||
|
||||
const WEATHER_SUGGESTION = Weather.suggestions?.[0];
|
||||
} = this.props;
|
||||
const { props } = this;
|
||||
const isContextMenuOpen = this.state.activeCard === index;
|
||||
|
||||
const outerClassName = [
|
||||
"weather",
|
||||
className,
|
||||
isContextMenuOpen && !Weather.searchActive && "active",
|
||||
isContextMenuOpen && "active",
|
||||
props.placeholder && "placeholder",
|
||||
Weather.searchActive && "search",
|
||||
]
|
||||
.filter(v => v)
|
||||
.join(" ");
|
||||
|
||||
const showDetailedView = Prefs.values["weather.display"] === "detailed";
|
||||
const showDetailedView =
|
||||
this.props.Prefs.values["weather.display"] === "detailed";
|
||||
|
||||
// Note: The temperature units/display options will become secondary menu items
|
||||
const WEATHER_SOURCE_CONTEXT_MENU_OPTIONS = [
|
||||
|
@ -235,9 +231,8 @@ export class _Weather extends React.PureComponent {
|
|||
"OpenLearnMoreURL",
|
||||
];
|
||||
|
||||
if (Weather.searchActive) {
|
||||
return <LocationSearch outerClassName={outerClassName} />;
|
||||
} else if (WEATHER_SUGGESTION) {
|
||||
// Only return the widget if we have data. Otherwise, show error state
|
||||
if (WEATHER_SUGGESTION) {
|
||||
return (
|
||||
<div ref={this.setImpressionRef} className={outerClassName}>
|
||||
<div className="weatherCard">
|
||||
|
@ -266,7 +261,7 @@ export class _Weather extends React.PureComponent {
|
|||
</div>
|
||||
<div className="weatherCityRow">
|
||||
<span className="weatherCity">
|
||||
{Weather.locationData.city}
|
||||
{WEATHER_SUGGESTION.city_name}
|
||||
</span>
|
||||
</div>
|
||||
{showDetailedView ? (
|
||||
|
|
|
@ -246,7 +246,6 @@
|
|||
font-size: var(--font-size-large);
|
||||
}
|
||||
|
||||
|
||||
// Weather Symbol Icons
|
||||
.weatherIconCol {
|
||||
width: var(--size-item-large);
|
||||
|
@ -371,70 +370,3 @@
|
|||
content: url('chrome://browser/skin/weather/night-mostly-cloudy-with-flurries.svg');
|
||||
}
|
||||
}
|
||||
|
||||
.location-input-wrapper {
|
||||
background-color: light-dark(var(--color-white), var(--newtab-background-color-secondary));
|
||||
color: var(--newtab-text-primary-color);
|
||||
border-radius: var(--border-radius-medium);
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
|
||||
// Contrast fix for users who have wallpapers set
|
||||
.lightWallpaper &,
|
||||
.darkWallpaper & {
|
||||
background-color: var(--newtab-weather-background-color);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--newtab-button-static-hover-background);
|
||||
}
|
||||
|
||||
&:hover:active {
|
||||
background-color: var(--newtab-button-static-active-background);
|
||||
}
|
||||
|
||||
@media (prefers-contrast) {
|
||||
background-color: var(--background-color-box);
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
content: url('chrome://global/skin/icons/search-glass.svg');
|
||||
-moz-context-properties: fill;
|
||||
fill: light-dark(var(--color-gray-70), var(--color-gray-05));
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
inset-inline-start: 18px;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
background-image: url('chrome://global/skin/icons/close.svg');
|
||||
-moz-context-properties: fill;
|
||||
fill: light-dark(var(--color-gray-70), var(--color-gray-05));
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
inset-inline-end: 18px;
|
||||
width: var(--size-item-small);
|
||||
height: var(--size-item-small);
|
||||
appearance: none;
|
||||
border: none;
|
||||
|
||||
&:focus-visible {
|
||||
outline: 1px solid var(--focus-outline-color);
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
border-radius: var(--border-radius-medium);
|
||||
background-color: light-dark(var(--color-white), var(--newtab-background-color-secondary));
|
||||
padding-block: 8px;
|
||||
padding-inline: 30px;
|
||||
border: $border-primary;
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--focus-outline-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -308,9 +308,9 @@ export const LinkMenuOptions = {
|
|||
isEnabled ? _OpenInPrivateWindow(site) : LinkMenuOptions.EmptyItem(),
|
||||
ChangeWeatherLocation: () => ({
|
||||
id: "newtab-weather-menu-change-location",
|
||||
action: ac.BroadcastToContent({
|
||||
type: at.WEATHER_SEARCH_ACTIVE,
|
||||
data: true,
|
||||
action: ac.OnlyToMain({
|
||||
type: at.CHANGE_WEATHER_LOCATION,
|
||||
data: { url: "https://mozilla.org" },
|
||||
}),
|
||||
}),
|
||||
ChangeWeatherDisplaySimple: () => ({
|
||||
|
|
|
@ -2356,63 +2356,6 @@ main section {
|
|||
content: url("chrome://browser/skin/weather/night-mostly-cloudy-with-flurries.svg");
|
||||
}
|
||||
|
||||
.location-input-wrapper {
|
||||
background-color: light-dark(var(--color-white), var(--newtab-background-color-secondary));
|
||||
color: var(--newtab-text-primary-color);
|
||||
border-radius: var(--border-radius-medium);
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
}
|
||||
.lightWallpaper .location-input-wrapper, .darkWallpaper .location-input-wrapper {
|
||||
background-color: var(--newtab-weather-background-color);
|
||||
}
|
||||
.lightWallpaper .location-input-wrapper:hover, .darkWallpaper .location-input-wrapper:hover {
|
||||
background-color: var(--newtab-button-static-hover-background);
|
||||
}
|
||||
.lightWallpaper .location-input-wrapper:hover:active, .darkWallpaper .location-input-wrapper:hover:active {
|
||||
background-color: var(--newtab-button-static-active-background);
|
||||
}
|
||||
@media (prefers-contrast) {
|
||||
.lightWallpaper .location-input-wrapper, .darkWallpaper .location-input-wrapper {
|
||||
background-color: var(--background-color-box);
|
||||
}
|
||||
}
|
||||
.location-input-wrapper .search-icon {
|
||||
content: url("chrome://global/skin/icons/search-glass.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: light-dark(var(--color-gray-70), var(--color-gray-05));
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
inset-inline-start: 18px;
|
||||
}
|
||||
.location-input-wrapper .close-icon {
|
||||
background-image: url("chrome://global/skin/icons/close.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: light-dark(var(--color-gray-70), var(--color-gray-05));
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
inset-inline-end: 18px;
|
||||
width: var(--size-item-small);
|
||||
height: var(--size-item-small);
|
||||
appearance: none;
|
||||
border: none;
|
||||
}
|
||||
.location-input-wrapper .close-icon:focus-visible {
|
||||
outline: 1px solid var(--focus-outline-color);
|
||||
}
|
||||
.location-input-wrapper input {
|
||||
border-radius: var(--border-radius-medium);
|
||||
background-color: light-dark(var(--color-white), var(--newtab-background-color-secondary));
|
||||
padding-block: 8px;
|
||||
padding-inline: 30px;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.location-input-wrapper input:focus-visible {
|
||||
outline: 2px solid var(--focus-outline-color);
|
||||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.card-outer {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
|
|
|
@ -2360,63 +2360,6 @@ main section {
|
|||
content: url("chrome://browser/skin/weather/night-mostly-cloudy-with-flurries.svg");
|
||||
}
|
||||
|
||||
.location-input-wrapper {
|
||||
background-color: light-dark(var(--color-white), var(--newtab-background-color-secondary));
|
||||
color: var(--newtab-text-primary-color);
|
||||
border-radius: var(--border-radius-medium);
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
}
|
||||
.lightWallpaper .location-input-wrapper, .darkWallpaper .location-input-wrapper {
|
||||
background-color: var(--newtab-weather-background-color);
|
||||
}
|
||||
.lightWallpaper .location-input-wrapper:hover, .darkWallpaper .location-input-wrapper:hover {
|
||||
background-color: var(--newtab-button-static-hover-background);
|
||||
}
|
||||
.lightWallpaper .location-input-wrapper:hover:active, .darkWallpaper .location-input-wrapper:hover:active {
|
||||
background-color: var(--newtab-button-static-active-background);
|
||||
}
|
||||
@media (prefers-contrast) {
|
||||
.lightWallpaper .location-input-wrapper, .darkWallpaper .location-input-wrapper {
|
||||
background-color: var(--background-color-box);
|
||||
}
|
||||
}
|
||||
.location-input-wrapper .search-icon {
|
||||
content: url("chrome://global/skin/icons/search-glass.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: light-dark(var(--color-gray-70), var(--color-gray-05));
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
inset-inline-start: 18px;
|
||||
}
|
||||
.location-input-wrapper .close-icon {
|
||||
background-image: url("chrome://global/skin/icons/close.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: light-dark(var(--color-gray-70), var(--color-gray-05));
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
inset-inline-end: 18px;
|
||||
width: var(--size-item-small);
|
||||
height: var(--size-item-small);
|
||||
appearance: none;
|
||||
border: none;
|
||||
}
|
||||
.location-input-wrapper .close-icon:focus-visible {
|
||||
outline: 1px solid var(--focus-outline-color);
|
||||
}
|
||||
.location-input-wrapper input {
|
||||
border-radius: var(--border-radius-medium);
|
||||
background-color: light-dark(var(--color-white), var(--newtab-background-color-secondary));
|
||||
padding-block: 8px;
|
||||
padding-inline: 30px;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.location-input-wrapper input:focus-visible {
|
||||
outline: 2px solid var(--focus-outline-color);
|
||||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.card-outer {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
|
|
|
@ -2356,63 +2356,6 @@ main section {
|
|||
content: url("chrome://browser/skin/weather/night-mostly-cloudy-with-flurries.svg");
|
||||
}
|
||||
|
||||
.location-input-wrapper {
|
||||
background-color: light-dark(var(--color-white), var(--newtab-background-color-secondary));
|
||||
color: var(--newtab-text-primary-color);
|
||||
border-radius: var(--border-radius-medium);
|
||||
padding: 8px;
|
||||
position: relative;
|
||||
}
|
||||
.lightWallpaper .location-input-wrapper, .darkWallpaper .location-input-wrapper {
|
||||
background-color: var(--newtab-weather-background-color);
|
||||
}
|
||||
.lightWallpaper .location-input-wrapper:hover, .darkWallpaper .location-input-wrapper:hover {
|
||||
background-color: var(--newtab-button-static-hover-background);
|
||||
}
|
||||
.lightWallpaper .location-input-wrapper:hover:active, .darkWallpaper .location-input-wrapper:hover:active {
|
||||
background-color: var(--newtab-button-static-active-background);
|
||||
}
|
||||
@media (prefers-contrast) {
|
||||
.lightWallpaper .location-input-wrapper, .darkWallpaper .location-input-wrapper {
|
||||
background-color: var(--background-color-box);
|
||||
}
|
||||
}
|
||||
.location-input-wrapper .search-icon {
|
||||
content: url("chrome://global/skin/icons/search-glass.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: light-dark(var(--color-gray-70), var(--color-gray-05));
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
inset-inline-start: 18px;
|
||||
}
|
||||
.location-input-wrapper .close-icon {
|
||||
background-image: url("chrome://global/skin/icons/close.svg");
|
||||
-moz-context-properties: fill;
|
||||
fill: light-dark(var(--color-gray-70), var(--color-gray-05));
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
inset-inline-end: 18px;
|
||||
width: var(--size-item-small);
|
||||
height: var(--size-item-small);
|
||||
appearance: none;
|
||||
border: none;
|
||||
}
|
||||
.location-input-wrapper .close-icon:focus-visible {
|
||||
outline: 1px solid var(--focus-outline-color);
|
||||
}
|
||||
.location-input-wrapper input {
|
||||
border-radius: var(--border-radius-medium);
|
||||
background-color: light-dark(var(--color-white), var(--newtab-background-color-secondary));
|
||||
padding-block: 8px;
|
||||
padding-inline: 30px;
|
||||
border: 1px solid var(--newtab-border-color);
|
||||
}
|
||||
.location-input-wrapper input:focus-visible {
|
||||
outline: 2px solid var(--focus-outline-color);
|
||||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.card-outer {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
|
|
|
@ -239,11 +239,6 @@ for (const type of [
|
|||
"WEATHER_LOAD_ERROR",
|
||||
"WEATHER_OPEN_PROVIDER_URL",
|
||||
"WEATHER_UPDATE",
|
||||
"WEATHER_SEARCH_ACTIVE",
|
||||
"WEATHER_LOCATION_DATA_UPDATE",
|
||||
"WEATHER_QUERY_UPDATE",
|
||||
"WEATHER_LOCATION_SEARCH_UPDATE",
|
||||
"WEATHER_LOCATION_SUGGESTIONS_UPDATE",
|
||||
"WEBEXT_CLICK",
|
||||
"WEBEXT_DISMISS",
|
||||
]) {
|
||||
|
@ -1765,9 +1760,9 @@ const LinkMenuOptions = {
|
|||
isEnabled ? _OpenInPrivateWindow(site) : LinkMenuOptions.EmptyItem(),
|
||||
ChangeWeatherLocation: () => ({
|
||||
id: "newtab-weather-menu-change-location",
|
||||
action: actionCreators.BroadcastToContent({
|
||||
type: actionTypes.WEATHER_SEARCH_ACTIVE,
|
||||
data: true,
|
||||
action: actionCreators.OnlyToMain({
|
||||
type: actionTypes.CHANGE_WEATHER_LOCATION,
|
||||
data: { url: "https://mozilla.org" },
|
||||
}),
|
||||
}),
|
||||
ChangeWeatherDisplaySimple: () => ({
|
||||
|
@ -5640,19 +5635,10 @@ const INITIAL_STATE = {
|
|||
wallpaperList: [],
|
||||
},
|
||||
Weather: {
|
||||
// do we have the data from WeatherFeed yet?
|
||||
initialized: false,
|
||||
lastUpdated: null,
|
||||
query: "",
|
||||
suggestions: [],
|
||||
locationData: {
|
||||
city: "",
|
||||
adminArea: "",
|
||||
country: "",
|
||||
},
|
||||
// Display search input in Weather widget
|
||||
searchActive: false,
|
||||
locationSearchString: "",
|
||||
suggestedLocations: [],
|
||||
lastUpdated: null,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -6410,17 +6396,8 @@ function Weather(prevState = INITIAL_STATE.Weather, action) {
|
|||
...prevState,
|
||||
suggestions: action.data.suggestions,
|
||||
lastUpdated: action.data.date,
|
||||
locationData: action.data.locationData || prevState.locationData,
|
||||
initialized: true,
|
||||
};
|
||||
case actionTypes.WEATHER_SEARCH_ACTIVE:
|
||||
return { ...prevState, searchActive: action.data };
|
||||
case actionTypes.WEATHER_LOCATION_SEARCH_UPDATE:
|
||||
return { ...prevState, locationSearchString: action.data };
|
||||
case actionTypes.WEATHER_LOCATION_SUGGESTIONS_UPDATE:
|
||||
return { ...prevState, suggestedLocations: action.data };
|
||||
case actionTypes.WEATHER_LOCATION_DATA_UPDATE:
|
||||
return { ...prevState, locationData: action.data };
|
||||
default:
|
||||
return prevState;
|
||||
}
|
||||
|
@ -9645,108 +9622,6 @@ class _Search extends (external_React_default()).PureComponent {
|
|||
const Search_Search = (0,external_ReactRedux_namespaceObject.connect)(state => ({
|
||||
Prefs: state.Prefs
|
||||
}))(_Search);
|
||||
;// CONCATENATED MODULE: ./content-src/components/Weather/LocationSearch.jsx
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
|
||||
|
||||
function LocationSearch({
|
||||
outerClassName
|
||||
}) {
|
||||
// should be the location object from suggestedLocations
|
||||
const [selectedLocation, setSelectedLocation] = (0,external_React_namespaceObject.useState)("");
|
||||
const suggestedLocations = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Weather.suggestedLocations);
|
||||
const locationSearchString = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Weather.locationSearchString);
|
||||
const [userInput, setUserInput] = (0,external_React_namespaceObject.useState)(locationSearchString || "");
|
||||
const inputRef = (0,external_React_namespaceObject.useRef)(null);
|
||||
const dispatch = (0,external_ReactRedux_namespaceObject.useDispatch)();
|
||||
(0,external_React_namespaceObject.useEffect)(() => {
|
||||
if (selectedLocation) {
|
||||
dispatch(actionCreators.AlsoToMain({
|
||||
type: actionTypes.WEATHER_LOCATION_DATA_UPDATE,
|
||||
data: {
|
||||
city: selectedLocation.localized_name,
|
||||
adminName: selectedLocation.administrative_area,
|
||||
country: selectedLocation.country
|
||||
}
|
||||
}));
|
||||
dispatch(actionCreators.SetPref("weather.query", selectedLocation.key));
|
||||
dispatch(actionCreators.BroadcastToContent({
|
||||
type: actionTypes.WEATHER_SEARCH_ACTIVE,
|
||||
data: false
|
||||
}));
|
||||
}
|
||||
}, [selectedLocation, dispatch]);
|
||||
|
||||
// when component mounts, set focus to input
|
||||
(0,external_React_namespaceObject.useEffect)(() => {
|
||||
inputRef?.current?.focus();
|
||||
}, [inputRef]);
|
||||
function handleChange(event) {
|
||||
const {
|
||||
value
|
||||
} = event.target;
|
||||
setUserInput(value);
|
||||
if (value < 3 && suggestedLocations.length) {
|
||||
dispatch(actionCreators.AlsoToMain({
|
||||
type: actionTypes.WEATHER_LOCATION_SUGGESTIONS_UPDATE,
|
||||
data: []
|
||||
}));
|
||||
}
|
||||
// find match in suggestedLocation array
|
||||
const match = suggestedLocations?.find(({
|
||||
key
|
||||
}) => key === value);
|
||||
if (match) {
|
||||
setSelectedLocation(match);
|
||||
setUserInput(`${match.localized_name}, ${match.administrative_area.localized_name}`);
|
||||
} else if (value.length >= 3 && !match) {
|
||||
dispatch(actionCreators.AlsoToMain({
|
||||
type: actionTypes.WEATHER_LOCATION_SEARCH_UPDATE,
|
||||
data: value
|
||||
}));
|
||||
}
|
||||
}
|
||||
function handleCloseSearch() {
|
||||
dispatch(actionCreators.BroadcastToContent({
|
||||
type: actionTypes.WEATHER_SEARCH_ACTIVE,
|
||||
data: false
|
||||
}));
|
||||
setUserInput("");
|
||||
}
|
||||
function handleKeyDown(e) {
|
||||
if (e.key === "Escape") {
|
||||
handleCloseSearch();
|
||||
}
|
||||
}
|
||||
return /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: `${outerClassName} location-search`
|
||||
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "location-input-wrapper"
|
||||
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "search-icon"
|
||||
}), /*#__PURE__*/external_React_default().createElement("input", {
|
||||
ref: inputRef,
|
||||
list: "merino-location-list",
|
||||
type: "text",
|
||||
placeholder: "Search location",
|
||||
onChange: handleChange,
|
||||
value: userInput,
|
||||
onKeyDown: handleKeyDown
|
||||
}), /*#__PURE__*/external_React_default().createElement("button", {
|
||||
className: "close-icon",
|
||||
onClick: handleCloseSearch
|
||||
}), /*#__PURE__*/external_React_default().createElement("datalist", {
|
||||
id: "merino-location-list"
|
||||
}, (suggestedLocations || []).map(location => /*#__PURE__*/external_React_default().createElement("option", {
|
||||
value: location.key,
|
||||
key: location.key
|
||||
}, location.localized_name, ",", " ", location.administrative_area.localized_name)))));
|
||||
}
|
||||
|
||||
;// CONCATENATED MODULE: ./content-src/components/Weather/Weather.jsx
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
|
@ -9756,7 +9631,6 @@ function LocationSearch({
|
|||
|
||||
|
||||
|
||||
|
||||
const Weather_VISIBLE = "visible";
|
||||
const Weather_VISIBILITY_CHANGE_EVENT = "visibilitychange";
|
||||
class _Weather extends (external_React_default()).PureComponent {
|
||||
|
@ -9908,30 +9782,26 @@ class _Weather extends (external_React_default()).PureComponent {
|
|||
const {
|
||||
showContextMenu
|
||||
} = this.state;
|
||||
const {
|
||||
props
|
||||
} = this;
|
||||
const WEATHER_SUGGESTION = this.props.Weather.suggestions?.[0];
|
||||
const {
|
||||
className,
|
||||
index,
|
||||
dispatch,
|
||||
eventSource,
|
||||
shouldSendImpressionStats,
|
||||
Prefs,
|
||||
Weather
|
||||
} = props;
|
||||
const WEATHER_SUGGESTION = Weather.suggestions?.[0];
|
||||
shouldSendImpressionStats
|
||||
} = this.props;
|
||||
const {
|
||||
props
|
||||
} = this;
|
||||
const isContextMenuOpen = this.state.activeCard === index;
|
||||
const outerClassName = ["weather", className, isContextMenuOpen && !Weather.searchActive && "active", props.placeholder && "placeholder", Weather.searchActive && "search"].filter(v => v).join(" ");
|
||||
const showDetailedView = Prefs.values["weather.display"] === "detailed";
|
||||
const outerClassName = ["weather", className, isContextMenuOpen && "active", props.placeholder && "placeholder"].filter(v => v).join(" ");
|
||||
const showDetailedView = this.props.Prefs.values["weather.display"] === "detailed";
|
||||
|
||||
// Note: The temperature units/display options will become secondary menu items
|
||||
const WEATHER_SOURCE_CONTEXT_MENU_OPTIONS = [...(this.props.Prefs.values["weather.locationSearchEnabled"] ? ["ChangeWeatherLocation"] : []), ...(this.props.Prefs.values["weather.temperatureUnits"] === "f" ? ["ChangeTempUnitCelsius"] : ["ChangeTempUnitFahrenheit"]), ...(this.props.Prefs.values["weather.display"] === "simple" ? ["ChangeWeatherDisplayDetailed"] : ["ChangeWeatherDisplaySimple"]), "HideWeather", "OpenLearnMoreURL"];
|
||||
if (Weather.searchActive) {
|
||||
return /*#__PURE__*/external_React_default().createElement(LocationSearch, {
|
||||
outerClassName: outerClassName
|
||||
});
|
||||
} else if (WEATHER_SUGGESTION) {
|
||||
|
||||
// Only return the widget if we have data. Otherwise, show error state
|
||||
if (WEATHER_SUGGESTION) {
|
||||
return /*#__PURE__*/external_React_default().createElement("div", {
|
||||
ref: this.setImpressionRef,
|
||||
className: outerClassName
|
||||
|
@ -9957,7 +9827,7 @@ class _Weather extends (external_React_default()).PureComponent {
|
|||
className: "weatherCityRow"
|
||||
}, /*#__PURE__*/external_React_default().createElement("span", {
|
||||
className: "weatherCity"
|
||||
}, Weather.locationData.city)), showDetailedView ? /*#__PURE__*/external_React_default().createElement("div", {
|
||||
}, WEATHER_SUGGESTION.city_name)), showDetailedView ? /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "weatherDetailedSummaryRow"
|
||||
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "weatherHighLowTemps"
|
||||
|
|
|
@ -17,8 +17,7 @@ import {
|
|||
|
||||
const CACHE_KEY = "weather_feed";
|
||||
const WEATHER_UPDATE_TIME = 10 * 60 * 1000; // 10 minutes
|
||||
const MERINO_PROVIDER = ["accuweather"];
|
||||
const MERINO_CLIENT_KEY = "HNT_WEATHER_FEED";
|
||||
const MERINO_PROVIDER = "accuweather";
|
||||
|
||||
const PREF_WEATHER_QUERY = "weather.query";
|
||||
const PREF_SHOW_WEATHER = "showWeather";
|
||||
|
@ -33,7 +32,6 @@ export class WeatherFeed {
|
|||
this.merino = null;
|
||||
this.suggestions = [];
|
||||
this.lastUpdated = null;
|
||||
this.locationData = {};
|
||||
this.fetchTimer = null;
|
||||
this.fetchIntervalMs = 30 * 60 * 1000; // 30 minutes
|
||||
this.timeoutMS = 5000;
|
||||
|
@ -87,8 +85,8 @@ export class WeatherFeed {
|
|||
try {
|
||||
suggestions = await this.merino.fetch({
|
||||
query: weatherQuery || "",
|
||||
providers: weatherQuery ? ["accuweather_city"] : MERINO_PROVIDER,
|
||||
timeoutMs: 7000,
|
||||
providers: [MERINO_PROVIDER],
|
||||
timeoutMs: 5000,
|
||||
});
|
||||
} catch (error) {
|
||||
// We don't need to do anything with this right now.
|
||||
|
@ -103,31 +101,15 @@ export class WeatherFeed {
|
|||
// this fetch. If fetching stops or this `Weather` instance is uninitialized
|
||||
// during the fetch, `#merino` will be nulled, and the fetch should stop. We
|
||||
// can compare `merino` to `this.merino` to tell when this occurs.
|
||||
if (!this.merino) {
|
||||
this.merino = await this.MerinoClient(MERINO_CLIENT_KEY);
|
||||
}
|
||||
|
||||
this.merino = await this.MerinoClient("HNT_WEATHER_FEED");
|
||||
await this.fetchHelper();
|
||||
|
||||
if (this.suggestions.length) {
|
||||
const hasLocationData =
|
||||
!this.store.getState().Prefs.values[PREF_WEATHER_QUERY];
|
||||
this.lastUpdated = this.Date().now();
|
||||
await this.cache.set("weather", {
|
||||
suggestions: this.suggestions,
|
||||
lastUpdated: this.lastUpdated,
|
||||
});
|
||||
|
||||
// only calls to merino without the query parameter would return the location data (and only city name)
|
||||
if (hasLocationData) {
|
||||
const [data] = this.suggestions;
|
||||
this.locationData = {
|
||||
city: data.city_name,
|
||||
adminArea: "",
|
||||
country: "",
|
||||
};
|
||||
await this.cache.set("locationData", this.locationData);
|
||||
}
|
||||
}
|
||||
|
||||
this.update(isStartup);
|
||||
|
@ -135,12 +117,8 @@ export class WeatherFeed {
|
|||
|
||||
async loadWeather(isStartup = false) {
|
||||
const cachedData = (await this.cache.get()) || {};
|
||||
const { weather, locationData } = cachedData;
|
||||
const { weather } = cachedData;
|
||||
|
||||
// if we have locationData in the cache set it to this.locationData so it is added to the redux store
|
||||
if (locationData.city) {
|
||||
this.locationData = locationData;
|
||||
}
|
||||
// If we have nothing in cache, or cache has expired, we can make a fresh fetch.
|
||||
if (
|
||||
!weather?.lastUpdated ||
|
||||
|
@ -161,7 +139,6 @@ export class WeatherFeed {
|
|||
data: {
|
||||
suggestions: this.suggestions,
|
||||
lastUpdated: this.lastUpdated,
|
||||
locationData: this.locationData,
|
||||
},
|
||||
meta: {
|
||||
isStartup,
|
||||
|
@ -177,35 +154,10 @@ export class WeatherFeed {
|
|||
}, ms);
|
||||
}
|
||||
|
||||
async fetchLocationAutocomplete() {
|
||||
if (!this.merino) {
|
||||
this.merino = await this.MerinoClient(MERINO_CLIENT_KEY);
|
||||
}
|
||||
|
||||
const query = this.store.getState().Weather.locationSearchString;
|
||||
let response = await this.merino.fetch({
|
||||
query: query || "",
|
||||
providers: ["accuweather_city"],
|
||||
timeoutMs: 5000,
|
||||
otherParams: {
|
||||
request_type: "location",
|
||||
},
|
||||
});
|
||||
const data = response?.[0];
|
||||
if (data?.locations.length) {
|
||||
this.store.dispatch(
|
||||
ac.BroadcastToContent({
|
||||
type: at.WEATHER_LOCATION_SUGGESTIONS_UPDATE,
|
||||
data: data.locations,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async onPrefChangedAction(action) {
|
||||
switch (action.data.name) {
|
||||
case PREF_WEATHER_QUERY:
|
||||
await this.fetch();
|
||||
await this.loadWeather();
|
||||
break;
|
||||
case PREF_SHOW_WEATHER:
|
||||
case PREF_SYSTEM_SHOW_WEATHER:
|
||||
|
@ -237,13 +189,6 @@ export class WeatherFeed {
|
|||
case at.PREF_CHANGED:
|
||||
await this.onPrefChangedAction(action);
|
||||
break;
|
||||
case at.WEATHER_LOCATION_SEARCH_UPDATE:
|
||||
await this.fetchLocationAutocomplete();
|
||||
break;
|
||||
case at.WEATHER_LOCATION_DATA_UPDATE:
|
||||
await this.cache.set("locationData", action.data);
|
||||
this.locationData = action.data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,11 +60,6 @@ add_task(async function test_onAction_INIT() {
|
|||
});
|
||||
|
||||
let feed = new WeatherFeed();
|
||||
let locationData = {
|
||||
city: "testcity",
|
||||
adminArea: "",
|
||||
country: "",
|
||||
};
|
||||
|
||||
Services.prefs.setBoolPref(WEATHER_ENABLED, true);
|
||||
Services.prefs.setBoolPref(SYS_WEATHER_ENABLED, true);
|
||||
|
@ -73,19 +68,9 @@ add_task(async function test_onAction_INIT() {
|
|||
|
||||
sandbox.stub(feed, "fetchHelper");
|
||||
feed.suggestions = [WEATHER_SUGGESTION];
|
||||
feed.locationData = locationData;
|
||||
|
||||
feed.store = {
|
||||
dispatch: sinon.spy(),
|
||||
getState() {
|
||||
return this.state;
|
||||
},
|
||||
state: {
|
||||
Prefs: {
|
||||
values: {
|
||||
"weather.query": "348794",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
info("WeatherFeed.onAction INIT should initialize Weather");
|
||||
|
@ -102,7 +87,6 @@ add_task(async function test_onAction_INIT() {
|
|||
data: {
|
||||
suggestions: [WEATHER_SUGGESTION],
|
||||
lastUpdated: dateNowTestValue,
|
||||
locationData,
|
||||
},
|
||||
meta: {
|
||||
isStartup: true,
|
||||
|
|
|
@ -117,9 +117,6 @@ export class MerinoClient {
|
|||
* @param {string} options.extraResponseHistogram
|
||||
* If specified, the fetch's response will be recorded in this histogram in
|
||||
* addition to the usual Merino response histogram.
|
||||
* @param {object} options.otherParams
|
||||
* If specified, the otherParams will be added as a query params. Currently
|
||||
* used for accuweather's location autocomplete endpoint
|
||||
* @returns {Array}
|
||||
* The Merino suggestions or null if there's an error or unexpected
|
||||
* response.
|
||||
|
@ -130,7 +127,6 @@ export class MerinoClient {
|
|||
timeoutMs = lazy.UrlbarPrefs.get("merinoTimeoutMs"),
|
||||
extraLatencyHistogram = null,
|
||||
extraResponseHistogram = null,
|
||||
otherParams = {},
|
||||
}) {
|
||||
this.logger.info(`Fetch starting with query: "${query}"`);
|
||||
|
||||
|
@ -196,11 +192,6 @@ export class MerinoClient {
|
|||
url.searchParams.set(SEARCH_PARAMS.PROVIDERS, providersString);
|
||||
}
|
||||
|
||||
// if otherParams are present add them to the url
|
||||
for (const [param, value] of Object.entries(otherParams)) {
|
||||
url.searchParams.set(param, value);
|
||||
}
|
||||
|
||||
let details = { query, providers, timeoutMs, url };
|
||||
this.logger.debug("Fetch details: " + JSON.stringify(details));
|
||||
|
||||
|
|
|
@ -867,12 +867,6 @@ pocketNewtab:
|
|||
pref: browser.newtabpage.activity-stream.newtabWallpapers.enabled
|
||||
description: >-
|
||||
Turns on and off wallpaper support.
|
||||
weatherLocationSearch:
|
||||
type: boolean
|
||||
fallbackPref: >-
|
||||
browser.newtabpage.activity-stream.weather.locationSearchEnabled
|
||||
description: >-
|
||||
Turns on and off location search for newtab weather widget
|
||||
recsPersonalized:
|
||||
type: boolean
|
||||
fallbackPref: >-
|
||||
|
|
Загрузка…
Ссылка в новой задаче