- 1 :
/* global log -- eslint */
- 2 :
- 3 :
/**
- 4 :
* @file This file provides functions and utilities specifically for the smartphone layout of IITC.
- 5 :
* @module smartphone
- 6 :
*/
- 7 :
- 8 :
/**
- 9 :
* Determines if the user's device is a smartphone.
- 10 :
* Note it should not detect tablets because their display is large enough to use the desktop version.
- 11 :
* The stock intel site allows forcing mobile/full sites with a vp=m or vp=f parameter. This function supports the same.
- 12 :
*
- 13 :
* @function isSmartphone
- 14 :
* @returns {boolean} True if the user's device is a smartphone, false otherwise.
- 15 :
*/
- 16 :
window.isSmartphone = function () {
- 17 :
// this check is also used in main.js. Note it should not detect
- 18 :
// tablets because their display is large enough to use the desktop
- 19 :
// version.
- 20 :
- 21 :
// The stock intel site allows forcing mobile/full sites with a vp=m or vp=f
- 22 :
// parameter - let's support the same. (stock only allows this for some
- 23 :
// browsers - e.g. android phone/tablet. let's allow it for all, but
- 24 :
// no promises it'll work right)
- 25 :
var viewParam = window.getURLParam('vp');
- 26 :
if (viewParam === 'm') return true;
- 27 :
if (viewParam === 'f') return false;
- 28 :
- 29 :
return !!(navigator.userAgent.match(/Android.*Mobile/) || navigator.userAgent.match(/iPhone|iPad|iPod/i));
- 30 :
};
- 31 :
- 32 :
/**
- 33 :
* Placeholder for smartphone specific manipulations.
- 34 :
* This function does not implement any logic by itself.
- 35 :
*
- 36 :
* @function smartphone
- 37 :
*/
- 38 :
window.smartphone = function () {};
- 39 :
- 40 :
/**
- 41 :
* Performs initial setup tasks for IITC on smartphones before the IITC boot process.
- 42 :
* This includes adding smartphone-specific stylesheets
- 43 :
* and modifying some of the setup functions for mobile compatibility.
- 44 :
*
- 45 :
* @function runOnSmartphonesBeforeBoot
- 46 :
*/
- 47 :
window.runOnSmartphonesBeforeBoot = function () {
- 48 :
if (!window.isSmartphone()) return;
- 49 :
log.warn('running smartphone pre boot stuff');
- 50 :
- 51 :
// add smartphone stylesheet
- 52 :
var style = document.createElement('style');
- 53 :
style.type = 'text/css';
- 54 :
style.appendChild(document.createTextNode('@include_string:smartphone.css@'));
- 55 :
document.head.appendChild(style);
- 56 :
- 57 :
// don’t need many of those
- 58 :
window.setupStyles = function () {
- 59 :
$('head').append(
- 60 :
'<style>' +
- 61 :
[
- 62 :
'#largepreview.enl img { border:2px solid ' + window.COLORS[window.TEAM_ENL] + '; } ',
- 63 :
'#largepreview.res img { border:2px solid ' + window.COLORS[window.TEAM_RES] + '; } ',
- 64 :
'#largepreview.none img { border:2px solid ' + window.COLORS[window.TEAM_NONE] + '; } ',
- 65 :
].join('\n') +
- 66 :
'</style>'
- 67 :
);
- 68 :
};
- 69 :
- 70 :
window.smartphone.mapButton = $('<a>map</a>').click(function () {
- 71 :
window.show('map');
- 72 :
$('#map').css({ visibility: 'visible', opacity: '1' });
- 73 :
$('#updatestatus').show();
- 74 :
$('#chatcontrols a.active').removeClass('active');
- 75 :
$("#chatcontrols a:contains('map')").addClass('active');
- 76 :
});
- 77 :
- 78 :
window.smartphone.sideButton = $('<a>info</a>').click(function () {
- 79 :
window.show('info');
- 80 :
$('#scrollwrapper').show();
- 81 :
window.resetScrollOnNewPortal();
- 82 :
$('#chatcontrols a.active').removeClass('active');
- 83 :
$("#chatcontrols a:contains('info')").addClass('active');
- 84 :
});
- 85 :
- 86 :
$('#chatcontrols').append(window.smartphone.mapButton).append(window.smartphone.sideButton);
- 87 :
- 88 :
if (!window.useAppPanes()) {
- 89 :
document.body.classList.add('show_controls');
- 90 :
}
- 91 :
- 92 :
window.addHook('portalDetailsUpdated', function () {
- 93 :
var x = $('.imgpreview img').removeClass('hide');
- 94 :
- 95 :
if (!x.length) {
- 96 :
$('.fullimg').remove();
- 97 :
return;
- 98 :
}
- 99 :
- 100 :
if ($('.fullimg').length) {
- 101 :
$('.fullimg').replaceWith(x.addClass('fullimg'));
- 102 :
} else {
- 103 :
x.addClass('fullimg').appendTo('#sidebar');
- 104 :
}
- 105 :
});
- 106 :
};
- 107 :
- 108 :
/**
- 109 :
* Updates the mobile information bar with portal details when a portal is selected.
- 110 :
* This function is hooked to the 'portalSelected' event and is specific to the smartphone layout.
- 111 :
*
- 112 :
* @function smartphoneInfo
- 113 :
* @param {Object} selectedPortalData - The object containing details about the selected portal.
- 114 :
*/
- 115 :
window.smartphoneInfo = function (selectedPortalData) {
- 116 :
var guid = selectedPortalData.selectedPortalGuid;
- 117 :
if (!window.portals[guid]) return;
- 118 :
- 119 :
var data = window.portals[window.selectedPortal].options.data;
- 120 :
if (typeof data.title === 'undefined') return;
- 121 :
- 122 :
var details = window.portalDetail.get(guid);
- 123 :
- 124 :
var lvl = data.level;
- 125 :
let t;
- 126 :
if (data.team === 'N' || data.team === 'NEUTRAL') t = '<span class="portallevel">L0</span>';
- 127 :
else t = '<span class="portallevel" style="background: ' + window.COLORS_LVL[lvl] + ';">L' + lvl + '</span>';
- 128 :
- 129 :
var percentage = data.health;
- 130 :
if (details) {
- 131 :
var totalEnergy = window.getTotalPortalEnergy(details);
- 132 :
if (window.getTotalPortalEnergy(details) > 0) {
- 133 :
percentage = Math.floor((window.getCurrentPortalEnergy(details) / totalEnergy) * 100);
- 134 :
}
- 135 :
}
- 136 :
t += ' ' + percentage + '% ';
- 137 :
t += data.title;
- 138 :
- 139 :
if (details) {
- 140 :
var l, v, max, perc;
- 141 :
var eastAnticlockwiseToNorthClockwise = [2, 1, 0, 7, 6, 5, 4, 3];
- 142 :
- 143 :
for (var ind = 0; ind < 8; ind++) {
- 144 :
let slot, reso;
- 145 :
if (details.resonators.length === 8) {
- 146 :
slot = eastAnticlockwiseToNorthClockwise[ind];
- 147 :
reso = details.resonators[slot];
- 148 :
} else {
- 149 :
slot = null;
- 150 :
reso = ind < details.resonators.length ? details.resonators[ind] : null;
- 151 :
}
- 152 :
- 153 :
var className = window.TEAM_TO_CSS[window.getTeam(details)];
- 154 :
if (slot !== null && window.OCTANTS[slot] === 'N') className += ' north';
- 155 :
if (reso) {
- 156 :
l = parseInt(reso.level);
- 157 :
v = parseInt(reso.energy);
- 158 :
max = window.RESO_NRG[l];
- 159 :
perc = (v / max) * 100;
- 160 :
} else {
- 161 :
l = 0;
- 162 :
v = 0;
- 163 :
max = 0;
- 164 :
perc = 0;
- 165 :
}
- 166 :
- 167 :
t += '<div class="resonator ' + className + '" style="border-top-color: ' + window.COLORS_LVL[l] + ';left: ' + (100 * ind) / 8.0 + '%;">';
- 168 :
t += '<div class="filllevel" style="width:' + perc + '%;"></div>';
- 169 :
t += '</div>';
- 170 :
}
- 171 :
}
- 172 :
- 173 :
$('#mobileinfo').html(t);
- 174 :
};
- 175 :
- 176 :
/**
- 177 :
* Performs setup tasks for IITC on smartphones after the IITC boot process.
- 178 :
* This includes initializing mobile info display, adjusting UI elements for mobile compatibility,
- 179 :
* and setting event handlers for mobile-specific interactions.
- 180 :
*
- 181 :
* @function runOnSmartphonesAfterBoot
- 182 :
*/
- 183 :
window.runOnSmartphonesAfterBoot = function () {
- 184 :
if (!window.isSmartphone()) return;
- 185 :
log.warn('running smartphone post boot stuff');
- 186 :
- 187 :
window.show('map');
- 188 :
- 189 :
// add a div/hook for updating mobile info
- 190 :
$('#updatestatus').prepend('<div id="mobileinfo" onclick="show(\'info\')"></div>');
- 191 :
window.addHook('portalSelected', window.smartphoneInfo);
- 192 :
window.addHook('portalDetailLoaded', (data) => {
- 193 :
if (data.success && data.guid === window.selectedPortal) {
- 194 :
window.smartphoneInfo({ selectedPortalGuid: data.guid });
- 195 :
}
- 196 :
});
- 197 :
- 198 :
// init msg of status bar. hint for the user that a tap leads to the info screen
- 199 :
$('#mobileinfo').html('<div style="text-align: center"><b>tap here for info screen</b></div>');
- 200 :
- 201 :
// replace img full view handler
- 202 :
$('#portaldetails')
- 203 :
.off('click', '.imgpreview')
- 204 :
.on('click', '.imgpreview', function (e) {
- 205 :
if (e.currentTarget === e.target) {
- 206 :
// do not fire on #level
- 207 :
$('.ui-tooltip').remove();
- 208 :
var newTop = $('.fullimg').position().top + $('#sidebar').scrollTop();
- 209 :
$('#sidebar').animate({ scrollTop: newTop }, 200);
- 210 :
}
- 211 :
});
- 212 :
};