Window title reflects current view; Hosted-instance tracking

This commit is contained in:
James Barnsley
2018-06-29 14:26:06 +12:00
parent 29f60071a9
commit 82fa3354c6
24 changed files with 23258 additions and 21027 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -77,7 +77,7 @@
// Release details // Release details
// These are automatically injected to built HTML // These are automatically injected to built HTML
var build = "1530088331"; var build = "1530238924";
var version = "3.21.4"; var version = "3.21.4";
// Construct the script tag // Construct the script tag

View File

@ -111,7 +111,7 @@ export default class InitialSetupModal extends React.Component{
</div> </div>
</div> </div>
<div className="field checkbox"> {helpers.isHosted() ? null : <div className="field checkbox">
<div className="input"> <div className="input">
<label> <label>
<input <input
@ -124,7 +124,7 @@ export default class InitialSetupModal extends React.Component{
</span> </span>
</label> </label>
</div> </div>
</div> </div>}
{!this.state.allow_reporting ? <p className="description">This anonymous usage data is important in identifying errors and potential features that make Iris better for everyone. Want to know more? Read the <a href="https://github.com/jaedb/Iris/wiki/Terms-of-use#privacy-policy" target="_blank">privacy policy</a>.</p> : null} {!this.state.allow_reporting ? <p className="description">This anonymous usage data is important in identifying errors and potential features that make Iris better for everyone. Want to know more? Read the <a href="https://github.com/jaedb/Iris/wiki/Terms-of-use#privacy-policy" target="_blank">privacy policy</a>.</p> : null}

View File

@ -783,6 +783,20 @@ export let isLoading = function(load_queue = [], keys = []){
} }
/**
* Is this app running from the hosted instance?
* For example the GitHub-hosted UI
*
* @param Array hosts = valid hosted domain names
* @return Boolean
**/
export let isHosted = function(hosts = ['jaedb.github.io']){
var hostname = window.location.hostname;
return hosts.includes(hostname);
}
/** /**
* Get indexed record(s) by URI from our asset index * Get indexed record(s) by URI from our asset index
* *

View File

@ -27,6 +27,7 @@ class Album extends React.Component{
} }
componentDidMount(){ componentDidMount(){
this.setWindowTitle();
this.loadAlbum(); this.loadAlbum();
} }
@ -40,14 +41,33 @@ class Album extends React.Component{
// if our URI has changed, fetch new album // if our URI has changed, fetch new album
if (nextProps.params.uri != this.props.params.uri){ if (nextProps.params.uri != this.props.params.uri){
this.loadAlbum(nextProps ) this.loadAlbum(nextProps);
// if mopidy has just connected AND we're a local album, go get // if mopidy has just connected AND we're a local album, go get
}else if (!this.props.mopidy_connected && nextProps.mopidy_connected){ }else if (!this.props.mopidy_connected && nextProps.mopidy_connected){
if (helpers.uriSource(this.props.params.uri ) != 'spotify'){ if (helpers.uriSource(this.props.params.uri ) != 'spotify'){
this.loadAlbum(nextProps ) this.loadAlbum(nextProps);
} }
} }
if (!this.props.album && nextProps.album){
this.setWindowTitle(nextProps.album);
}
}
setWindowTitle(album = this.props.album){
if (album){
var artists = "";
for (var i = 0; i < album.artists.length; i++){
if (artists != ""){
artists += ", ";
}
artists += album.artists[i].name;
}
this.props.uiActions.setWindowTitle(album.name+" by "+artists+" (album)");
} else{
this.props.uiActions.setWindowTitle("Album");
}
} }
handleContextMenu(e){ handleContextMenu(e){
@ -57,7 +77,7 @@ class Album extends React.Component{
items: [this.props.album], items: [this.props.album],
uris: [this.props.params.uri] uris: [this.props.params.uri]
} }
this.props.uiActions.showContextMenu(data) this.props.uiActions.showContextMenu(data);
} }
loadAlbum(props = this.props){ loadAlbum(props = this.props){
@ -77,7 +97,7 @@ class Album extends React.Component{
if (props.album && props.album.tracks){ if (props.album && props.album.tracks){
console.info('Loading album from index') console.info('Loading album from index')
} else { } else {
this.props.mopidyActions.getAlbum(props.params.uri ); this.props.mopidyActions.getAlbum(props.params.uri);
} }
} }
break; break;

View File

@ -31,6 +31,7 @@ class Artist extends React.Component{
} }
componentDidMount(){ componentDidMount(){
this.setWindowTitle();
this.loadArtist(); this.loadArtist();
} }
@ -42,6 +43,22 @@ class Artist extends React.Component{
this.loadArtist(nextProps); this.loadArtist(nextProps);
} }
} }
if (!this.props.artist && nextProps.artist){
this.setWindowTitle(nextProps.artist);
}
if (this.props.params.uri !== nextProps.params.uri && nextProps.artist){
this.setWindowTitle(nextProps.artist);
}
}
setWindowTitle(artist = this.props.artist){
if (artist){
this.props.uiActions.setWindowTitle(artist.name+" (artist)");
} else{
this.props.uiActions.setWindowTitle("Artist");
}
} }
handleContextMenu(e){ handleContextMenu(e){

View File

@ -30,16 +30,33 @@ class Playlist extends React.Component{
componentDidMount(){ componentDidMount(){
this.loadPlaylist(); this.loadPlaylist();
this.setWindowTitle();
} }
componentWillReceiveProps(nextProps){ componentWillReceiveProps(nextProps){
if (nextProps.params.uri != this.props.params.uri){ if (nextProps.params.uri != this.props.params.uri){
this.loadPlaylist(nextProps ) this.loadPlaylist(nextProps);
}else if (!this.props.mopidy_connected && nextProps.mopidy_connected){ } else if (!this.props.mopidy_connected && nextProps.mopidy_connected){
if (helpers.uriSource(this.props.params.uri) != 'spotify'){ if (helpers.uriSource(this.props.params.uri) != 'spotify'){
this.loadPlaylist(nextProps ) this.loadPlaylist(nextProps);
} }
} }
if (!this.props.playlist && nextProps.playlist){
this.setWindowTitle(nextProps.playlist);
}
if (this.props.params.uri !== nextProps.params.uri && nextProps.playlist){
this.setWindowTitle(nextProps.playlist);
}
}
setWindowTitle(playlist = this.props.playlist){
if (playlist){
this.props.uiActions.setWindowTitle(playlist.name+" (playlist)");
} else{
this.props.uiActions.setWindowTitle("Playlist");
}
} }
loadPlaylist(props = this.props){ loadPlaylist(props = this.props){

View File

@ -88,6 +88,8 @@ class Search extends React.Component{
search(type = this.state.type, term = this.state.term, provider){ search(type = this.state.type, term = this.state.term, provider){
this.props.uiActions.setWindowTitle("Search: "+term);
this.props.mopidyActions.clearSearchResults(); this.props.mopidyActions.clearSearchResults();
this.props.spotifyActions.clearSearchResults(); this.props.spotifyActions.clearSearchResults();

View File

@ -14,6 +14,7 @@ import Thumbnail from '../components/Thumbnail'
import URILink from '../components/URILink' import URILink from '../components/URILink'
import Services from '../components/Services' import Services from '../components/Services'
import * as helpers from '../helpers'
import * as coreActions from '../services/core/actions' import * as coreActions from '../services/core/actions'
import * as uiActions from '../services/ui/actions' import * as uiActions from '../services/ui/actions'
import * as pusherActions from '../services/pusher/actions' import * as pusherActions from '../services/pusher/actions'
@ -255,24 +256,26 @@ class Settings extends React.Component {
<h4 className="underline">Services</h4> <h4 className="underline">Services</h4>
<Services active={this.props.params.sub_view} /> <Services active={this.props.params.sub_view} />
<h4 className="underline">Privacy</h4> {helpers.isHosted() ? null : <div>
<h4 className="underline">Privacy</h4>
<div className="field checkbox"> <div className="field checkbox">
<div className="name">Reporting</div> <div className="name">Reporting</div>
<div className="input"> <div className="input">
<label> <label>
<input <input
type="checkbox" type="checkbox"
name="allow_reporting" name="allow_reporting"
checked={ this.props.ui.allow_reporting } checked={ this.props.ui.allow_reporting }
onChange={ e => this.props.uiActions.set({ allow_reporting: !this.props.ui.allow_reporting })} /> onChange={ e => this.props.uiActions.set({ allow_reporting: !this.props.ui.allow_reporting })} />
<span className="label"> <span className="label">
Allow reporting of anonymous usage statistics Allow reporting of anonymous usage statistics
</span> </span>
</label> </label>
<div className="description">Anonymous usage data is used to identify errors and potential features that make Iris better for everyone. Read the <a href="https://github.com/jaedb/Iris/wiki/Terms-of-use#privacy-policy" target="_blank">privacy policy</a>.</div> <div className="description">Anonymous usage data is used to identify errors and potential features that make Iris better for everyone. Read the <a href="https://github.com/jaedb/Iris/wiki/Terms-of-use#privacy-policy" target="_blank">privacy policy</a>.</div>
</div>
</div> </div>
</div> </div>}
<h4 className="underline">Advanced</h4> <h4 className="underline">Advanced</h4>

View File

@ -69,6 +69,25 @@ class Track extends React.Component{
this.props.geniusActions.findTrackLyrics(nextProps.track); this.props.geniusActions.findTrackLyrics(nextProps.track);
} }
} }
if (!this.props.track && nextProps.track){
this.setWindowTitle(nextProps.track);
}
}
setWindowTitle(track = this.props.track){
if (track){
var artists = "";
for (var i = 0; i < track.artists.length; i++){
if (artists != ""){
artists += ", ";
}
artists += track.artists[i].name;
}
this.props.uiActions.setWindowTitle(track.name+" by "+artists+" (track)");
} else{
this.props.uiActions.setWindowTitle("Track");
}
} }
handleContextMenu(e){ handleContextMenu(e){

View File

@ -12,6 +12,7 @@ import ContextMenuTrigger from '../components/ContextMenuTrigger'
import Icon from '../components/Icon' import Icon from '../components/Icon'
import * as helpers from '../helpers' import * as helpers from '../helpers'
import * as uiActions from '../services/ui/actions'
import * as mopidyActions from '../services/mopidy/actions' import * as mopidyActions from '../services/mopidy/actions'
import * as spotifyActions from '../services/spotify/actions' import * as spotifyActions from '../services/spotify/actions'
@ -22,6 +23,7 @@ class User extends React.Component{
} }
componentDidMount(){ componentDidMount(){
this.setWindowTitle();
this.loadUser(); this.loadUser();
} }
@ -29,6 +31,18 @@ class User extends React.Component{
if (nextProps.params.uri != this.props.params.uri){ if (nextProps.params.uri != this.props.params.uri){
this.loadUser(nextProps); this.loadUser(nextProps);
} }
if (!this.props.user && nextProps.user){
this.setWindowTitle(nextProps.user);
}
}
setWindowTitle(user = this.props.user){
if (user){
this.props.uiActions.setWindowTitle(user.name+" (user)");
} else{
this.props.uiActions.setWindowTitle("User");
}
} }
loadUser(props = this.props){ loadUser(props = this.props){
@ -129,6 +143,7 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
uiActions: bindActionCreators(uiActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch) spotifyActions: bindActionCreators(spotifyActions, dispatch)
} }
} }

View File

@ -8,6 +8,7 @@ import Icon from '../../components/Icon'
import CategoryGrid from '../../components/CategoryGrid' import CategoryGrid from '../../components/CategoryGrid'
import * as helpers from '../../helpers' import * as helpers from '../../helpers'
import * as uiActions from '../../services/ui/actions'
import * as spotifyActions from '../../services/spotify/actions' import * as spotifyActions from '../../services/spotify/actions'
class DiscoverCategories extends React.Component{ class DiscoverCategories extends React.Component{
@ -20,6 +21,7 @@ class DiscoverCategories extends React.Component{
if (!this.props.categories){ if (!this.props.categories){
this.props.spotifyActions.getCategories(); this.props.spotifyActions.getCategories();
} }
this.props.uiActions.setWindowTitle("Genre / Mood");
} }
render(){ render(){
@ -74,6 +76,7 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
uiActions: bindActionCreators(uiActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch) spotifyActions: bindActionCreators(spotifyActions, dispatch)
} }
} }

View File

@ -9,6 +9,7 @@ import PlaylistGrid from '../../components/PlaylistGrid'
import LazyLoadListener from '../../components/LazyLoadListener' import LazyLoadListener from '../../components/LazyLoadListener'
import * as helpers from '../../helpers' import * as helpers from '../../helpers'
import * as uiActions from '../../services/ui/actions'
import * as spotifyActions from '../../services/spotify/actions' import * as spotifyActions from '../../services/spotify/actions'
class DiscoverCategory extends React.Component{ class DiscoverCategory extends React.Component{
@ -19,11 +20,24 @@ class DiscoverCategory extends React.Component{
componentDidMount(){ componentDidMount(){
this.loadCategory(); this.loadCategory();
this.setWindowTitle();
} }
componentWillReceiveProps(nextProps){ componentWillReceiveProps(nextProps){
if (nextProps.params.id != this.props.params.id){ if (nextProps.params.id != this.props.params.id){
this.loadCategory() this.loadCategory();
}
if (!this.props.category && nextProps.category){
this.setWindowTitle(nextProps.category);
}
}
setWindowTitle(category = this.props.category){
if (category){
this.props.uiActions.setWindowTitle(category.name);
} else{
this.props.uiActions.setWindowTitle("Genre / Mood");
} }
} }
@ -107,6 +121,7 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
uiActions: bindActionCreators(uiActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch) spotifyActions: bindActionCreators(spotifyActions, dispatch)
} }
} }

View File

@ -22,6 +22,7 @@ class DiscoverFeatured extends React.Component{
} }
componentDidMount(){ componentDidMount(){
this.props.uiActions.setWindowTitle("Featured playlists");
if (!this.props.featured_playlists){ if (!this.props.featured_playlists){
this.props.spotifyActions.getFeaturedPlaylists(); this.props.spotifyActions.getFeaturedPlaylists();
} }

View File

@ -24,6 +24,8 @@ class DiscoverNewReleases extends React.Component{
} }
componentDidMount(){ componentDidMount(){
this.props.uiActions.setWindowTitle("New releases");
if (!this.props.new_releases){ if (!this.props.new_releases){
this.props.spotifyActions.getNewReleases(); this.props.spotifyActions.getNewReleases();
} }

View File

@ -150,6 +150,7 @@ class Discover extends React.Component{
} }
componentDidMount(){ componentDidMount(){
this.props.uiActions.setWindowTitle("Discover");
// We have seeds provided in the URL // We have seeds provided in the URL
if (this.props.params.seeds){ if (this.props.params.seeds){

View File

@ -34,6 +34,8 @@ class LibraryAlbums extends React.Component{
} }
componentDidMount(){ componentDidMount(){
this.props.uiActions.setWindowTitle("Albums");
if (this.props.mopidy_library_albums_status != 'finished' && this.props.mopidy_library_albums_status != 'started' && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'local')){ if (this.props.mopidy_library_albums_status != 'finished' && this.props.mopidy_library_albums_status != 'started' && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'local')){
this.props.mopidyActions.getLibraryAlbums() this.props.mopidyActions.getLibraryAlbums()
} }

View File

@ -30,6 +30,8 @@ class LibraryArtists extends React.Component{
} }
componentDidMount(){ componentDidMount(){
this.props.uiActions.setWindowTitle("Artists");
if (!this.props.mopidy_library_artists && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'local')){ if (!this.props.mopidy_library_artists && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'local')){
this.props.mopidyActions.getLibraryArtists(); this.props.mopidyActions.getLibraryArtists();
} }

View File

@ -26,6 +26,7 @@ class LibraryBrowse extends React.Component{
} }
componentWillReceiveProps(nextProps){ componentWillReceiveProps(nextProps){
this.props.uiActions.setWindowTitle("Browse");
// mopidy goes online // mopidy goes online
if (!this.props.mopidy_connected && nextProps.mopidy_connected){ if (!this.props.mopidy_connected && nextProps.mopidy_connected){

View File

@ -31,6 +31,8 @@ class LibraryPlaylists extends React.Component{
} }
componentDidMount(){ componentDidMount(){
this.props.uiActions.setWindowTitle("Playlists");
if (!this.props.mopidy_library_playlists && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'local')){ if (!this.props.mopidy_library_playlists && this.props.mopidy_connected && (this.props.source == 'all' || this.props.source == 'local')){
this.props.mopidyActions.getLibraryPlaylists() this.props.mopidyActions.getLibraryPlaylists()
} }

View File

@ -10,6 +10,7 @@ import LazyLoadListener from '../../components/LazyLoadListener'
import Icon from '../../components/Icon' import Icon from '../../components/Icon'
import * as helpers from '../../helpers' import * as helpers from '../../helpers'
import * as uiActions from '../../services/ui/actions'
import * as mopidyActions from '../../services/mopidy/actions' import * as mopidyActions from '../../services/mopidy/actions'
import * as spotifyActions from '../../services/spotify/actions' import * as spotifyActions from '../../services/spotify/actions'
@ -21,6 +22,8 @@ class LibraryTracks extends React.Component{
// on render // on render
componentDidMount(){ componentDidMount(){
this.props.uiActions.setWindowTitle("Tracks");
if (this.props.library_tracks === undefined){ if (this.props.library_tracks === undefined){
this.props.spotifyActions.getLibraryTracks(); this.props.spotifyActions.getLibraryTracks();
} }
@ -103,6 +106,7 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
uiActions: bindActionCreators(uiActions, dispatch),
mopidyActions: bindActionCreators(mopidyActions, dispatch), mopidyActions: bindActionCreators(mopidyActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch) spotifyActions: bindActionCreators(spotifyActions, dispatch)
} }