import*as Common from'../common/common.js';import*as Host from'../host/host.js';import*as SDK from'../sdk/sdk.js';import*as UI from'../ui/ui.js';export class SensorsView extends UI.Widget.VBox{constructor(){super(true);this.registerRequiredCSS('emulation/sensors.css');this.contentElement.classList.add('sensors-view');this._geolocationSetting=self.Common.settings.createSetting('emulation.geolocationOverride','');this._geolocation=SDK.EmulationModel.Geolocation.parseSetting(this._geolocationSetting.get());this._geolocationOverrideEnabled=false;this._createGeolocationSection(this._geolocation);this.contentElement.createChild('div').classList.add('panel-section-separator');this._deviceOrientationSetting=self.Common.settings.createSetting('emulation.deviceOrientationOverride','');this._deviceOrientation=SDK.EmulationModel.DeviceOrientation.parseSetting(this._deviceOrientationSetting.get());this._deviceOrientationOverrideEnabled=false;this._createDeviceOrientationSection();this.contentElement.createChild('div').classList.add('panel-section-separator');this._appendTouchControl();}
static instance(){if(!SensorsView._instanceObject){SensorsView._instanceObject=new SensorsView();}
return SensorsView._instanceObject;}
_createGeolocationSection(geolocation){const geogroup=this.contentElement.createChild('section','sensors-group');const geogroupTitle=UI.UIUtils.createLabel(ls`Geolocation`,'sensors-group-title');geogroup.appendChild(geogroupTitle);const fields=geogroup.createChild('div','geo-fields');const noOverrideOption={title:Common.UIString.UIString('No override'),location:NonPresetOptions.NoOverride};this._locationSelectElement=fields.createChild('select','chrome-select');UI.ARIAUtils.bindLabelToControl(geogroupTitle,this._locationSelectElement);this._locationSelectElement.appendChild(new Option(noOverrideOption.title,noOverrideOption.location));this._customLocationsGroup=this._locationSelectElement.createChild('optgroup');this._customLocationsGroup.label=ls`Overrides`;const customGeolocations=self.Common.settings.moduleSetting('emulation.geolocations');const manageButton=UI.UIUtils.createTextButton(ls`Manage`,()=>Common.Revealer.reveal(customGeolocations));UI.ARIAUtils.setAccessibleName(manageButton,ls`Manage the list of geolocations`);fields.appendChild(manageButton);const fillCustomSettings=()=>{this._customLocationsGroup.removeChildren();for(const geolocation of customGeolocations.get()){this._customLocationsGroup.appendChild(new Option(geolocation.title,JSON.stringify(geolocation)));}};customGeolocations.addChangeListener(fillCustomSettings);fillCustomSettings();const customLocationOption={title:Common.UIString.UIString('Other\u2026'),location:NonPresetOptions.Custom};this._locationSelectElement.appendChild(new Option(customLocationOption.title,customLocationOption.location));const group=this._locationSelectElement.createChild('optgroup');group.label=ls`Error`;group.appendChild(new Option(ls`Location unavailable`,NonPresetOptions.Unavailable));this._locationSelectElement.selectedIndex=0;this._locationSelectElement.addEventListener('change',this._geolocationSelectChanged.bind(this));this._fieldsetElement=fields.createChild('fieldset');this._fieldsetElement.disabled=!this._geolocationOverrideEnabled;this._fieldsetElement.id='geolocation-override-section';const latitudeGroup=this._fieldsetElement.createChild('div','latlong-group');const longitudeGroup=this._fieldsetElement.createChild('div','latlong-group');const timezoneGroup=this._fieldsetElement.createChild('div','latlong-group');const cmdOrCtrl=Host.Platform.isMac()?'\u2318':'Ctrl';const modifierKeyMessage=ls`Adjust with mousewheel or up/down keys. ${cmdOrCtrl}: ±10, Shift: ±1, Alt: ±0.01`;this._latitudeInput=UI.UIUtils.createInput('','number');latitudeGroup.appendChild(this._latitudeInput);this._latitudeInput.setAttribute('step','any');this._latitudeInput.value=0;this._latitudeSetter=UI.UIUtils.bindInput(this._latitudeInput,this._applyGeolocationUserInput.bind(this),SDK.EmulationModel.Geolocation.latitudeValidator,true,0.1);this._latitudeSetter(String(geolocation.latitude));this._latitudeInput.title=modifierKeyMessage;latitudeGroup.appendChild(UI.UIUtils.createLabel(ls`Latitude`,'latlong-title',this._latitudeInput));this._longitudeInput=UI.UIUtils.createInput('','number');longitudeGroup.appendChild(this._longitudeInput);this._longitudeInput.setAttribute('step','any');this._longitudeInput.value=0;this._longitudeSetter=UI.UIUtils.bindInput(this._longitudeInput,this._applyGeolocationUserInput.bind(this),SDK.EmulationModel.Geolocation.longitudeValidator,true,0.1);this._longitudeSetter(String(geolocation.longitude));this._longitudeInput.title=modifierKeyMessage;longitudeGroup.appendChild(UI.UIUtils.createLabel(ls`Longitude`,'latlong-title',this._longitudeInput));this._timezoneInput=UI.UIUtils.createInput('','text');timezoneGroup.appendChild(this._timezoneInput);this._timezoneInput.value='Europe/Berlin';this._timezoneSetter=UI.UIUtils.bindInput(this._timezoneInput,this._applyGeolocationUserInput.bind(this),SDK.EmulationModel.Geolocation.timezoneIdValidator,false);this._timezoneSetter(String(geolocation.timezoneId));timezoneGroup.appendChild(UI.UIUtils.createLabel(ls`Timezone ID`,'timezone-title',this._timezoneInput));this._timezoneError=timezoneGroup.createChild('div','timezone-error');}
_geolocationSelectChanged(){this._fieldsetElement.disabled=false;this._timezoneError.textContent='';const value=this._locationSelectElement.options[this._locationSelectElement.selectedIndex].value;if(value===NonPresetOptions.NoOverride){this._geolocationOverrideEnabled=false;this._fieldsetElement.disabled=true;}else if(value===NonPresetOptions.Custom){this._geolocationOverrideEnabled=true;const geolocation=SDK.EmulationModel.Geolocation.parseUserInput(this._latitudeInput.value.trim(),this._longitudeInput.value.trim(),this._timezoneInput.value.trim());if(!geolocation){return;}
this._geolocation=geolocation;}else if(value===NonPresetOptions.Unavailable){this._geolocationOverrideEnabled=true;this._geolocation=new SDK.EmulationModel.Geolocation(0,0,'',true);}else{this._geolocationOverrideEnabled=true;const coordinates=JSON.parse(value);this._geolocation=new SDK.EmulationModel.Geolocation(coordinates.lat,coordinates.long,coordinates.timezoneId,false);this._latitudeSetter(coordinates.lat);this._longitudeSetter(coordinates.long);this._timezoneSetter(coordinates.timezoneId);}
this._applyGeolocation();if(value===NonPresetOptions.Custom){this._latitudeInput.focus();}}
_applyGeolocationUserInput(){const geolocation=SDK.EmulationModel.Geolocation.parseUserInput(this._latitudeInput.value.trim(),this._longitudeInput.value.trim(),this._timezoneInput.value.trim());if(!geolocation){return;}
this._timezoneError.textContent='';this._setSelectElementLabel(this._locationSelectElement,NonPresetOptions.Custom);this._geolocation=geolocation;this._applyGeolocation();}
_applyGeolocation(){if(this._geolocationOverrideEnabled){this._geolocationSetting.set(this._geolocation.toSetting());}
for(const emulationModel of self.SDK.targetManager.models(SDK.EmulationModel.EmulationModel)){emulationModel.emulateGeolocation(this._geolocationOverrideEnabled?this._geolocation:null).catch(err=>{switch(err.type){case'emulation-set-timezone':this._timezoneError.textContent=err.message;break;}});}}
_createDeviceOrientationSection(){const orientationGroup=this.contentElement.createChild('section','sensors-group');const orientationTitle=UI.UIUtils.createLabel(ls`Orientation`,'sensors-group-title');orientationGroup.appendChild(orientationTitle);const orientationContent=orientationGroup.createChild('div','orientation-content');const fields=orientationContent.createChild('div','orientation-fields');const orientationOffOption={title:Common.UIString.UIString('Off'),orientation:NonPresetOptions.NoOverride};const customOrientationOption={title:Common.UIString.UIString('Custom orientation...'),orientation:NonPresetOptions.Custom};this._orientationSelectElement=this.contentElement.createChild('select','chrome-select');UI.ARIAUtils.bindLabelToControl(orientationTitle,this._orientationSelectElement);this._orientationSelectElement.appendChild(new Option(orientationOffOption.title,orientationOffOption.orientation));this._orientationSelectElement.appendChild(new Option(customOrientationOption.title,customOrientationOption.orientation));const orientationGroups=PresetOrientations;for(let i=0;i<orientationGroups.length;++i){const groupElement=this._orientationSelectElement.createChild('optgroup');groupElement.label=orientationGroups[i].title;const group=orientationGroups[i].value;for(let j=0;j<group.length;++j){groupElement.appendChild(new Option(group[j].title,group[j].orientation));}}
this._orientationSelectElement.selectedIndex=0;fields.appendChild(this._orientationSelectElement);this._orientationSelectElement.addEventListener('change',this._orientationSelectChanged.bind(this));this._deviceOrientationFieldset=this._createDeviceOrientationOverrideElement(this._deviceOrientation);this._stageElement=orientationContent.createChild('div','orientation-stage');this._orientationLayer=this._stageElement.createChild('div','orientation-layer');this._boxElement=this._orientationLayer.createChild('section','orientation-box orientation-element');this._boxElement.createChild('section','orientation-front orientation-element');this._boxElement.createChild('section','orientation-top orientation-element');this._boxElement.createChild('section','orientation-back orientation-element');this._boxElement.createChild('section','orientation-left orientation-element');this._boxElement.createChild('section','orientation-right orientation-element');this._boxElement.createChild('section','orientation-bottom orientation-element');UI.UIUtils.installDragHandle(this._stageElement,this._onBoxDragStart.bind(this),this._onBoxDrag.bind(this),null,'-webkit-grabbing','-webkit-grab');fields.appendChild(this._deviceOrientationFieldset);this._enableOrientationFields(true);this._setBoxOrientation(this._deviceOrientation,false);}
_enableOrientationFields(disable){if(disable){this._deviceOrientationFieldset.disabled=true;this._stageElement.classList.add('disabled');this._stageElement.title=ls`Enable orientation to rotate`;}else{this._deviceOrientationFieldset.disabled=false;this._stageElement.classList.remove('disabled');this._stageElement.title=ls`Shift+drag horizontally to rotate around the y-axis`;}}
_orientationSelectChanged(){const value=this._orientationSelectElement.options[this._orientationSelectElement.selectedIndex].value;this._enableOrientationFields(false);if(value===NonPresetOptions.NoOverride){this._deviceOrientationOverrideEnabled=false;this._enableOrientationFields(true);}else if(value===NonPresetOptions.Custom){this._deviceOrientationOverrideEnabled=true;this._alphaElement.focus();}else{const parsedValue=JSON.parse(value);this._deviceOrientationOverrideEnabled=true;this._deviceOrientation=new SDK.EmulationModel.DeviceOrientation(parsedValue[0],parsedValue[1],parsedValue[2]);this._setDeviceOrientation(this._deviceOrientation,DeviceOrientationModificationSource.SelectPreset);}}
_applyDeviceOrientation(){if(this._deviceOrientationOverrideEnabled){this._deviceOrientationSetting.set(this._deviceOrientation.toSetting());}
for(const emulationModel of self.SDK.targetManager.models(SDK.EmulationModel.EmulationModel)){emulationModel.emulateDeviceOrientation(this._deviceOrientationOverrideEnabled?this._deviceOrientation:null);}}
_setSelectElementLabel(selectElement,labelValue){const optionValues=Array.prototype.map.call(selectElement.options,x=>x.value);selectElement.selectedIndex=optionValues.indexOf(labelValue);}
_applyDeviceOrientationUserInput(){this._setDeviceOrientation(SDK.EmulationModel.DeviceOrientation.parseUserInput(this._alphaElement.value.trim(),this._betaElement.value.trim(),this._gammaElement.value.trim()),DeviceOrientationModificationSource.UserInput);this._setSelectElementLabel(this._orientationSelectElement,NonPresetOptions.Custom);}
_resetDeviceOrientation(){this._setDeviceOrientation(new SDK.EmulationModel.DeviceOrientation(0,90,0),DeviceOrientationModificationSource.ResetButton);this._setSelectElementLabel(this._orientationSelectElement,'[0, 90, 0]');}
_setDeviceOrientation(deviceOrientation,modificationSource){if(!deviceOrientation){return;}
function roundAngle(angle){return Math.round(angle*10000)/10000;}
if(modificationSource!==DeviceOrientationModificationSource.UserInput){this._alphaSetter(roundAngle(deviceOrientation.alpha));this._betaSetter(roundAngle(deviceOrientation.beta));this._gammaSetter(roundAngle(deviceOrientation.gamma));}
const animate=modificationSource!==DeviceOrientationModificationSource.UserDrag;this._setBoxOrientation(deviceOrientation,animate);this._deviceOrientation=deviceOrientation;this._applyDeviceOrientation();UI.ARIAUtils.alert(ls`Device orientation set to alpha: ${deviceOrientation.alpha}, beta: ${deviceOrientation.beta}, gamma: ${
            deviceOrientation.gamma}`,this._orientationSelectElement);}
_createAxisInput(parentElement,input,label){const div=parentElement.createChild('div','orientation-axis-input-container');div.appendChild(input);div.appendChild(UI.UIUtils.createLabel(label,'',input));input.type='number';return UI.UIUtils.bindInput(input,this._applyDeviceOrientationUserInput.bind(this),SDK.EmulationModel.DeviceOrientation.validator,true);}
_createDeviceOrientationOverrideElement(deviceOrientation){const fieldsetElement=createElement('fieldset');fieldsetElement.classList.add('device-orientation-override-section');const cellElement=fieldsetElement.createChild('td','orientation-inputs-cell');this._alphaElement=UI.UIUtils.createInput();this._alphaElement.setAttribute('step','any');this._alphaSetter=this._createAxisInput(cellElement,this._alphaElement,Common.UIString.UIString('\u03B1 (alpha)'));this._alphaSetter(String(deviceOrientation.alpha));this._betaElement=UI.UIUtils.createInput();this._betaElement.setAttribute('step','any');this._betaSetter=this._createAxisInput(cellElement,this._betaElement,Common.UIString.UIString('\u03B2 (beta)'));this._betaSetter(String(deviceOrientation.beta));this._gammaElement=UI.UIUtils.createInput();this._gammaElement.setAttribute('step','any');this._gammaSetter=this._createAxisInput(cellElement,this._gammaElement,Common.UIString.UIString('\u03B3 (gamma)'));this._gammaSetter(String(deviceOrientation.gamma));const resetButton=UI.UIUtils.createTextButton(Common.UIString.UIString('Reset'),this._resetDeviceOrientation.bind(this),'orientation-reset-button');UI.ARIAUtils.setAccessibleName(resetButton,ls`Reset device orientation`);resetButton.setAttribute('type','reset');cellElement.appendChild(resetButton);return fieldsetElement;}
_setBoxOrientation(deviceOrientation,animate){if(animate){this._stageElement.classList.add('is-animating');}else{this._stageElement.classList.remove('is-animating');}
const matrix=new WebKitCSSMatrix();this._boxMatrix=matrix.rotate(-deviceOrientation.beta,deviceOrientation.gamma,-deviceOrientation.alpha);const eulerAngles=new UI.Geometry.EulerAngles(deviceOrientation.alpha,deviceOrientation.beta,deviceOrientation.gamma);this._orientationLayer.style.transform=eulerAngles.toRotate3DString();}
_onBoxDrag(event){const mouseMoveVector=this._calculateRadiusVector(event.x,event.y);if(!mouseMoveVector){return true;}
event.consume(true);let axis,angle;if(event.shiftKey){axis=new UI.Geometry.Vector(0,0,-1);angle=(this._mouseDownVector.x-mouseMoveVector.x)*ShiftDragOrientationSpeed;}else{axis=UI.Geometry.crossProduct(this._mouseDownVector,mouseMoveVector);angle=UI.Geometry.calculateAngle(this._mouseDownVector,mouseMoveVector);}
let currentMatrix=new WebKitCSSMatrix();currentMatrix=currentMatrix.rotate(-90,0,0).rotateAxisAngle(axis.x,axis.y,axis.z,angle).rotate(90,0,0).multiply(this._originalBoxMatrix);const eulerAngles=UI.Geometry.EulerAngles.fromRotationMatrix(currentMatrix);const newOrientation=new SDK.EmulationModel.DeviceOrientation(-eulerAngles.alpha,-eulerAngles.beta,eulerAngles.gamma);this._setDeviceOrientation(newOrientation,DeviceOrientationModificationSource.UserDrag);this._setSelectElementLabel(this._orientationSelectElement,NonPresetOptions.Custom);return false;}
_onBoxDragStart(event){if(!this._deviceOrientationOverrideEnabled){return false;}
this._mouseDownVector=this._calculateRadiusVector(event.x,event.y);this._originalBoxMatrix=this._boxMatrix;if(!this._mouseDownVector){return false;}
event.consume(true);return true;}
_calculateRadiusVector(x,y){const rect=this._stageElement.getBoundingClientRect();const radius=Math.max(rect.width,rect.height)/2;const sphereX=(x-rect.left-rect.width/2)/radius;const sphereY=(y-rect.top-rect.height/2)/radius;const sqrSum=sphereX*sphereX+sphereY*sphereY;if(sqrSum>0.5){return new UI.Geometry.Vector(sphereX,sphereY,0.5/Math.sqrt(sqrSum));}
return new UI.Geometry.Vector(sphereX,sphereY,Math.sqrt(1-sqrSum));}
_appendTouchControl(){const groupElement=this.contentElement.createChild('div','sensors-group');const title=UI.UIUtils.createLabel(ls`Touch`,'sensors-group-title');groupElement.appendChild(title);const fieldsElement=groupElement.createChild('div','sensors-group-fields');const select=fieldsElement.createChild('select','chrome-select');UI.ARIAUtils.bindLabelToControl(title,select);select.appendChild(new Option(Common.UIString.UIString('Device-based'),'auto'));select.appendChild(new Option(Common.UIString.UIString('Force enabled'),'enabled'));select.addEventListener('change',applyTouch,false);const reloadWarning=groupElement.createChild('div','reload-warning hidden');reloadWarning.textContent=Common.UIString.UIString('*Requires reload');UI.ARIAUtils.markAsAlert(reloadWarning);function applyTouch(){for(const emulationModel of self.SDK.targetManager.models(SDK.EmulationModel.EmulationModel)){emulationModel.overrideEmulateTouch(select.value==='enabled');}
reloadWarning.classList.remove('hidden');const resourceTreeModel=self.SDK.targetManager.models(SDK.ResourceTreeModel.ResourceTreeModel)[0];if(resourceTreeModel){resourceTreeModel.once(SDK.ResourceTreeModel.Events.MainFrameNavigated).then(()=>reloadWarning.classList.add('hidden'));}}}}
export const DeviceOrientationModificationSource={UserInput:'userInput',UserDrag:'userDrag',ResetButton:'resetButton',SelectPreset:'selectPreset'};export const NonPresetOptions={NoOverride:'noOverride',Custom:'custom',Unavailable:'unavailable'};export const PresetOrientations=[{title:ls`Presets`,value:[{title:Common.UIString.UIString('Portrait'),orientation:'[0, 90, 0]'},{title:Common.UIString.UIString('Portrait upside down'),orientation:'[180, -90, 0]'},{title:Common.UIString.UIString('Landscape left'),orientation:'[0, 90, -90]'},{title:Common.UIString.UIString('Landscape right'),orientation:'[0, 90, 90]'},{title:Common.UIString.UIString('Display up'),orientation:'[0, 0, 0]'},{title:Common.UIString.UIString('Display down'),orientation:'[0, 180, 0]'}]}];export class ShowActionDelegate{handleAction(context,actionId){self.UI.viewManager.showView('sensors');return true;}}
export const ShiftDragOrientationSpeed=16;