mobile.system 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  1. <html>
  2. <head>
  3. <title>ArozOS Mobile</title>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <link rel="manifest" href="manifest.webmanifest">
  7. <link rel="stylesheet" href="script/semantic/semantic.css">
  8. <link rel="stylesheet" href="script/ao.css">
  9. <script type="text/javascript" src="script/jquery.min.js"></script>
  10. <script type="text/javascript" src="script/semantic/semantic.js"></script>
  11. <script type="text/javascript" src="script/ao_module.js"></script>
  12. <style>
  13. document, body{
  14. height: 100%;
  15. }
  16. .themeColor{
  17. background-color:#1c1c1c;
  18. }
  19. .taskBar{
  20. position:fixed;
  21. top:0px;
  22. left:0px;
  23. width:30px;
  24. height:100%;
  25. overflow: visible !important;
  26. z-index:999;
  27. }
  28. #mainFrame{
  29. width: calc(100% - 30px);
  30. position:fixed;
  31. top:0px;
  32. right:0px;
  33. overflow: hidden;
  34. }
  35. .toggleTaskBar{
  36. position:absolute;
  37. bottom:0px;
  38. right:0px;
  39. margin-right:-20px;
  40. width:30px;
  41. height:90px;
  42. border-radius: 0px 10px 10px 0px;
  43. }
  44. #listMenu{
  45. z-index:1000;
  46. position:fixed;
  47. top:0px;
  48. left:0px;
  49. width:100%;
  50. height:100%;
  51. padding:12px;
  52. background-color: #fcffff;
  53. box-shadow: 3px 3px 5px 0px rgba(207, 207, 207, 0.37);
  54. }
  55. #listMenu .searchBar {
  56. width: 100%;
  57. border-bottom: 2px solid #34b7eb;
  58. }
  59. #listMenu .listItemWrapper {
  60. overflow: hidden;
  61. }
  62. #listMenu .listItemWrapper .groups {
  63. background-color: #f5f5f5;
  64. width: 120px;
  65. height: calc(100% - 40px);
  66. display: inline-block;
  67. overflow-y: auto;
  68. padding-top: 8px;
  69. }
  70. #listMenu .listItemWrapper .groups .item {
  71. padding-left: 7px;
  72. padding-bottom: 6px;
  73. padding-top: 6px;
  74. cursor: pointer;
  75. }
  76. #listMenu .listItemWrapper .groups .item.selected {
  77. color: #34b7eb;
  78. }
  79. #listMenu .listItemWrapper .groups .item:hover {
  80. background-color: #dedede;
  81. }
  82. #listMenuItem{
  83. width: calc(100% - 130px) !important;
  84. float: right;
  85. overflow-y: auto;
  86. height: calc(100% - 40px) !important;
  87. }
  88. #listMenuItem img{
  89. width: 50px;
  90. }
  91. .module.item{
  92. padding:8px;
  93. }
  94. .hideListMenuButton{
  95. position: absolute;
  96. bottom:22px;
  97. left:32px;
  98. cursor:pointer;
  99. }
  100. .hideListMenuButton img{
  101. left:12px;
  102. width:50px;
  103. }
  104. .listMenuLauncher{
  105. position:absolute;
  106. bottom:12px;
  107. left:12px;
  108. }
  109. .listMenuLauncher .functionbtn{
  110. cursor:pointer;
  111. }
  112. .blurred{
  113. filter: blur(3px);
  114. }
  115. #backdrop {
  116. background-repeat: no-repeat;
  117. background-size: cover;
  118. background-position: center;
  119. background-image: url('img/desktop/bg/init.jpg');
  120. width: 100%;
  121. height: 100%;
  122. overflow-x: hidden;
  123. pointer-events: none;
  124. }
  125. #windowButtonWrapper{
  126. padding-top:6px;
  127. }
  128. .floatWindowButton{
  129. padding: 5px;
  130. }
  131. .floatWindowButton .minimizedIcon{
  132. width: 20px;
  133. height:20px;
  134. }
  135. .floatWindowButton .normalElements{
  136. padding:8px;
  137. border-bottom: 1px solid #4a4a4a;
  138. cursor:pointer;
  139. vertical-align:middle;
  140. position: relative;
  141. }
  142. .floatWindowButton .normalizedIcon{
  143. width:40;
  144. height:40px;
  145. margin-right:12px;
  146. }
  147. .normalElements .windowTitle{
  148. display:inline-block;
  149. width:200px !important;
  150. vertical-align:middle;
  151. white-space: nowrap;
  152. overflow: hidden;
  153. text-overflow: ellipsis;
  154. }
  155. .fwtab{
  156. position: absolute;
  157. top:0px;
  158. right: 0px;
  159. width: 100%;
  160. height: 100%;
  161. }
  162. #windowWrapper{
  163. height: 100%;
  164. width: 100%;
  165. position: absolute;
  166. top:0px;
  167. right:0px;
  168. }
  169. .floatWindowWrapper{
  170. width: 100%;
  171. height: 100%;
  172. }
  173. .floatWindow{
  174. width: 100%;
  175. height: 100%;
  176. position: absolute;
  177. }
  178. .fwtab iframe{
  179. border: 0px solid transparent;
  180. height: 100%;
  181. }
  182. .floatWindowButton .closebutton{
  183. position: absolute;
  184. font-size: 120%;
  185. color:white;
  186. right: 0em;
  187. top: 0px;
  188. margin-top: -8px;
  189. margin-left: -4px;
  190. padding: 3px;
  191. }
  192. .floatWindowButton .externalbutton{
  193. position: absolute;
  194. font-size: 120%;
  195. color:white;
  196. right: 1.6em;
  197. top: 0px;
  198. margin-top: -8px;
  199. margin-left: -4px;
  200. padding: 3px;
  201. }
  202. #conndrop{
  203. padding: 0.5em;
  204. position: fixed;
  205. top: 0px;
  206. right: 0px;
  207. z-index: 115;
  208. width: 100px;
  209. display: none;
  210. justify-content: flex-end;
  211. pointer-events: none;
  212. }
  213. .extendOnly{
  214. display:none;
  215. }
  216. /* Magic css to make the connection logo blink */
  217. @-moz-keyframes blink {
  218. 0% {
  219. opacity:1;
  220. }
  221. 50% {
  222. opacity:0;
  223. }
  224. 100% {
  225. opacity:1;
  226. }
  227. }
  228. @-webkit-keyframes blink {
  229. 0% {
  230. opacity:1;
  231. }
  232. 50% {
  233. opacity:0;
  234. }
  235. 100% {
  236. opacity:1;
  237. }
  238. }
  239. /* IE */
  240. @-ms-keyframes blink {
  241. 0% {
  242. opacity:1;
  243. }
  244. 50% {
  245. opacity:0;
  246. }
  247. 100% {
  248. opacity:1;
  249. }
  250. }
  251. /* Opera and prob css3 final iteration */
  252. @keyframes blink {
  253. 0% {
  254. opacity:1;
  255. }
  256. 50% {
  257. opacity:0;
  258. }
  259. 100% {
  260. opacity:1;
  261. }
  262. }
  263. .blink-image {
  264. -moz-animation: blink normal 2s infinite ease-in-out; /* Firefox */
  265. -webkit-animation: blink normal 2s infinite ease-in-out; /* Webkit */
  266. -ms-animation: blink normal 2s infinite ease-in-out; /* IE */
  267. animation: blink normal 2s infinite ease-in-out; /* Opera and prob css3 final iteration */
  268. }
  269. #sidebarToggleOverlay{
  270. width: 100%;
  271. height: 100%;
  272. z-index: 995;
  273. position: fixed;
  274. top:0px;
  275. left:0px;
  276. display:none;
  277. }
  278. #userprofile{
  279. z-index: 90;
  280. position: fixed;
  281. top: 0px;
  282. left: 3em;
  283. right: 3em;
  284. background-color: rgba(255,255,255,0.95);
  285. backdrop-filter: blur(4px);
  286. border-bottom-left-radius: 20px;
  287. border-bottom-right-radius: 20px;
  288. padding-left: 1.2em;
  289. padding-right: 1.2em;
  290. padding-top: 1.2em;
  291. display:none;
  292. box-shadow: 6px 8px 5px 2px rgba(0,0,0,0.2);
  293. -webkit-box-shadow: 6px 8px 5px 2px rgba(0,0,0,0.2);
  294. -moz-box-shadow: 6px 8px 5px 2px rgba(0,0,0,0.2);
  295. }
  296. .clock{
  297. position: fixed;
  298. left: 0px;
  299. width: 100%;
  300. top: 0px;
  301. padding-top: 0.3em;
  302. padding-bottom: 0.7em;
  303. color: white;
  304. text-align: center;
  305. pointer-events: none;
  306. background: rgb(255,255,255);
  307. background: linear-gradient(0deg, rgba(255,255,255,0) 2%, rgba(6,6,6,0.4479635060791801) 44%, rgba(29,29,29,1) 100%);
  308. }
  309. </style>
  310. </head>
  311. <body>
  312. <div class="taskBar themeColor" >
  313. <div class="toggleTaskBar themeColor" shown="false" onclick="toggleTaskBar(this);">
  314. <img class="ui image sidebararrow" style="margin-top:8px; margin-left: -10px;" src="img/mobile/keyboard_arrow_right-white-48dp.svg"></img>
  315. </div>
  316. <div class="listMenuLauncher">
  317. <img onclick="showListMenu();" class="functionbtn" src="img/mobile/apps-white-48dp.svg" style="width: 30px;"/>
  318. <img onclick="showProfileInfo();" class="functionbtn extendOnly" src="img/mobile/account_circle_white_48dp.svg" style="width: 30px;"/>
  319. <img onclick="openDesktopCustomization();" class="functionbtn extendOnly" src="img/mobile/palette_white_48dp.svg" style="width: 30px;"/>
  320. <img onclick="openDesktopAsFolder();" class="functionbtn extendOnly" src="img/mobile/folder_open_white_24dp.svg" style="width: 30px;"/>
  321. <img onclick="fullscreen();" class="functionbtn extendOnly" src="img/mobile/fullscreen_white_48dp.svg" style="width: 30px;"/>
  322. <img onclick="openSystemSettings();" class="functionbtn extendOnly" src="img/mobile/tune_white_24dp.svg" style="width: 30px;"/>
  323. <img onclick="showDesktop();" class="functionbtn extendOnly" src="img/mobile/layers_clear_white_48dp.svg" style="width: 30px;"/>
  324. </div>
  325. <div id="windowButtonWrapper">
  326. </div>
  327. </div>
  328. <div id="userprofile">
  329. <div class="ui minimal comments">
  330. <div class="ui comment">
  331. <div class="avatar">
  332. <img class="usericon" src="img/desktop/system_icon/user.svg">
  333. </div>
  334. <div class="content">
  335. <dic class="author" id="username">User</dic>
  336. <div class="text" id="usergroups">@user</div>
  337. </div>
  338. </div>
  339. </div>
  340. <button onclick="logout();" class="ui basic blue mini button" style="position: absolute; top: 1em; right: 1em;">Logout</button>
  341. <button onclick="toggleProfileInfo();" class="circular ui themecolor icon button" style="position: absolute; bottom: 0px; right: 0px; margin-bottom: -10px; margin-right: -10px; color: white;">
  342. <i class="remove icon"></i>
  343. </button>
  344. </div>
  345. <div id="listMenu" style="left:-100%;">
  346. <div class="searchBar" onkeydown="searchModule(event);">
  347. <div class="ui icon fluid input" style="border-radius: 0px !important;">
  348. <input id="searchBar" type="text" placeholder="Search">
  349. <i class="search icon"></i>
  350. </div>
  351. </div>
  352. <dib class="listItemWrapper">
  353. <div class="groups">
  354. <div id="searchResults" class="item" style="display:none;">Search Results</div>
  355. <div class="item groupType selected" group="All">All</div>
  356. <div class="item groupType" group="Media">Media</div>
  357. <div class="item groupType" group="Office">Office</div>
  358. <div class="item groupType" group="Download">Download</div>
  359. <div class="item groupType" group="Files">Files</div>
  360. <div class="item groupType" group="Internet">Internet</div>
  361. <div class="item groupType" group="System Settings">System Settings</div>
  362. <div class="item groupType" group="System Tools">System Tools</div>
  363. <div class="item groupType" group="Utilities">Utilities</div>
  364. <div class="item groupType" group="Other">Other</div>
  365. <div class="hideListMenuButton" onclick="closeListMenu();">
  366. <img class="ui image" src="img/mobile/cancel-black-48dp.svg"></img>
  367. <p>Close Menu</p>
  368. </div>
  369. </div>
  370. <div id="listMenuItem" class="items" align="left">
  371. </div>
  372. </div>
  373. </div>
  374. <div id="mainFrame">
  375. <div id="backdrop">
  376. </div>
  377. <div class="clock">
  378. ArozOS Desktop
  379. </div>
  380. <div id="windowWrapper">
  381. </div>
  382. <div id="conndrop">
  383. <img class="ui mini image blink-image" src="SystemAO/desktop/icons/connlost.svg">
  384. </div>
  385. </div>
  386. <div id="sidebarToggleOverlay"></div>
  387. <script>
  388. var isDesktopMode = true; //Try to emulate Desktop mode
  389. var moduleInstalled = []; //List of installed modules on the system
  390. var desktopThemeList = []; //List of themes installed, same as desktop theme
  391. var listMenuShown = false;
  392. var hostInfo;
  393. //IME mockup
  394. window.ime = null;
  395. //Clock related
  396. var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
  397. var daysNames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
  398. //initiation Functions
  399. initHostInfo();
  400. initModuleList();
  401. bindGroupTypeEvents();
  402. initBackdropImage();
  403. initUserDefinedThemeColor();
  404. bindBackgroundClickActions();
  405. initStartupSounds();
  406. initDesktopUserInfo();
  407. //Bind background click
  408. function bindBackgroundClickActions(){
  409. $("#mainFrame").on("touchstart click", function(evt){
  410. if ($(this).hasClass("blurred") && $(".taskBar").find(".toggleTaskBar").attr("shown") == "true"){
  411. //hide the taskbar
  412. hideTaskBar();
  413. }
  414. });
  415. $("#sidebarToggleOverlay").on("touchstart click", function(evt){
  416. if ($(".taskBar").find(".toggleTaskBar").attr("shown") == "true"){
  417. //hide the taskbar
  418. evt.preventDefault();
  419. hideTaskBar();
  420. }
  421. });
  422. }
  423. //Connection check
  424. setInterval(function() {
  425. $.ajax({
  426. url: 'system/auth/checkLogin',
  427. success: function(data) {
  428. if (data == true) {
  429. //Continue session
  430. } else {
  431. //Session timeout. Redirect to system index
  432. window.location.href = "index.html";
  433. }
  434. $("#conndrop").hide();
  435. $("#conndrop").css("display", "none");
  436. },
  437. error: function(evt) {
  438. //Server closed or freezed?
  439. $("#conndrop").show();
  440. $("#conndrop").css("display", "flex");
  441. },
  442. timeout: 15000
  443. });
  444. }, 15000);
  445. //Initiate the host information
  446. function initHostInfo(){
  447. $.get("system/desktop/host",function(data){
  448. hostInfo = data;
  449. document.title = hostInfo.Hostname;
  450. });
  451. }
  452. //Initialize background image
  453. function initBackdropImage(){
  454. $.get("system/desktop/theme", function(data) {
  455. //Return a list of theme stored on the system
  456. desktopThemeList = data;
  457. $.get("system/desktop/theme?get=true", function(data) {
  458. //Get the user theme settings
  459. changeDesktopTheme(data);
  460. });
  461. });
  462. }
  463. function initUserDefinedThemeColor(){
  464. $.ajax({
  465. url: "../../system/file_system/preference",
  466. data: {key: "themecolor"},
  467. success: function(data){
  468. if (data.error == undefined && data != ""){
  469. $(".themeColor").css("background-color", data);
  470. }
  471. }
  472. });
  473. }
  474. function changeDesktopTheme(themename){
  475. //Match the given theme to the themename
  476. if (themename.includes(":/") == false){
  477. //This is a path
  478. for (var i =0; i < desktopThemeList.length ; i++){
  479. if (desktopThemeList[i].Theme == themename){
  480. var targetImage = desktopThemeList[i].Bglist[0];
  481. $("#backdrop").css("background-image", `url(img/desktop/bg/${themename}/${targetImage})`)
  482. }
  483. }
  484. }else{
  485. //This is a path (user defined background folder)
  486. $.get("system/desktop/theme?load=" + themename, function(data){
  487. if (data.error !== undefined){
  488. //The folder is gone. Use default instead
  489. console.log(data.error);
  490. changeDesktopTheme("default");
  491. }else{
  492. $("#backdrop").css("background-image", `url(media/?file=${data[0]})`)
  493. }
  494. });
  495. }
  496. }
  497. function toggleFullScreen() {
  498. var doc = window.document;
  499. var docEl = doc.documentElement;
  500. var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen;
  501. var cancelFullScreen = doc.exitFullscreen || doc.mozCancelFullScreen || doc.webkitExitFullscreen || doc.msExitFullscreen;
  502. if(!doc.fullscreenElement && !doc.mozFullScreenElement && !doc.webkitFullscreenElement && !doc.msFullscreenElement) {
  503. requestFullScreen.call(docEl);
  504. }
  505. else {
  506. cancelFullScreen.call(doc);
  507. }
  508. }
  509. //Sidebar
  510. function toggleTaskBar(obj){
  511. if ($(obj).attr("shown") == "true"){
  512. hideTaskBar();
  513. }else{
  514. showTaskBar();
  515. }
  516. }
  517. function hideTaskBar(){
  518. //Hide the taskBar
  519. $(".taskBar").animate({
  520. width: "30px"
  521. },300, "swing");
  522. $(".taskBar").find('.sidebararrow').attr("src","img/mobile/keyboard_arrow_right-white-48dp.svg");
  523. $(".taskBar").find(".toggleTaskBar").attr("shown","false");
  524. $("#mainFrame").removeClass("blurred");
  525. //Minimize all fwbuttons
  526. $(".floatWindowButton").each(function(){
  527. $(this).find(".minimizedElements").show();
  528. $(this).find(".normalElements").hide();
  529. });
  530. $("#sidebarToggleOverlay").hide();
  531. $(".extendOnly").slideUp("fast");
  532. }
  533. function showTaskBar(){
  534. //Show the taskbar
  535. $(".taskBar").animate({
  536. width: "300px"
  537. }, 300, "swing", function(){
  538. //Switch all fwbuttons to normal size
  539. $(".floatWindowButton").each(function(){
  540. $(this).find(".minimizedElements").hide();
  541. $(this).find(".normalElements").show();
  542. });
  543. $(".extendOnly").slideDown("fast");
  544. });
  545. $(".taskBar").find('.sidebararrow').attr("src","img/mobile/keyboard_arrow_left-white-48dp.svg");
  546. $(".taskBar").find(".toggleTaskBar").attr("shown","true");
  547. $("#mainFrame").addClass("blurred");
  548. $("#sidebarToggleOverlay").show();
  549. }
  550. //List all modules
  551. function initModuleList(){
  552. $.ajax({
  553. url: "system/modules/list",
  554. success: function(data) {
  555. moduleInstalled = data;
  556. listModulesType("All");
  557. }
  558. });
  559. }
  560. //ListMenu group classification events
  561. function bindGroupTypeEvents(){
  562. $(".groupType").on("click",function(evt){
  563. //Clear all serach results
  564. $("#searchResults").slideUp('fast');
  565. listModulesType($(this).attr("group"));
  566. $(".groupType.selected").removeClass("selected");
  567. $(this).addClass("selected");
  568. /*
  569. var classificationObject = this;
  570. if ($(this).attr("group") == "All"){
  571. $('.item.module').show();
  572. } else if ($(this).attr("group") == "Other"){
  573. var excludeList = ["Media", "Office", "Download", "Files", "Internet", "System Settings", "System Tools", "Utilties"];
  574. $('.item.module').each(function(){
  575. if (excludeList.includes($(this).attr("group")) == false){
  576. $(this).show();
  577. }else{
  578. $(this).hide();
  579. }
  580. });
  581. }else{
  582. $('.item.module').each(function(){
  583. if ($(this).attr("group") == $(classificationObject).attr("group")){
  584. $(this).show();
  585. }else{
  586. $(this).hide();
  587. }
  588. });
  589. }
  590. */
  591. });
  592. }
  593. function searchModule(event) {
  594. if (event.which == 13) {
  595. var keyword = $("#searchBar").val().toLowerCase();
  596. var results = [];
  597. var lessAccurateResults = [];
  598. $(".groupType.selected").removeClass("selected");
  599. $("#searchResults").addClass("selected").slideDown('fast');
  600. //Load all search results
  601. for (var i = 0; i < moduleInstalled.length; i++) {
  602. var thisModule = moduleInstalled[i];
  603. var pathInfo = thisModule["StartDir"].split("/");
  604. for (var j = 0; j < pathInfo.length; j++) {
  605. pathInfo[j] = pathInfo[j].toLowerCase();
  606. }
  607. if (thisModule["Name"].toLowerCase().includes(keyword)) {
  608. results.push(thisModule);
  609. } else if (pathInfo.includes(keyword.toLowerCase()) || pathInfo.includes(keyword.split(" ").join("_").toLowerCase())) {
  610. lessAccurateResults.push(thisModule);
  611. }
  612. }
  613. results = results.concat(lessAccurateResults);
  614. //Append the results to list
  615. $("#listMenuItem").html("");
  616. for (var i = 0; i < results.length; i++) {
  617. generateListMenuItem(results[i]);
  618. }
  619. if (results.length == 0) {
  620. //Append a custom no results div to the content
  621. $("#listMenuItem").append(`<div class="item module"><span><img class="ui middle aligned tiny image" src="img/system/not found.png" style="padding-right: 12px;">No Results</span></div>`);
  622. }
  623. }
  624. }
  625. function listModulesType(groupType) {
  626. var listingItems = [];
  627. if (groupType == "All") {
  628. //List all of the items
  629. for (var i = 0; i < moduleInstalled.length; i++) {
  630. if (moduleInstalled[i]["StartDir"] != "") {
  631. listingItems.push(moduleInstalled[i]);
  632. }
  633. }
  634. } else if (groupType == "Other") {
  635. var excludeList = ["Media", "Office", "Download", "Files", "Internet", "System Settings", "System Tools", "Utilties"];
  636. //List the Other groups
  637. for (var i = 0; i < moduleInstalled.length; i++) {
  638. if (excludeList.includes(moduleInstalled[i]["Group"]) == false && moduleInstalled[i]["StartDir"] != "") {
  639. listingItems.push(moduleInstalled[i]);
  640. }
  641. }
  642. } else {
  643. //List the given group
  644. for (var i = 0; i < moduleInstalled.length; i++) {
  645. if (moduleInstalled[i]["Group"] == groupType && moduleInstalled[i]["StartDir"] != "") {
  646. listingItems.push(moduleInstalled[i]);
  647. }
  648. }
  649. }
  650. //List the item to the listmenu
  651. $("#listMenuItem").html("");
  652. for (var i = 0; i < listingItems.length; i++) {
  653. var thisModule = listingItems[i];
  654. generateListMenuItem(thisModule);
  655. }
  656. if (listingItems.length == 0) {
  657. $("#listMenuItem").html(`<div class="item module"><span><img class="ui middle aligned tiny image" src="img/system/not found.png" style="padding-right: 12px;">No WebApp found</span></div>`)
  658. }
  659. }
  660. function generateListMenuItem(thisModule) {
  661. var icon = thisModule["IconPath"];
  662. if (icon == "") {
  663. //Use default system icon
  664. icon = "img/system/service.png";
  665. }
  666. var name = thisModule["Name"];
  667. var startdir = thisModule["StartDir"];
  668. var group = thisModule["Group"];
  669. var fwsupport = "false";
  670. if (thisModule["SupportFW"]) {
  671. fwsupport = "true";
  672. }
  673. $("#listMenuItem").append(`<div class="item module" module="${name}" startdir="${startdir}" fw="${fwsupport}" group="${group}" onclick="openModuleFromMenu(this);">
  674. <span>
  675. <img class="ui middle aligned tiny image" src="${icon}" style="padding-right: 12px;"></img>
  676. ${name}
  677. </span>
  678. </div>`);
  679. }
  680. function closeListMenu(callback = undefined){
  681. $("#listMenu").animate({
  682. left: window.innerWidth * -1
  683. },300,"swing", function(){
  684. $(".taskBar").animate({
  685. width: "300px",
  686. },300,"swing", function(){
  687. if (typeof callback != "undefined"){
  688. callback();
  689. }else{
  690. $(".extendOnly").slideDown("fast");
  691. }
  692. });
  693. });
  694. listMenuShown = false;
  695. }
  696. //Bind swip events
  697. document.addEventListener('touchstart', handleTouchStart, false);
  698. document.addEventListener('touchmove', handleTouchMove, false);
  699. var xDown = null;
  700. var yDown = null;
  701. var swipeTarget = null;
  702. var targetType = "fw";
  703. function getTouches(evt) {
  704. return evt.touches || // browser API
  705. evt.originalEvent.touches; // jQuery
  706. }
  707. function handleTouchStart(evt) {
  708. const firstTouch = getTouches(evt)[0];
  709. if ($(evt.target).hasClass("taskBar")){
  710. swipeTarget = evt.target;
  711. targetType = "taskbar"
  712. }else if ($(evt.target).hasClass("toggleTaskBar")){
  713. }else{
  714. if (evt.path != undefined){
  715. swipeTarget = getFloatWindowObjectFromPath(evt.path);
  716. }
  717. }
  718. xDown = firstTouch.clientX;
  719. yDown = firstTouch.clientY;
  720. };
  721. function getFloatWindowObjectFromPath(path){
  722. var targetObject = undefined;
  723. targetType = undefined
  724. path.forEach(object => {
  725. if ($(object).hasClass("floatWindowButton")){
  726. targetObject = object
  727. targetType = "fw"
  728. }
  729. })
  730. return targetObject;
  731. }
  732. function handleTouchMove(evt) {
  733. if ( ! xDown || ! yDown ) {
  734. return;
  735. }
  736. var xUp = evt.touches[0].clientX;
  737. var yUp = evt.touches[0].clientY;
  738. var xDiff = xDown - xUp;
  739. var yDiff = yDown - yUp;
  740. if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
  741. if ( xDiff > 0 ) {
  742. /* left swipe */
  743. if (swipeTarget !== undefined && targetType == "fw"){
  744. closeFloatWindow($(swipeTarget).attr("windowId"));
  745. }else if (swipeTarget !== undefined && targetType == "taskbar"){
  746. hideTaskBar();
  747. }
  748. } else {
  749. /* right swipe */
  750. if (swipeTarget !== undefined && targetType == "fw"){
  751. //Allow left or right swipe to remove fw
  752. closeFloatWindow($(swipeTarget).attr("windowId"));
  753. }else if (swipeTarget !== undefined && targetType == "taskbar"){
  754. //Right swipe on taskbar
  755. if ($(swipeTarget).find(".toggleTaskBar").attr("shown") == "true"){
  756. //Already shown. Toggle list menu
  757. showListMenu();
  758. }else{
  759. showTaskBar();
  760. }
  761. }
  762. }
  763. } else {
  764. if ( yDiff > 0 ) {
  765. /* up swipe */
  766. } else {
  767. /* down swipe */
  768. }
  769. }
  770. /* reset values */
  771. xDown = null;
  772. yDown = null;
  773. swipeTarget = null;
  774. };
  775. function showListMenu(callback = undefined){
  776. if ($(".taskBar").find(".toggleTaskBar").attr("shown") == "false"){
  777. $(".taskBar").find(".toggleTaskBar").attr("shown", "true");
  778. $(".taskBar").find('.sidebararrow').attr("src","img/mobile/keyboard_arrow_left-white-48dp.svg");
  779. $("#mainFrame").addClass("blurred");
  780. }
  781. $(".taskBar").animate({
  782. width: window.innerWidth,
  783. },300, "swing", function(){
  784. //Switch all fwbuttons to normal size
  785. $(".floatWindowButton").each(function(){
  786. $(this).find(".minimizedElements").hide();
  787. $(this).find(".normalElements").show();
  788. });
  789. //Show list menu
  790. $("#listMenu").animate({
  791. left: 0
  792. },300,"swing", function(){
  793. if (typeof callback != "undefined"){
  794. callback();
  795. }
  796. });
  797. });
  798. listMenuShown = true;
  799. $("#sidebarToggleOverlay").show();
  800. }
  801. function openModule(moduleName) {
  802. $.get("system/modules/getLaunchPara?module=" + moduleName, function(data) {
  803. console.log(data);
  804. if (data.error !== undefined) {
  805. //Something went wrong.
  806. console.log("Unable to open module " + moduleName);
  807. if (data.error == "Not logged in."){
  808. //Session expired
  809. window.location.href = "login.system";
  810. }
  811. }else {
  812. //Launch the given module
  813. var url = data["StartDir"];
  814. var size = [undefined, undefined];
  815. var icon = "img/system/favicon.png";
  816. if (data["IconPath"] != "") {
  817. icon = data["IconPath"];
  818. }
  819. var title = data["Name"];
  820. //Check if the module support fw mode. If yes, launch with fwmode url. IF not, launch to index
  821. if (data["SupportFW"] == true) {
  822. if (data["LaunchFWDir"] != null) {
  823. url = data["LaunchFWDir"];
  824. }
  825. if (data["InitFWSize"] != null) {
  826. size = data["InitFWSize"];
  827. }
  828. }
  829. //Launch the given module
  830. newFloatWindow({
  831. url: url,
  832. width: size[0],
  833. height: size[1],
  834. appicon: icon,
  835. title: title
  836. });
  837. closeListMenu(function(){
  838. hideTaskBar();
  839. });
  840. }
  841. });
  842. }
  843. function openModuleFromMenu(object) {
  844. var moduleName = $(object).attr("module");
  845. openModule(moduleName);
  846. }
  847. //In mobile interface, there will be some option ignored by default
  848. function newFloatWindow(options){
  849. //Hide all other floatWindows
  850. $(".floatWindowWrapper").fadeOut("fast");
  851. //Construct the new window
  852. var windowID = Date.now();
  853. var parent = options.parent || "";
  854. var callback = options.callback || "";
  855. //Create a new iframe
  856. $("#windowWrapper").append(` <div class="floatWindowWrapper" windowId="${windowID}">
  857. <div class="floatWindow" windowId="${windowID}" parent="${parent}" callback="${callback}">
  858. <div class="fwtab">
  859. <iframe src="${options.url}" style="width: 100%; height: 100%;"></iframe>
  860. </div>
  861. </div>
  862. </div>`);
  863. //Create the button
  864. var title = options.title || "New FloatWindow";
  865. $("#windowButtonWrapper").append(`
  866. <div class="floatWindowButton" windowID="${windowID}" onclick="focusTab(this)">
  867. <div class="minimizedElements">
  868. <img class="minimizedIcon" src="${options.appicon}">
  869. </div>
  870. <div class="normalElements" style="display:none;">
  871. <img class="ui normalizedIcon middle aligned image" src="${options.appicon}">
  872. <span class="windowTitle" style="color:white;">${title}</span>
  873. <div class="closebutton" onclick="closefw(this);"><i class="remove icon"></i></div>
  874. <div class="externalbutton" onclick="openfwInNewTab(this);"><i class="external icon"></i></div>
  875. </div>
  876. </div>
  877. `);
  878. }
  879. ///Functions realted to window resize and auto scaling
  880. function updateWindowDimensions(){
  881. $("#backdrop").css({
  882. width: window.innerWidth,
  883. height: window.innerHeight
  884. });
  885. if (!listMenuShown){
  886. $("#listMenu").css("left", window.innerWidth * -1);
  887. }
  888. }
  889. updateWindowDimensions();
  890. $(window).on("resize", function(data){
  891. updateWindowDimensions();
  892. })
  893. //Float Window APIs
  894. function setFloatWindowTitle(id, title){
  895. $(".floatWindowButton").each(function(){
  896. if ($(this).attr("windowId") == id){
  897. $(this).find(".windowTitle").text(title);
  898. }
  899. })
  900. }
  901. function getFloatWindowByID(id){
  902. var targetObejct = undefined;
  903. $(".floatWindowWrapper").each(function(){
  904. if ($(this).attr("windowId") == id){
  905. targetObejct = $(this);
  906. }
  907. });
  908. return targetObejct;
  909. }
  910. function MoveFloatWindowToTop(targetfw){
  911. //Check if this windows is already topped
  912. if ($(targetfw).is(":visible")){
  913. //Already topped
  914. return;
  915. }
  916. $(".floatWindowWrapper").each(function(){
  917. $(this).fadeOut("fast");
  918. });
  919. console.log(targetfw);
  920. $(targetfw).parent().fadeIn("fast");
  921. }
  922. function focusTab(object){
  923. var windowID = $(object).attr("windowId");
  924. //Hide all other flowWindows
  925. $(".floatWindowWrapper").fadeOut("fast");
  926. //Show the target fw
  927. var fw = getFloatWindowByID(windowID);
  928. fw.fadeIn("fast", function(){
  929. hideTaskBar();
  930. });
  931. }
  932. function getFloatWindowByID(id){
  933. var targetObejct = undefined;
  934. $(".floatWindowWrapper").each(function(){
  935. if ($(this).attr("windowId") == id){
  936. targetObejct = $(this);
  937. }
  938. });
  939. return targetObejct;
  940. }
  941. function setFloatWindowResizePolicy(id, allowResize){
  942. //Disabled in mobile mode
  943. }
  944. function setFloatWindowSize(id, width, height){
  945. //Disabled in mobile mode
  946. }
  947. function closeFloatWindow(windowID){
  948. //Get the content iframe with that windowID
  949. var contentWindow = getFloatWindowByID(windowID);
  950. if (contentWindow == undefined){
  951. return;
  952. }
  953. contentWindow = contentWindow.find("iframe")[0].contentWindow;
  954. try {
  955. if (contentWindow.ao_module_close === undefined) {
  956. //This module do not use ao_module wrapper. Close it directly.
  957. closeFwProcess(windowID);
  958. } else {
  959. //Pass the closing events to the window itself
  960. contentWindow.ao_module_close();
  961. }
  962. } catch (ex) {
  963. //Problems of closing floatWindow. Force closing.
  964. closeFwProcess(windowID);
  965. }
  966. }
  967. function closefw(object){
  968. var windowID = $(object).parent().parent().attr("windowID");
  969. closeFloatWindow(windowID);
  970. }
  971. function openfwInNewTab(object){
  972. event.preventDefault();
  973. event.stopImmediatePropagation();
  974. var windowID = $(object).parent().parent().attr("windowID");
  975. var targetFloatWindow = null;
  976. $(".floatWindowWrapper").each(function(){
  977. if ($(this).attr("windowid") == windowID){
  978. targetFloatWindow = $(this);
  979. }
  980. });
  981. if (targetFloatWindow == null){
  982. return;
  983. }
  984. var iframe = $(targetFloatWindow).find("iframe");
  985. var url = $(iframe)[0].contentWindow.location.href;
  986. window.open(url);
  987. }
  988. //Get the window below this window id, can return null if there is no window
  989. function getPreviousWindowObject(windowID){
  990. var previousWindowID = null;
  991. var result = null;
  992. $(".floatWindowButton").each(function(){
  993. if ($(this).attr("windowid") == windowID){
  994. result = previousWindowID;
  995. }else{
  996. let thisWindowID = $(this).attr("windowid");
  997. previousWindowID = thisWindowID;
  998. }
  999. });
  1000. return result;
  1001. }
  1002. function closeFwProcess(windowID){
  1003. //Get the previous window object
  1004. var previousWindowID = getPreviousWindowObject(windowID);
  1005. //Remove the window object
  1006. $(".floatWindowWrapper").each(function(){
  1007. if ($(this).attr("windowId") == windowID){
  1008. $(this).fadeOut("fast",function(){
  1009. $(this).remove();
  1010. });
  1011. }
  1012. });
  1013. //Remove the button object
  1014. $(".floatWindowButton").each(function(){
  1015. if ($(this).attr("windowId") == windowID){
  1016. $(this).fadeOut("fast",function(){
  1017. $(this).remove();
  1018. });
  1019. }
  1020. });
  1021. //Focus the window behind if exists
  1022. setTimeout(function(){
  1023. if (previousWindowID != null){
  1024. //Hide all other flowWindows
  1025. $(".floatWindowWrapper").fadeOut("fast");
  1026. //Show the target fw
  1027. var fw = getFloatWindowByID(previousWindowID);
  1028. console.log(fw);
  1029. fw.fadeIn("fast", function(){
  1030. });
  1031. }
  1032. }, 100);
  1033. }
  1034. function bindObjectToIMEEvents(object){
  1035. console.log("IME not supported in mobile desktop mode")
  1036. };
  1037. function openFileWithModule(moduleLaunchInfo, openFileList) {
  1038. var url = moduleLaunchInfo["StartDir"];
  1039. var size = [undefined, undefined];
  1040. var title = moduleLaunchInfo["Name"];
  1041. var icon = "img/system/favicon.png";
  1042. if (moduleLaunchInfo["IconPath"] != "") {
  1043. icon = moduleLaunchInfo["IconPath"];
  1044. }
  1045. //Use floatWindow if exists
  1046. if (moduleLaunchInfo["SupportFW"] == true && moduleLaunchInfo["LaunchFWDir"] != "") {
  1047. url = moduleLaunchInfo["LaunchFWDir"];
  1048. if (moduleLaunchInfo["InitFWSize"] !== null) {
  1049. size = moduleLaunchInfo["InitFWSize"]
  1050. }
  1051. }
  1052. //Use embedded mode if exists
  1053. if (moduleLaunchInfo["SupportEmb"] == true && moduleLaunchInfo["LaunchEmb"] != "") {
  1054. url = moduleLaunchInfo["LaunchEmb"];
  1055. if (moduleLaunchInfo["InitEmbSize"] !== null) {
  1056. size = moduleLaunchInfo["InitEmbSize"]
  1057. }
  1058. }
  1059. var openParamter = encodeURIComponent(JSON.stringify(openFileList));
  1060. //Add launch files info and launch floatWindow
  1061. newFloatWindow({
  1062. url: url + "#" + openParamter,
  1063. width: size[0],
  1064. height: size[1],
  1065. appicon: icon,
  1066. title: title
  1067. });
  1068. }
  1069. //Mobile interface do not support pin function yet
  1070. function PinFloatWindowToTopMostMode(object){
  1071. }
  1072. function UnpinFloatWindowFromTopMostMode(object){
  1073. }
  1074. /*
  1075. List Menu Specific function groups
  1076. */
  1077. function openDesktopAsFolder(){
  1078. newFloatWindow({
  1079. url: "SystemAO/file_system/file_explorer.html#" + encodeURIComponent("user:/Desktop/"),
  1080. appicon: "SystemAO/file_system/img/small_icon.png",
  1081. width:1080,
  1082. height:580,
  1083. title: "File Manager"
  1084. });
  1085. hideTaskBar();
  1086. }
  1087. function openDesktopCustomization(){
  1088. newFloatWindow({
  1089. url: "SystemAO/desktop/personalization.html",
  1090. appicon: "SystemAO/desktop/img/personalization.png",
  1091. width:640,
  1092. height:480,
  1093. title: "Personalization"
  1094. });
  1095. hideTaskBar();
  1096. }
  1097. function showDesktop(){
  1098. $(".floatWindowWrapper").fadeOut("fast");
  1099. hideTaskBar();
  1100. }
  1101. //Theme color placeholder functions
  1102. function setThemeColor(color){
  1103. $(".themeColor").css("background-color", color);
  1104. }
  1105. //Startup sound
  1106. function initStartupSounds(){
  1107. $.ajax({
  1108. url: "../../system/desktop/preference",
  1109. method: "GET",
  1110. data: {preference: "startup-audio"},
  1111. success: function(data){
  1112. if (data == undefined || data == ""){
  1113. return;
  1114. }
  1115. var currentGlobalVol = localStorage.getItem("global_volume");
  1116. if (currentGlobalVol != null && currentGlobalVol != undefined && currentGlobalVol != ""){
  1117. }else{
  1118. currentGlobalVol = 0;
  1119. }
  1120. var audio = new Audio("media?file=" + data);
  1121. audio.volume = currentGlobalVol;
  1122. audio.play();
  1123. }
  1124. });
  1125. }
  1126. function fullscreen() {
  1127. //Opening full screen will lead to hidden of all iframe for unknown reasons
  1128. var isInFullScreen = (document.fullscreenElement && document.fullscreenElement !== null) ||
  1129. (document.webkitFullscreenElement && document.webkitFullscreenElement !== null) ||
  1130. (document.mozFullScreenElement && document.mozFullScreenElement !== null) ||
  1131. (document.msFullscreenElement && document.msFullscreenElement !== null);
  1132. var elem = document.documentElement;
  1133. if (!isInFullScreen) {
  1134. if (elem.requestFullscreen) {
  1135. elem.requestFullscreen();
  1136. } else if (elem.mozRequestFullScreen) { /* Firefox */
  1137. elem.mozRequestFullScreen();
  1138. } else if (elem.webkitRequestFullscreen) { /* Chrome, Safari and Opera */
  1139. elem.webkitRequestFullscreen();
  1140. } else if (elem.msRequestFullscreen) { /* IE/Edge */
  1141. elem.msRequestFullscreen();
  1142. }
  1143. } else {
  1144. if (document.exitFullscreen) {
  1145. document.exitFullscreen();
  1146. } else if (document.webkitExitFullscreen) {
  1147. document.webkitExitFullscreen();
  1148. } else if (document.mozCancelFullScreen) {
  1149. document.mozCancelFullScreen();
  1150. } else if (document.msExitFullscreen) {
  1151. document.msExitFullscreen();
  1152. }
  1153. }
  1154. hideTaskBar();
  1155. }
  1156. function initDesktopUserInfo(){
  1157. $.get("system/desktop/user", function(data){
  1158. if (data.error !== undefined){
  1159. alert(data.error);
  1160. }else{
  1161. userInfo = data;
  1162. //Update the user tag
  1163. $("#username").text(userInfo.Username);
  1164. $("#usergroups").text("@" + userInfo.UserGroups.join("/"));
  1165. $("#usergroups").attr("title",userInfo.UserGroups.join(" / "));
  1166. if (data.UserIcon !== ""){
  1167. $(".usericon").attr("src",data.UserIcon);
  1168. }
  1169. }
  1170. });
  1171. }
  1172. function showProfileInfo(){
  1173. hideTaskBar();
  1174. setTimeout(function(){
  1175. toggleProfileInfo();
  1176. }, 500);
  1177. }
  1178. function toggleProfileInfo(){
  1179. $("#userprofile").transition('drop');
  1180. }
  1181. function openSystemSettings(){
  1182. openModule("System Setting");
  1183. }
  1184. function logout() {
  1185. loggingOut = true;
  1186. if (confirm("Exiting Session. Confirm?")){
  1187. $.get("system/auth/logout", function() {
  1188. window.location.href = "/";
  1189. });
  1190. toggleProfileInfo();
  1191. }
  1192. }
  1193. //Keep the clock updated
  1194. setInterval(function(){
  1195. updateClockTime();
  1196. },5000);
  1197. updateClockTime();
  1198. function updateClockTime(){
  1199. var d = new Date();
  1200. var display = monthNames[d.getMonth()] + " " + d.getDate() + " " + zeropad(d.getHours(),2) + ":" + zeropad(d.getMinutes(),2);
  1201. if ($(".notification.object").length > 0){
  1202. display += `<span style="color: #f54242; margin-left: 8px; float: center;"><i class="notice circle icon"></i></span>`;
  1203. }
  1204. $(".clock").html(display);
  1205. var largedate = monthNames[d.getMonth()] + " " + d.getDate() + " " + d.getFullYear()
  1206. $("#largedate").text(largedate);
  1207. var dow = daysNames[d.getDay()];
  1208. $("#dayofweek").text(dow);
  1209. }
  1210. function zeropad(n, width, z) {
  1211. z = z || '0';
  1212. n = n + '';
  1213. return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
  1214. }
  1215. </script>
  1216. </body>
  1217. </html>