diff --git a/launcher/public/output.css b/launcher/public/output.css index b7e7a38ca4..f0099d8a13 100755 --- a/launcher/public/output.css +++ b/launcher/public/output.css @@ -2571,11 +2571,6 @@ video { appearance: none; } -.auto-cols-max{ - grid-auto-columns: -webkit-max-content; - grid-auto-columns: max-content; -} - .grid-flow-row{ grid-auto-flow: row; } @@ -2862,6 +2857,12 @@ video { margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); } +.space-y-3 > :not([hidden]) ~ :not([hidden]){ + --tw-space-y-reverse: 0; + margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); +} + .space-y-4 > :not([hidden]) ~ :not([hidden]){ --tw-space-y-reverse: 0; margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); @@ -2886,12 +2887,6 @@ video { margin-bottom: calc(1px * var(--tw-space-y-reverse)); } -.space-y-3 > :not([hidden]) ~ :not([hidden]){ - --tw-space-y-reverse: 0; - margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); -} - .divide-x > :not([hidden]) ~ :not([hidden]){ --tw-divide-x-reverse: 0; border-right-width: calc(1px * var(--tw-divide-x-reverse)); diff --git a/launcher/src/components/UI/edit-page/EditScreen.vue b/launcher/src/components/UI/edit-page/EditScreen.vue index 8b013e5740..a021838ccc 100644 --- a/launcher/src/components/UI/edit-page/EditScreen.vue +++ b/launcher/src/components/UI/edit-page/EditScreen.vue @@ -147,7 +147,7 @@ import { useServers } from "@/store/servers"; import { useServices } from "@/store/services"; import { useFooter } from "@/store/theFooter"; import { useStakingStore } from "@/store/theStaking"; -import { computed, onMounted, onUnmounted, ref, watch, watchEffect } from "vue"; +import { computed, onMounted, onUnmounted, ref, watchEffect } from "vue"; import { useRouter } from "vue-router"; import { useMultiSetups } from "../../../composables/multiSetups"; import { useSetups } from "../../../store/setups"; @@ -171,6 +171,7 @@ import SetupInfos from "./components/modals/setups/SetupInfos.vue"; import ChangesSection from "./sections/ChangesSection.vue"; import ServiceSection from "./sections/ServiceSection.vue"; import SidebarSection from "./sections/SidebarSection.vue"; +import { useFrontendServices } from "@/composables/services"; const setupStore = useSetups(); const footerStore = useFooter(); @@ -200,7 +201,7 @@ const nukeModalComponent = ref(); const selectedSetupNetwork = ref(""); const changeAnime = ref("/animation/confirm-changes/modify.gif"); const setupImportAnime = ref("/animation/setup/loader.gif"); -const { loadSetups, loadServices, getAllSetups, getServerView, updateDom } = useMultiSetups(); +const { loadSetups, getAllSetups, getServerView, updateDom } = useMultiSetups(); // Computed & Watcher @@ -226,13 +227,6 @@ const getAimationSrc = computed(() => { // { deep: true } // ); -watch( - () => manageStore.newConfiguration.length, - () => { - updateDom(); - } -); - watchEffect(() => { if (setupStore.isImportAnimeActive) { setTimeout(() => { @@ -291,7 +285,6 @@ onUnmounted(() => { // Methods const fetchSetups = async () => { await loadSetups(); - await loadServices(); setupStore.editSetups = getAllSetups(); }; @@ -818,6 +811,7 @@ const confirmHandler = async () => { } catch (error) { console.error("Error processing changes:", error); } finally { + await useFrontendServices(); await resetState(); } }; @@ -858,10 +852,10 @@ const resetState = async () => { setupStore.selectedSetupToRemove = []; manageStore.isLineHidden = false; await listKeys(); + await updateDom(); setTimeout(() => { manageStore.disableConfirmButton = false; }, 3000); - await updateDom(); }; const nukeConfirmation = () => { diff --git a/launcher/src/components/UI/edit-page/components/edit/setups/RenameSetup.vue b/launcher/src/components/UI/edit-page/components/edit/setups/RenameSetup.vue index 29888b8672..ddb6a3c11a 100644 --- a/launcher/src/components/UI/edit-page/components/edit/setups/RenameSetup.vue +++ b/launcher/src/components/UI/edit-page/components/edit/setups/RenameSetup.vue @@ -47,6 +47,7 @@ const renameSetup = () => { }; const confirmRename = () => { + if(setupStore.setupToRename.trim() === "" || setupStore.setupToRename.trim() === "commonServices") return; emit("confirmRename"); }; diff --git a/launcher/src/components/UI/edit-page/components/edit/setups/SetupMenu.vue b/launcher/src/components/UI/edit-page/components/edit/setups/SetupMenu.vue index efb09470ef..3d87827fc8 100755 --- a/launcher/src/components/UI/edit-page/components/edit/setups/SetupMenu.vue +++ b/launcher/src/components/UI/edit-page/components/edit/setups/SetupMenu.vue @@ -24,6 +24,7 @@ diff --git a/launcher/src/composables/multiSetups.js b/launcher/src/composables/multiSetups.js index 56b7cf8725..fa7749553c 100644 --- a/launcher/src/composables/multiSetups.js +++ b/launcher/src/composables/multiSetups.js @@ -3,10 +3,8 @@ import { useServices } from "@/store/services"; import { useSetups } from "@/store/setups"; import { useNodeManage } from "@/store/nodeManage"; import { useDeepClone } from "@/composables/utils"; -import { ref } from "vue"; export const useMultiSetups = () => { - const services = ref([]); const setupStore = useSetups(); const serviceStore = useServices(); const manageStore = useNodeManage(); @@ -20,14 +18,6 @@ export const useMultiSetups = () => { } }; - const loadServices = async () => { - try { - services.value = await ControlService.getServices(); - } catch (e) { - console.error("Couldn't read services", e); - } - }; - const parseYAMLData = (data) => { const parsedConfigs = []; const lines = data.split("\n"); @@ -64,8 +54,8 @@ export const useMultiSetups = () => { setupType: config.setupType, network: config.network, color: config.color, - services: services.value - .filter((service) => config.serviceIds.includes(service.id)) + services: serviceStore.installedServices + .filter((service) => config.serviceIds.includes(service.config.serviceID)) .map((s) => { return { ...s, @@ -97,38 +87,15 @@ export const useMultiSetups = () => { setupStore.selectedSetup = null; }; - const updateInstalledServices = () => { - serviceStore.installedServices = serviceStore.installedServices.map((service) => { - if (!service.setupId) { - for (const setup of setupStore.allSetups) { - const matchingService = setup.services.find((s) => s.id === service?.config?.serviceID); - - if (matchingService) { - return { - ...service, - setupId: setup.setupId, - setupName: setup.setupName, - }; - } - } - } - return service; - }); - }; - const updateDom = async () => { - await loadSetups(); - await loadServices(); setupStore.allSetups = getAllSetups(); setupStore.editSetups = getAllSetups(); - updateInstalledServices(); manageStore.newConfiguration = useDeepClone(serviceStore.installedServices); setupStore.updateSelectedSetup(); }; return { loadSetups, - loadServices, getAllSetups, getSelectedSetup, getServerView, diff --git a/launcher/src/composables/pingQuality.js b/launcher/src/composables/pingQuality.js index 8c48483965..1246fd94c5 100644 --- a/launcher/src/composables/pingQuality.js +++ b/launcher/src/composables/pingQuality.js @@ -1,23 +1,37 @@ import { useNodeStore } from "@/store/theNode"; import ControlService from "@/store/ControlService.js"; -import { ref, onUnmounted } from "vue"; +import { ref } from "vue"; export function usePingQuality() { const nodeStore = useNodeStore(); let connectionStatus = ref(null); - let intervalId = null; // Compare real-time ping with predefined ping quality levels const getConnectionQuality = (pingTime) => { + nodeStore.pingHistory.push(pingTime); + if (nodeStore.pingHistory.length > 3) { + nodeStore.pingHistory.shift(); + } + + if (nodeStore.pingHistory.every(val => val === "unknown") && nodeStore.pingHistory.length === 3) { + return { + status: "unknown", + description: "Unable to determine connection quality.", + }; + } + + if (pingTime === "unknown") { + pingTime = nodeStore.pingHistory.find(val => val !== "unknown") + } + for (let i = 0; i < nodeStore.pingQuality.length; i++) { if (pingTime <= nodeStore.pingQuality[i].maxRate) { - return nodeStore.pingQuality[i]; + return { + ...nodeStore.pingQuality[i], + pingTime: pingTime, + }; } } - return { - status: "unknown", - description: "Unable to determine connection quality.", - }; }; const checkConnectionQuality = async () => { @@ -26,7 +40,7 @@ export function usePingQuality() { const quality = getConnectionQuality(res.pingTime); connectionStatus.value = { status: quality.status, - pingTime: res.pingTime, + pingTime: quality.pingTime, description: quality.description, }; nodeStore.connectionStatus = connectionStatus.value; @@ -40,28 +54,7 @@ export function usePingQuality() { } }; - const startPolling = () => { - if (!intervalId) { - intervalId = setInterval(async () => { - await checkConnectionQuality(); - }, 10000); // Polling interval - } - }; - - const stopPolling = () => { - if (intervalId) { - clearInterval(intervalId); - intervalId = null; - } - }; - - onUnmounted(() => { - stopPolling(); // Clean up interval on component unmount - }); - return { checkConnectionQuality, - startPolling, - stopPolling, }; } diff --git a/launcher/src/composables/services.js b/launcher/src/composables/services.js index 1a02feea1c..5536d5bc59 100644 --- a/launcher/src/composables/services.js +++ b/launcher/src/composables/services.js @@ -4,6 +4,9 @@ import { useNodeHeader } from "@/store/nodeHeader"; import { useNodeManage } from "@/store/nodeManage"; import { useFooter } from "@/store/theFooter"; import { useDeepClone } from "@/composables/utils"; +import { useMultiSetups } from "@/composables/multiSetups"; +import { useSetups } from "@/store/setups"; +import { usePingQuality } from "@/composables/pingQuality"; export async function useBackendServices(force = false) { const serviceStore = useServices(); @@ -43,13 +46,21 @@ export async function useFrontendServices() { const serviceStore = useServices(); const nodeHeaderStore = useNodeHeader(); const nodeManageStore = useNodeManage(); - + const setupStore = useSetups(); + const { loadSetups, getAllSetups } = useMultiSetups(); + const { checkConnectionQuality } = usePingQuality(); + checkConnectionQuality(); const allServices = JSON.parse(JSON.stringify(serviceStore.allServices)); if (nodeHeaderStore.refresh) { if (await useConnectionCheck()) { let services; + let setups; try { services = await ControlService.refreshServiceInfos(); + await loadSetups(); + setups = getAllSetups(); + setupStore.allSetups = setups; + setupStore.editSetups = setups; } catch (error) { console.log(error); return; @@ -111,13 +122,27 @@ export async function useFrontendServices() { } return oldService; }); - serviceStore.installedServices = newServices.concat(otherServices).map((e, i) => { - e.id = i; - return e; + serviceStore.installedServices = newServices.concat(otherServices).map((service, i) => { + service.id = i; + if (!service.setupId) { + for (const setup of setups) { + const matchingService = setup.services.find((s) => s?.config?.serviceID === service?.config?.serviceID); + + if (matchingService) { + return { + ...service, + setupId: setup.setupId, + setupName: setup.setupName, + }; + } + } + } + return service; }); let network = serviceStore.installedServices[0]?.config?.network; nodeManageStore.currentNetwork = nodeManageStore.networkList.find((item) => item.network === network); + // Mange Tunnels if (needForTunnel.length != 0 && nodeHeaderStore.refresh) { let localPorts = await ControlService.getAvailablePort({ min: 9000, diff --git a/launcher/src/store/theNode.js b/launcher/src/store/theNode.js index 149f6229c4..cbc5d66bf4 100755 --- a/launcher/src/store/theNode.js +++ b/launcher/src/store/theNode.js @@ -35,6 +35,7 @@ export const useNodeStore = defineStore("theNode", { description: "Very poor connection quality with high latency.Try reconnecting to the node.", }, ], + pingHistory: [], connectionStatus: null, connectionStatusIsPoor: false, skeletonLoading: false,