interface.html 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <!-- Startup Interface Settings — loaded into SystemAO/system_setting/index.html via jQuery .load() -->
  2. <style>
  3. #sif-root {
  4. --sif-text: #1a1a1a;
  5. --sif-dim: #5a5a5a;
  6. --sif-muted: #9a9a9a;
  7. --sif-border: rgba(0,0,0,0.10);
  8. --sif-hover: rgba(0,0,0,0.04);
  9. --sif-accent: #2f6fed;
  10. --sif-accent-soft: rgba(47,111,237,0.08);
  11. --sif-green: #107c10;
  12. font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  13. font-size: 14px;
  14. color: var(--sif-text);
  15. padding: 4px 0 32px;
  16. }
  17. body.dark #sif-root {
  18. --sif-text: #f0f0f0;
  19. --sif-dim: #b0b0b0;
  20. --sif-muted: #808080;
  21. --sif-border: rgba(255,255,255,0.10);
  22. --sif-hover: rgba(255,255,255,0.05);
  23. --sif-accent: #6b9bff;
  24. --sif-accent-soft: rgba(107,155,255,0.12);
  25. }
  26. #sif-root h3.section-title {
  27. font-size: 15px;
  28. font-weight: 600;
  29. color: var(--sif-text);
  30. margin: 0 0 4px;
  31. }
  32. #sif-root .section-desc {
  33. font-size: 12px;
  34. color: var(--sif-muted);
  35. margin: 0 0 12px;
  36. }
  37. #sif-root .sif-section {
  38. padding: 16px;
  39. border-bottom: 1px solid var(--sif-border);
  40. }
  41. #sif-root .sif-section:last-child { border-bottom: none; }
  42. #sif-root .sif-list {
  43. display: flex;
  44. flex-direction: column;
  45. gap: 6px;
  46. max-width: 560px;
  47. }
  48. #sif-root .sif-option {
  49. display: flex;
  50. align-items: center;
  51. gap: 12px;
  52. padding: 10px 12px;
  53. border: 1px solid var(--sif-border);
  54. border-radius: 6px;
  55. cursor: pointer;
  56. transition: background-color 0.1s, border-color 0.1s;
  57. }
  58. #sif-root .sif-option:hover { background: var(--sif-hover); }
  59. #sif-root .sif-option.selected {
  60. border-color: var(--sif-accent);
  61. background: var(--sif-accent-soft);
  62. }
  63. #sif-root .sif-option.disabled { cursor: default; }
  64. #sif-root .sif-radio {
  65. flex-shrink: 0;
  66. width: 16px;
  67. height: 16px;
  68. border-radius: 50%;
  69. border: 1.5px solid var(--sif-muted);
  70. position: relative;
  71. }
  72. #sif-root .sif-option.selected .sif-radio { border-color: var(--sif-accent); }
  73. #sif-root .sif-option.selected .sif-radio::after {
  74. content: '';
  75. position: absolute;
  76. top: 3px; left: 3px;
  77. width: 7px; height: 7px;
  78. border-radius: 50%;
  79. background: var(--sif-accent);
  80. }
  81. #sif-root .sif-icon {
  82. flex-shrink: 0;
  83. width: 32px;
  84. height: 32px;
  85. object-fit: contain;
  86. }
  87. #sif-root .sif-icon-ask {
  88. flex-shrink: 0;
  89. width: 32px;
  90. height: 32px;
  91. display: flex;
  92. align-items: center;
  93. justify-content: center;
  94. color: var(--sif-dim);
  95. }
  96. #sif-root .sif-name { font-size: 13px; font-weight: 600; }
  97. #sif-root .sif-desc { font-size: 12px; color: var(--sif-muted); }
  98. #sif-root .sif-note {
  99. font-size: 12px;
  100. color: var(--sif-dim);
  101. margin-top: 10px;
  102. }
  103. #sif-root .btn {
  104. padding: 5px 12px;
  105. border-radius: 4px;
  106. border: 1px solid var(--sif-border);
  107. background: transparent;
  108. color: var(--sif-text);
  109. font-size: 12px;
  110. cursor: pointer;
  111. display: inline-flex;
  112. align-items: center;
  113. gap: 4px;
  114. margin-top: 12px;
  115. }
  116. #sif-root .btn:hover { opacity: 0.75; }
  117. #sif-root .confirm-msg {
  118. display: none;
  119. margin-top: 8px;
  120. padding: 8px 12px;
  121. background: rgba(16,124,16,0.1);
  122. border-radius: 4px;
  123. font-size: 12px;
  124. color: var(--sif-green);
  125. max-width: 560px;
  126. }
  127. body.dark #sif-root .confirm-msg { background: rgba(16,124,16,0.15); }
  128. </style>
  129. <div id="sif-root">
  130. <div class="sif-section">
  131. <h3 class="section-title" locale="sif/title">Startup Interface</h3>
  132. <p class="section-desc" locale="sif/desc">Choose which workspace opens after you sign in. This setting only applies to this browser.</p>
  133. <div id="sif-list" class="sif-list"></div>
  134. <div id="sif-single" class="sif-note" style="display:none;" locale="sif/single">Your account has only one workspace, so it always opens after you sign in.</div>
  135. <div id="sif-save-confirm" class="confirm-msg"><span locale="sif/saved">Startup interface updated for this browser.</span></div>
  136. <button id="sif-open-selector" class="btn" onclick="sifOpenSelector()" style="display:none;">
  137. <svg width="12" height="12" viewBox="0 0 16 16" fill="none"><path d="M2 5h10M9 2l3 3-3 3M14 11H4M7 8l-3 3 3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
  138. <span locale="sif/switch">Switch Workspace Now</span>
  139. </button>
  140. </div>
  141. </div>
  142. <script>
  143. (function () {
  144. var sifLocale = NewAppLocale();
  145. var sifStorageKey = "default-interface-module";
  146. var sifModules = [];
  147. sifLocale.init("../locale/system_settings/desktop.json", function () {
  148. sifLocale.translate();
  149. sifLoadModules();
  150. }, function () {
  151. sifLoadModules();
  152. });
  153. function sifEsc(text) {
  154. return $("<div>").text(text == undefined ? "" : text).html();
  155. }
  156. function sifGetRemembered() {
  157. try {
  158. return localStorage.getItem(sifStorageKey) || "";
  159. } catch (e) {
  160. return "";
  161. }
  162. }
  163. function sifSetRemembered(name) {
  164. try {
  165. if (name === "") {
  166. localStorage.removeItem(sifStorageKey);
  167. } else {
  168. localStorage.setItem(sifStorageKey, name);
  169. }
  170. return true;
  171. } catch (e) {
  172. return false;
  173. }
  174. }
  175. function sifLoadModules() {
  176. $.get("../../system/users/interfaceinfo", function (data) {
  177. sifModules = Array.isArray(data) ? data : [];
  178. sifRender();
  179. });
  180. }
  181. function sifRender() {
  182. var list = $("#sif-list");
  183. list.html("");
  184. var remembered = sifGetRemembered();
  185. if (remembered !== "" && !sifModules.some(function (m) { return m.Name === remembered; })) {
  186. //The remembered interface is no longer available to this user
  187. remembered = "";
  188. }
  189. if (sifModules.length <= 1) {
  190. //The server opens the only interface directly, the browser choice is never used
  191. sifModules.forEach(function (m) {
  192. list.append(sifOptionHTML(m.Name, m.Name, m.Desc, "../../" + m.IconPath, true));
  193. });
  194. list.find(".sif-option").addClass("disabled");
  195. $("#sif-single").show();
  196. return;
  197. }
  198. list.append(sifOptionHTML("",
  199. sifLocale.getString("sif/ask", "Ask me every time"),
  200. sifLocale.getString("sif/ask-desc", "Show the workspace selector after signing in"),
  201. "", remembered === ""));
  202. sifModules.forEach(function (m) {
  203. list.append(sifOptionHTML(m.Name, m.Name, m.Desc, "../../" + m.IconPath, remembered === m.Name));
  204. });
  205. $("#sif-open-selector").show();
  206. list.find(".sif-option").on("click", function () {
  207. var value = $(this).attr("data-value");
  208. if (!sifSetRemembered(value)) {
  209. return;
  210. }
  211. list.find(".sif-option").removeClass("selected");
  212. $(this).addClass("selected");
  213. $("#sif-save-confirm").stop(true).finish().slideDown("fast").delay(3000).slideUp("fast");
  214. });
  215. }
  216. function sifOptionHTML(value, name, desc, icon, selected) {
  217. var iconHTML = icon === "" ?
  218. '<div class="sif-icon-ask"><svg width="22" height="22" viewBox="0 0 24 24" fill="none"><rect x="3" y="4" width="18" height="16" rx="2.5" stroke="currentColor" stroke-width="1.6"/><path d="M7 9h10M7 13h6" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg></div>' :
  219. '<img class="sif-icon" src="' + sifEsc(icon) + '" alt="" onerror="this.src=\'../../img/system/service.png\'">';
  220. return '<div class="sif-option' + (selected ? ' selected' : '') + '" data-value="' + sifEsc(value) + '">' +
  221. '<div class="sif-radio"></div>' + iconHTML +
  222. '<div><div class="sif-name">' + sifEsc(name) + '</div><div class="sif-desc">' + sifEsc(desc) + '</div></div>' +
  223. '</div>';
  224. }
  225. window.sifOpenSelector = function () {
  226. window.top.location.href = new URL("../boot/interface_selector.html?switch", window.location.href).href;
  227. };
  228. }());
  229. </script>