Skip to content

Commit

Permalink
add mixed mode
Browse files Browse the repository at this point in the history
  • Loading branch information
felixriehm committed Mar 16, 2024
1 parent 9442ff5 commit dbbdd22
Show file tree
Hide file tree
Showing 30 changed files with 560 additions and 511 deletions.
32 changes: 6 additions & 26 deletions web/src/audio/hatnote_audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ export class HatnoteAudio {
private readonly swells: Howl[] = []
private readonly harp: Howl[] = []
private lastAudioPlayed: number = 0
private readonly showAudioInfoboxSubject: Subject<boolean>
private readonly settings_data: SettingsData

constructor(settings_data: SettingsData, showAudioInfoboxSubject: Subject<boolean> ) {
this.showAudioInfoboxSubject = showAudioInfoboxSubject
constructor(settings_data: SettingsData ) {
this.settings_data = settings_data

let loaded_sounds = 0
Expand Down Expand Up @@ -47,10 +45,7 @@ export class HatnoteAudio {
console.log("Number of audio playing (subtract): " + thisAudio.current_notes)
}
},
onload: sound_load,
onunlock: function() {
thisAudio.showAudioInfoboxSubject.next(false)
},
onload: sound_load
}))

this.clav.push(new Howl({
Expand All @@ -63,10 +58,7 @@ export class HatnoteAudio {
console.log("Number of audio playing (subtract): " + thisAudio.current_notes)
}
},
onload: sound_load,
onunlock: function() {
thisAudio.showAudioInfoboxSubject.next(false)
},
onload: sound_load
}))
}

Expand All @@ -82,37 +74,25 @@ export class HatnoteAudio {
console.log("Number of audio playing (subtract): " + thisAudio.current_notes)
}
},
onload : sound_load,
onunlock: function() {
thisAudio.showAudioInfoboxSubject.next(false)
},
onload : sound_load
}))
}

// load transition sound
this.harp.push(new Howl({
src : [sound_map.get('sounds/ConcertHarp-small/samples/C3_mf3.wav')],
volume : 0.2,
onload : sound_load,
onunlock: function() {
thisAudio.showAudioInfoboxSubject.next(false)
},
onload : sound_load
}))
this.harp.push(new Howl({
src : [sound_map.get('sounds/ConcertHarp-small/samples/F2_f1.wav')],
volume : 0.2,
onload : sound_load,
onunlock: function() {
thisAudio.showAudioInfoboxSubject.next(false)
},
onload : sound_load
}))
this.harp.push(new Howl({
src : [sound_map.get('sounds/ConcertHarp-small/samples/A2_mf1.wav')],
volume : 0.2,
onload : sound_load,
onunlock: function() {
thisAudio.showAudioInfoboxSubject.next(false)
},
}))
}

Expand Down
4 changes: 2 additions & 2 deletions web/src/canvas/banner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class Banner{
this.bannerLayer = bannerLayer

this.root = bannerLayer.appendSVGElement('g')
.attr('transform', 'translate(0, ' + bannerLayer.canvas.theme.header_height +')');
.attr('transform', 'translate(0, ' + bannerLayer.canvas.visDirector.hatnoteTheme.header_height +')');

this.user_container = this.root.append('g')

Expand All @@ -28,7 +28,7 @@ export class Banner{

this.user_container.append('rect')
.attr('opacity', 0)
.attr('fill', bannerLayer.canvas.theme.getThemeColor(bannerData.serviceEvent))
.attr('fill', bannerLayer.canvas.visDirector.getThemeColor(bannerData.serviceEvent))
.attr('width', bannerLayer.canvas.width)
.attr('height', 35)
.transition()
Expand Down
8 changes: 4 additions & 4 deletions web/src/canvas/banner_layer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {Selection} from "d3";
import {ListenToCanvas} from "./listen/listenToCanvas";
import {BannerData} from "../observable/model";
import {Banner} from "./banner";
import {Canvas} from "./canvas";

export class BannerLayer{
public readonly canvas: ListenToCanvas
public readonly canvas: Canvas
private readonly root: Selection<SVGGElement, unknown, null, any>;
private banner: Banner | null
constructor(canvas: ListenToCanvas) {
constructor(canvas: Canvas) {
this.canvas = canvas
this.root = canvas.appendSVGElement('g').attr('id', 'banner_layer')
this.banner = null;
Expand All @@ -18,7 +18,7 @@ export class BannerLayer{
}

public addBanner(bannerData: BannerData){
if(this.banner !== null || this.canvas.theme.current_service_theme?.id_name !== this.canvas.theme.getHatnoteService(bannerData.serviceEvent)) {
if(this.banner !== null || this.canvas.visDirector.current_service_theme?.id_name !== this.canvas.visDirector.getHatnoteService(bannerData.serviceEvent)) {
return;
}

Expand Down
148 changes: 133 additions & 15 deletions web/src/canvas/canvas.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,46 @@
import {select, Selection} from "d3";
import {BehaviorSubject, Subject} from "rxjs";
import {CircleData, DatabaseInfo, NetworkInfoboxData} from "../observable/model";
import {BannerData, CircleData, DatabaseInfo, NetworkInfoboxData} from "../observable/model";
import {SettingsData} from "../configuration/hatnote_settings";
import {InfoBox, InfoboxType} from "./info_box";
import {CirclesLayer} from "./listen/circles_layer";
import {Header} from "./header";
import {Theme} from "../theme/theme";
import {VisualisationDirector} from "../theme/visualisationDirector";
import {HatnoteVisService} from "../service_event/model";
import {Navigation} from "./navigation";
import {BannerLayer} from "./banner_layer";
import {QRCode} from "./qr_code";
import {MuteIcon} from "./mute_icon";
import {Carousel} from "./carousel";
import {ListenToVisualisation} from "./listen/listenToVisualisation";
import {GeoVisualisation} from "./geo/geoVisualisation";
import {Visualisation} from "../theme/model";
import {set} from "lodash";

export abstract class Canvas {
abstract header: Header;
public readonly theme: Theme;
abstract info_box_websocket: InfoBox;
abstract info_box_legend: InfoBox;
export class Canvas {
public readonly banner_layer: BannerLayer;
public readonly qr_code: QRCode;
public readonly header: Header;
public readonly visDirector: VisualisationDirector;
public readonly mute_icon: MuteIcon;
public readonly carousel: Carousel | undefined
public readonly navigation: Navigation | undefined;
public readonly info_box_websocket: InfoBox;
public readonly info_box_legend: InfoBox;
public readonly isMobileScreen: boolean = false;
public readonly settings: SettingsData;
public readonly showNetworkInfoboxObservable: Subject<NetworkInfoboxData>
public readonly updateDatabaseInfoSubject: Subject<DatabaseInfo>
public readonly hatnoteVisServiceChangedSubject: BehaviorSubject<HatnoteVisService>
public readonly onCarouselTransitionStart: BehaviorSubject<[HatnoteVisService, Visualisation]>
public readonly onThemeHasChanged: BehaviorSubject<[HatnoteVisService, Visualisation]>
public readonly onCarouselTransitionEnd: BehaviorSubject<[HatnoteVisService, Visualisation]>
public readonly updateVersionSubject: Subject<[string, number]>
public readonly newCircleSubject: Subject<CircleData>
public readonly newBannerSubject: Subject<BannerData>
private readonly listenToVis: ListenToVisualisation;
public readonly geoPopUpContainer: Selection<HTMLDivElement, unknown, null, undefined>
private readonly geoVis: GeoVisualisation;
public readonly appContainer: Selection<HTMLDivElement, unknown, null, undefined>;
protected abstract _root: Selection<SVGSVGElement, unknown, null, any>;
private readonly _root: Selection<SVGSVGElement, unknown, null, any>;
public get root(): Selection<SVGSVGElement, unknown, null, any> {
return this._root;
}
Expand All @@ -40,30 +59,129 @@ export abstract class Canvas {
this._height = value;
}

protected constructor(theme: Theme, settings: SettingsData, newCircleSubject: Subject<CircleData>,
constructor(theme: VisualisationDirector, settings: SettingsData, newCircleSubject: Subject<CircleData>,
showNetworkInfoboxObservable: Subject<NetworkInfoboxData>,
updateVersionSubject: Subject<[string, number]>,
hatnoteVisServiceChangedSubject: BehaviorSubject<HatnoteVisService>,
onCarouselTransitionStart: BehaviorSubject<[HatnoteVisService, Visualisation]>,
onCarouselTransitionMid: BehaviorSubject<[HatnoteVisService, Visualisation]>,
onCarouselTransitionEnd: BehaviorSubject<[HatnoteVisService, Visualisation]>,
updateDatabaseInfoSubject: Subject<DatabaseInfo>,
newBannerSubject: Subject<BannerData>,
appContainer: Selection<HTMLDivElement, unknown, null, undefined>) {
this._width = window.innerWidth;
this._height = window.innerHeight;
this.theme = theme;
this.visDirector = theme;
this.settings = settings
this.hatnoteVisServiceChangedSubject = hatnoteVisServiceChangedSubject
this.onCarouselTransitionStart = onCarouselTransitionStart
this.onThemeHasChanged = onCarouselTransitionMid
this.onCarouselTransitionEnd = onCarouselTransitionEnd
this.newCircleSubject = newCircleSubject
this.showNetworkInfoboxObservable = showNetworkInfoboxObservable
this.updateDatabaseInfoSubject = updateDatabaseInfoSubject
this.updateVersionSubject = updateVersionSubject
this.appContainer = appContainer;
this.newBannerSubject = newBannerSubject
if (this.width <= 430 || this.height <= 430) { // iPhone 12 Pro Max 430px viewport width
this.isMobileScreen = true;
}

// draw order matters in this function. Do not change without checking the result.
this._root = this.appContainer.append("svg")
.attr("width", this.width)
.attr("height", this.height)
.attr('fill', this.visDirector.hatnoteTheme.svg_background_color)
.style('background-color', '#1c2733');
this.geoPopUpContainer = this.appContainer.append('div')
.attr("id","geo-visualisation-popup-container").attr("style", "opacity: 1;")

this.qr_code = new QRCode(this)

this.listenToVis = new ListenToVisualisation(this)
this.geoVis = new GeoVisualisation(this)

this.banner_layer = new BannerLayer(this)
this.header = new Header(this)
// needs to be added last to the svg because it should draw over everything else
this.info_box_websocket = new InfoBox(this, InfoboxType.network_websocket_connecting)
this.info_box_legend = new InfoBox(this, InfoboxType.legend)

if(settings.carousel_mode && !this.isMobileScreen){
this.carousel = new Carousel(this)
}

// needs to be added after the carousel transition because the transition layer spans over the entire screen
// which captures mouse clicks that otherwise would not arrive at the navigation buttons
if (this.isMobileScreen && !this.settings.embedded_mode) {
this.navigation = new Navigation(this)
}

// needs to be here because otherwise the transition animation and mobile navigation layer of the carousel would lay above the mute icon
// and block the cursor event of the mute icon
this.mute_icon = new MuteIcon(this)

this.onThemeHasChanged.subscribe({
next: (value) => {
this.renderCurrentTheme()
}
})

this.renderCurrentTheme();

if(!settings.kiosk_mode && !settings.audio_mute && !(!settings.carousel_mode && settings.map)){
this.mute_icon.show()
}

window.onresize = (_) => this.windowUpdate();
}

public appendSVGElement(type: string): Selection<SVGGElement, unknown, null, any> {
return this._root.append(type)
}

protected abstract windowUpdate() : void
public renderCurrentTheme(){
// remove circles and visualisation from other services
this.listenToVis.renderCurrentTheme()
this.geoVis.renderCurrentTheme()

// remove banner
this.banner_layer.removeBanner();

// update qr code
this.qr_code.themeUpdate(this.visDirector.current_service_theme)

// update header logo
this.header.themeUpdate(this.visDirector.current_service_theme)

this.navigation?.themeUpdate(this.visDirector.current_service_theme)
}

// This method does not cover all ui elements. There is no requirement for this nor a need for a mobile version. People
// will use the website as a background animation. If you resize the window it is easier to just reload the page for a moment.
public windowUpdate() {
// update canvas root dimensions
this.width = window.innerWidth;
this.height = window.innerHeight;
this._root.attr("width", this.width).attr("height", this.height);

// update canvas header dimensions
this.header.windowUpdate()

// update banner
this.banner_layer.windowUpdate()

// update progress indicator
this.carousel?.windowUpdate()

// update qr_code
this.qr_code?.windowUpdate()

// update navigation
this.navigation?.windowUpdate()

// update websocket info box
this.info_box_websocket.windowUpdate()

// update mute icon
this.mute_icon.windowUpdate()
}
}
Loading

0 comments on commit dbbdd22

Please sign in to comment.