file_share.html 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <html>
  2. <head>
  3. <title>File Share</title>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
  6. <style>
  7. body{
  8. background: rgba(255,255,255,01) !important;
  9. }
  10. </style>
  11. </head>
  12. <body>
  13. <div class="ui stackable grid">
  14. <div class="eight wide column">
  15. <div class="width: 100%; ">
  16. <div style="display: block; margin-left: auto; margin-right: auto;" align="center">
  17. <div id="qrcode" style="border: 10px solid white; background-color: white;">
  18. <h1>Loading</h1>
  19. </div>
  20. </div>
  21. <div style="width: 100%">
  22. <a id="sharelink" href="" target="_blank" style="margin-top:8px; font-size: 120%; padding-left: 20px; padding-right: 20px; word-break: break-all; overflow-wrap: anywhere;">Scan this QR Code to copy the share link</a>
  23. </div>
  24. </div>
  25. </div>
  26. <div id="shareSettingOptions" class="eight wide column" style="padding-left: 12px; display:none;">
  27. <div class="ui header whiteTheme">
  28. Share Settings
  29. <div class="sub header whiteTheme">Change who can see this file</div>
  30. </div>
  31. <div id="shareSettingForm" class="ui form">
  32. <div class="field">
  33. <label><p class="whiteTheme">Visable options:</p></label>
  34. <div class="ui checkboxes">
  35. <div class="ui radio checkbox">
  36. <input id="anyone" type="radio" class="shareoption" name="shareopt" value="anyone" onchange="updateSharePermission(this);">
  37. <label for="anyone">
  38. <div class="ui header">
  39. <div class="content whiteTheme">
  40. <i class="globe icon"></i> Anyone with the link
  41. <div class="sub header whiteTheme">Anyone who has the link can access this file</div>
  42. </div>
  43. </div>
  44. </label>
  45. </div>
  46. <br><br>
  47. <div class="ui radio checkbox">
  48. <input id="signedin" type="radio" class="shareoption" value="signedin" name="shareopt" onchange="updateSharePermission(this);">
  49. <label for="signedin">
  50. <div class="ui header">
  51. <div class="content whiteTheme">
  52. <i class="user circle outline icon"></i> Anyone signed in
  53. <div class="sub header whiteTheme">Anyone who has signed in can access this file</div>
  54. </div>
  55. </div>
  56. </label>
  57. </div>
  58. <br><br>
  59. <div class="ui radio checkbox">
  60. <input id="samegroup" type="radio" class="shareoption" value="samegroup" name="shareopt" onchange="updateSharePermission(this);">
  61. <label for="samegroup">
  62. <div class="ui header">
  63. <div class="content whiteTheme">
  64. <i class="users icon"></i> Users in the same group
  65. <div class="sub header whiteTheme">Anyone who is in the same group as you do</div>
  66. </div>
  67. </div>
  68. </label>
  69. </div>
  70. <br><br>
  71. <div id="udpateNotification" style="display:none;" class="ui green inverted segment">
  72. <i class=" checkmark icon"></i> Share Setting Updated
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </div>
  79. <div class="ui divider"></div>
  80. <div style="width: 100%; padding-right: 12px;" align="right">
  81. <div class="ui button popupbuttons whiteTheme allowHover" onclick="copyLinkToClipboard(this)">
  82. <i class="copy icon"></i> Copy
  83. </div>
  84. <div id="sharingRemoveBtn" class="ui red button popupbuttons negative whiteTheme allowHover" onclick="removeSharing()">
  85. <i class="remove icon"></i> Remove
  86. </div>
  87. </div>
  88. <script>
  89. /*
  90. Usage: Pass in file descriptor to start share a file
  91. var fd = encodeURIComponent(JSON.stringify({
  92. filename: "test.txt",
  93. filepath: "user:/Desktop/test.txt"
  94. })
  95. );
  96. window.open("file_share.html#" + fd);
  97. If you want to preset a file sharing mode (aka your module handle the share mode picking),
  98. Pass in with the "shareMode" paramter. Example fd as follow:
  99. {
  100. filename: "test.txt",
  101. filepath: "user:/Desktop/test.txt",
  102. shareMode: "signedin"
  103. }
  104. To remove a share, pass in "remove" for the share mode
  105. Supported Share Mode keywords {anyone/signedin/samegroup/remove}
  106. */
  107. var shareEditingUUID = "";
  108. var shareingFileData = {};
  109. var initialized = false;
  110. var fileSharingURL = "";
  111. function PageReady(){
  112. if (initialized){
  113. return;
  114. }
  115. initialized = true;
  116. $(".checkbox").checkbox();
  117. var inputFile = ao_module_loadInputFiles();
  118. if (inputFile == null){
  119. //No file selected
  120. $(".shareoption").parent().addClass("disabled");
  121. $("#qrcode").html(`<h1>No File</h1>`);
  122. $("#sharelink").text(``);
  123. $("#sharingRemoveBtn").addClass("disabled");
  124. return
  125. }
  126. //Make sure one file is choicen each time
  127. inputFile = inputFile[0];
  128. shareingFileData = inputFile;
  129. initFileDetails(shareingFileData, function(shareUUID){
  130. //Set the mode of share if it is defined
  131. if (shareingFileData.shareMode !== undefined && shareingFileData.shareMode == "remove"){
  132. //Remove the share UUID
  133. removeSharing();
  134. return;
  135. }
  136. if (shareingFileData.shareMode !== undefined){
  137. //As the share mode is defined by the caller, hide the setting interface
  138. $("#shareSettingOptions").hide();
  139. $.ajax({
  140. url: "../../system/file_system/share/edit",
  141. data: {uuid: shareEditingUUID, mode: shareingFileData.shareMode},
  142. success: function(data){
  143. if (data.error !== undefined){
  144. alert(data.error);
  145. return;
  146. }
  147. //Update the checkbox
  148. $(".shareoption").each(function(){
  149. if ($(this)[0].value != shareingFileData.shareMode){
  150. $(this)[0].checked = false;
  151. }else{
  152. $(this)[0].checked = true;
  153. }
  154. });
  155. }
  156. });
  157. }else{
  158. //Default: show the setting to allow user adjustment
  159. $("#shareSettingOptions").show();
  160. }
  161. });
  162. }
  163. function initFileDetails(shareingFileData, callback=undefined){
  164. $.ajax({
  165. url: "../../system/file_system/share/new",
  166. data: {path: shareingFileData.filepath},
  167. success: function(data){
  168. if (data.error !== undefined){
  169. alert(data.error);
  170. }else{
  171. updateShareLinkInfo(data.UUID);
  172. shareEditingUUID = data.UUID;
  173. $(".shareoption").each(function(){
  174. if ($(this)[0].value != data.Permission){
  175. $(this)[0].checked = false;
  176. }else{
  177. $(this)[0].checked = true;
  178. }
  179. });
  180. //If the file is from desktop, set share icon
  181. if (ao_module_virtualDesktop == true){
  182. var fileDir = shareingFileData.filepath.split("/");
  183. fileDir.pop();
  184. fileDir = fileDir.join("/");
  185. if (fileDir == "user:/Desktop"){
  186. //Remove share icon
  187. parent.setFileShareIndicator(shareingFileData.filename);
  188. }
  189. }
  190. if (callback != undefined){
  191. callback(data.UUID)
  192. }
  193. }
  194. }
  195. });
  196. }
  197. function removeSharing(){
  198. if (shareEditingUUID == ""){
  199. return
  200. }
  201. //The target file to remove
  202. $.ajax({
  203. url: "../../system/file_system/share/delete",
  204. data: {path: shareingFileData.filepath},
  205. success: function(data){
  206. if (data.error !== undefined){
  207. alert(data.error);
  208. }else{
  209. //Removed!
  210. $(".button").addClass('disabled');
  211. $(".checkbox").addClass("disabled");
  212. $("#sharelink").text("");
  213. $("#sharelink").attr("href", "#");
  214. $("#qrcode").html(`<br><br><h1><i class="green checkmark icon"></i> Share Removed</h1>`);
  215. //If the file is located on desktop and it is web desktop mode
  216. if (ao_module_virtualDesktop == true){
  217. var fileDir = shareingFileData.filepath.split("/");
  218. fileDir.pop();
  219. fileDir = fileDir.join("/");
  220. if (fileDir == "user:/Desktop"){
  221. //Remove share icon
  222. parent.removeFileShareIndicator(shareingFileData.filename);
  223. }
  224. }
  225. }
  226. }
  227. });
  228. }
  229. function updateSharePermission(object){
  230. var newPermission = $(object).attr('value');
  231. $.ajax({
  232. url: "../../system/file_system/share/edit",
  233. data: {uuid: shareEditingUUID, mode: newPermission},
  234. success: function(data){
  235. if (data.error !== undefined){
  236. alert(data.error);
  237. return;
  238. }
  239. $("#udpateNotification").slideDown("fast").delay(3000).slideUp("fast");
  240. }
  241. });
  242. }
  243. function updateShareLinkInfo(uuid){
  244. $("#qrcode").html("");
  245. let protocol = "https://";
  246. if (location.protocol !== 'https:') {
  247. protocol = "http://";
  248. }
  249. var shareURL = protocol + window.location.hostname + ":" + window.location.port + "/share/" + uuid;
  250. shareEditingUUID = uuid;
  251. fileSharingURL = shareURL;
  252. new QRCode(document.getElementById("qrcode"), shareURL);
  253. $("#sharelink").text(shareURL);
  254. $("#sharelink").attr("href", shareURL)
  255. }
  256. /*
  257. Dynamic Script Loader
  258. This is a really experimental implementation of importing a script from anywhere
  259. under the ArozOS web root. This section of code must be written in plain JS to make sure
  260. it works without jQuery and other libraries.
  261. This function try to load jQuery and ao_module from the script folder.
  262. Also loading the semantic js and the css main body
  263. */
  264. //The possible location for desktop.system, standard webapp module, SystemAO interfaces and iui sub-interfaces
  265. let possibleLocations = ["script/", "../script/", "../../script/", "../../../script/"];
  266. let loopCount = Math.min(possibleLocations.length, JSON.parse(JSON.stringify(window.location.toString())).split("/").length - 3);
  267. function tryLoad(relpath, filename, successCallback=undefined){
  268. var request = new XMLHttpRequest();
  269. request.open('GET', relpath + filename, true);
  270. request.onreadystatechange = function(){
  271. if (request.readyState === 4){
  272. if (request.status == 200 || request.status == 304) {
  273. if (typeof(successCallback) != "undefined"){
  274. successCallback(relpath, filename);
  275. }
  276. }
  277. }
  278. };
  279. request.send();
  280. }
  281. function injectOtherJavaScriptLibrary(relpath){
  282. //Check if ao_module is loaded
  283. if (typeof(ao_module_virtualDesktop) == "undefined"){
  284. var script = document.createElement('script');
  285. script.setAttribute('src', relpath + "ao_module.js");
  286. document.getElementsByTagName('head')[0].appendChild(script);
  287. }else{
  288. //This routine already run
  289. return;
  290. }
  291. //Inject QR Code library
  292. var script = document.createElement('script');
  293. script.setAttribute('src', relpath + "qrcode.min.js");
  294. document.getElementsByTagName('head')[0].appendChild(script);
  295. //Inject semmantic css and js anyway
  296. var head = document.getElementsByTagName('head')[0];
  297. var link = document.createElement('link');
  298. link.id = "semantic";
  299. link.rel = 'stylesheet';
  300. link.type = 'text/css';
  301. link.href = relpath + 'semantic/semantic.min.css';
  302. link.media = 'all';
  303. head.appendChild(link);
  304. var script = document.createElement('script');
  305. script.setAttribute('src', relpath + "semantic/semantic.min.js");
  306. document.getElementsByTagName('head')[0].appendChild(script);
  307. setTimeout(function(){
  308. PageReady();
  309. }, 1000);
  310. }
  311. //Load jQuery first
  312. if (typeof(window.jQuery) == "undefined"){
  313. //jQuery not found. Laod it
  314. for (var i = 0; i < loopCount; i++){
  315. var relpath = possibleLocations[i];
  316. tryLoad(relpath, "jquery.min.js", function(relpath, filename){
  317. //Generate the jquery script element
  318. var script = document.createElement('script');
  319. script.setAttribute('src', relpath + filename);
  320. document.getElementsByTagName('head')[0].appendChild(script);
  321. doAfterJqueryLoaded(function(){
  322. injectOtherJavaScriptLibrary(relpath);
  323. });
  324. });
  325. }
  326. }else{
  327. //jQuery exists. Load ao_module
  328. dynamicLoadAoModule();
  329. }
  330. function doAfterJqueryLoaded(callback){
  331. setTimeout(function(){
  332. //Wait until it is loaded
  333. if (typeof(window.jQuery) == "undefined"){
  334. doAfterJqueryLoaded(callback);
  335. return
  336. }else{
  337. callback();
  338. }
  339. }), 300;
  340. }
  341. function copyLinkToClipboard(btn){
  342. //Copy text
  343. const area = document.createElement('textarea');
  344. document.body.appendChild(area);
  345. area.value = fileSharingURL;
  346. area.select();
  347. document.execCommand('copy');
  348. document.body.removeChild(area);
  349. //Do visual feedback
  350. let oldContent = $(btn).html();
  351. $(btn).html(`<i class="green checkmark icon"></i> Copied!`);
  352. setTimeout(function(){
  353. $(btn).html(oldContent);
  354. }, 3000);
  355. }
  356. </script>
  357. </body>
  358. </html>