Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,9 @@
"lint-staged": {
"*.{js,jsx,ts,tsx,css,scss,svelte,vue}": "eslint --fix",
"*.{js,ts,css,scss,md,svelte,vue,yaml}": "prettier .prettierrc --write"
},
"resolutions": {
"axios": "^1.12.0",
"@babel/runtime": "^7.26.10"
}
}
1 change: 1 addition & 0 deletions packages/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@threefold/types": "2.9.1",
"@types/ip": "^1.1.3",
"@types/md5": "^2.3.5",
"@vueuse/core": "^14.0.0",
"await-lock": "^3.0.0",
"bip39": "^3.1.0",
"chart.js": "^4.4.9",
Expand Down
6 changes: 5 additions & 1 deletion packages/playground/src/components/TfNavigationLoader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</template>

<script lang="ts">
import { computed, ref, type StyleValue, watch } from "vue";
import { computed, onUnmounted, ref, type StyleValue, watch } from "vue";

import { useNavigationStatus, useOnline } from "../hooks";

Expand Down Expand Up @@ -72,6 +72,10 @@ export default {
};
});

onUnmounted(() => {
clear();
});

return { loadingValue, style };
},
};
Expand Down
13 changes: 9 additions & 4 deletions packages/playground/src/components/TfOfflineNotifier.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@
</VCardText>

<VCardActions v-if="failed" class="d-flex justify-center mb-4">
<VBtn prepend-icon="mdi-reload" variant="outlined" color="secondary" @click="reload">
Reload Now
</VBtn>
<VBtn prepend-icon="mdi-reload" variant="outlined" color="secondary" @click="reload"> Reload Now </VBtn>
</VCardActions>
</VCard>
</VDialog>
</template>

<script lang="ts">
import { computed, ref, watch } from "vue";
import { computed, onUnmounted, ref, watch } from "vue";

import { useOffline } from "../hooks";

Expand Down Expand Up @@ -81,6 +79,13 @@ export default {
can reload instantly.`;
});

onUnmounted(() => {
if (interval) {
clearInterval(interval);
interval = null;
}
});

return { offline, failed, reload, dotCount, title, description };
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ import { ContractStates, type GridClient, type OverdueDetails } from "@threefold
import { type Contract, ContractState, type NodeStatus } from "@threefold/gridproxy_client";
import { TFChainError } from "@threefold/tfchain_client";
import { DeploymentKeyDeletionError } from "@threefold/types";
import { capitalize, computed, defineComponent, type PropType, type Ref, ref, watch } from "vue";
import { capitalize, computed, defineComponent, onUnmounted, type PropType, type Ref, ref, watch } from "vue";
import { useDocumentVisibility } from "@vueuse/core";

import { useProfileManagerController } from "@/components/profile_manager_controller.vue";
import type { VDataTableHeader } from "@/types";
Expand Down Expand Up @@ -423,6 +424,9 @@ const freeBalance = computed(() => balance.value?.free ?? 0);
const unlockContractLoading = ref(false);
const unlockDialog = ref(false);
const rentContracts = ref<{ [key: number]: number }>({}); // to store the node id with its rent contract
const visibility = useDocumentVisibility();
const isVisible = computed(() => visibility.value === "visible");
const timeouts: ReturnType<typeof setTimeout>[] = [];
const selectedLockedContracts = computed(() => {
if (selectedContracts.value.length == 0) return false;
for (const contract of selectedContracts.value) {
Expand Down Expand Up @@ -615,7 +619,11 @@ async function unlockContract(contractId: number[]) {
`Your request to unlock contract ${contractId} has been processed successfully. Changes may take a few minutes to reflect`,
ToastType.info,
);
setTimeout(() => emits("update:unlock-contracts"), 30000);
// Only schedule refresh if tab is visible
if (isVisible.value) {
const timeoutId = setTimeout(() => emits("update:unlock-contracts"), 30000);
timeouts.push(timeoutId);
}
contractStateDialog.value = false;
unlockDialog.value = false;
selectedContracts.value = [];
Expand All @@ -629,6 +637,20 @@ async function unlockContract(contractId: number[]) {
watch(contractStateDialog, contractStateDialog => {
if (!contractStateDialog) selectedItem.value = undefined;
});

// Cleanup timeouts when tab becomes inactive
watch(isVisible, visible => {
if (!visible) {
timeouts.forEach(timeout => clearTimeout(timeout));
timeouts.length = 0;
}
});

onUnmounted(() => {
timeouts.forEach(timeout => clearTimeout(timeout));
timeouts.length = 0;
});

defineExpose({
reset() {
rentContracts.value = {};
Expand Down
20 changes: 8 additions & 12 deletions packages/playground/src/components/deposit_dialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
@update:model-value="closeDialog"
>
<v-card>
<VCardTitle class="bg-primary">
Deposit TFT
</VCardTitle>
<VCardTitle class="bg-primary"> Deposit TFT </VCardTitle>
<v-card-text>
<v-container>
<v-row class="py-2">
Expand All @@ -20,9 +18,7 @@
{{ selectedName ? selectedName.charAt(0).toUpperCase() + selectedName.slice(1) : "" }}
transaction.
</p>
<p class="mt-1 mb-8 text-secondary text-sm-subtitle-2 font-weight-bold">
Deposit fee is 1 TFT
</p>
<p class="mt-1 mb-8 text-secondary text-sm-subtitle-2 font-weight-bold">Deposit fee is 1 TFT</p>
</div>
<input-tooltip
v-if="selectedName == 'stellar'"
Expand Down Expand Up @@ -53,19 +49,15 @@
<v-col>
<QRPlayStore :qr="qrCodeText">
<b> OR </b>
<p class="mb-3">
Use ThreeFold Connect to scan this QRcode:
</p>
<p class="mb-3">Use ThreeFold Connect to scan this QRcode:</p>
</QRPlayStore>
</v-col>
</v-row>
</v-container>
<v-divider />
</v-card-text>
<v-card-actions class="justify-end my-1 mr-2">
<v-btn color="anchor" @click="closeDialog">
Close
</v-btn>
<v-btn color="anchor" @click="closeDialog"> Close </v-btn>
<v-btn color="secondary" :href="manual.tft_bridges" target="_blank" text="Learn more?" />
</v-card-actions>
</v-card>
Expand Down Expand Up @@ -157,6 +149,10 @@ const closeDialog = () => {

onBeforeUnmount(() => {
destroyed = true;
if (interval.value !== null) {
window.clearInterval(interval.value);
interval.value = null;
}
});
</script>
<script lang="ts">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ import { RequestError } from "@threefold/types";
import type AwaitLock from "await-lock";
import equals from "lodash/fp/equals.js";
import { computed, nextTick, onMounted, onUnmounted, onUpdated, type PropType, ref } from "vue";
import { useDocumentVisibility } from "@vueuse/core";

import { useAsync, usePagination, useWatchDeep } from "../../hooks";
import { ValidatorStatus } from "../../hooks/form_validator";
Expand Down Expand Up @@ -195,6 +196,8 @@ export default {
},
setup(props, ctx) {
const gridStore = useGrid();
const visibility = useDocumentVisibility();
const isVisible = computed(() => visibility.value === "visible");
const _loadedNodes = ref<NodeInfo[]>([]);
const visibleAlert = ref(true);
onUpdated(() => (visibleAlert.value = true));
Expand Down Expand Up @@ -272,6 +275,9 @@ export default {
return;
}

// Skip expensive operations if tab is not visible
if (!isVisible.value) return;

if (baseFilters.value) {
if (equals(filters, baseFilters.value)) {
baseFilters.value = undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
<script lang="ts">
import type { FarmInfo } from "@threefold/grid_client";
import { computed, nextTick, onUnmounted, type PropType, ref, watch } from "vue";
import { useDocumentVisibility } from "@vueuse/core";

import { useAsync, usePagination, useWatchDeep } from "../../hooks";
import { useGrid } from "../../stores";
Expand Down Expand Up @@ -112,6 +113,8 @@ export default {
},
setup(props, ctx) {
const gridStore = useGrid();
const visibility = useDocumentVisibility();
const isVisible = computed(() => visibility.value === "visible");

/* Load farms with filters */
const loadedFarms = ref<FarmInfo[]>([]);
Expand Down Expand Up @@ -153,6 +156,8 @@ export default {
useWatchDeep(
filters,
async filters => {
// Skip expensive API calls if tab is not visible
if (!isVisible.value) return;
farmsTask.value.reset();
await pageCountTask.value.run(gridStore, filters);
pagination.value.reset(pageCountTask.value.data as number);
Expand Down
8 changes: 8 additions & 0 deletions packages/playground/src/components/weblet_layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ import { events, type GridClient, type NodeInfo } from "@threefold/grid_client";
import debounce from "lodash/debounce.js";
import { computed, ref, watch } from "vue";
import { useTheme } from "vuetify";
import { useDocumentVisibility } from "@vueuse/core";

import { manual } from "@/utils/manual";
import {
Expand Down Expand Up @@ -162,6 +163,8 @@ const emits = defineEmits<{ (event: "mount"): void; (event: "back"): void }>();
const baseUrl = import.meta.env.BASE_URL;
const profileManager = useProfileManager();
const theme = useTheme();
const visibility = useDocumentVisibility();
const isVisible = computed(() => visibility.value === "visible");
const webletLayoutContainer = ref<VCard>();
const status = ref<WebletStatus>();
const message = ref<string>();
Expand Down Expand Up @@ -346,6 +349,9 @@ const onlyIPV4UsdPrice = ref<number>();
watch(
() => [props.cpu, props.memory, props.disk, props.ipv4, props.dedicated, props.selectedNode],
debounce((value, oldValue) => {
// Skip expensive calculations if tab is not visible
if (!isVisible.value) return;

if (
oldValue &&
value[0] === oldValue[0] &&
Expand All @@ -365,6 +371,8 @@ watch(
() => [profileManager.profile, costLoading.value, shouldUpdateCost.value] as const,
([profile, loading, shouldUpdate]) => {
if (!profile || loading || !shouldUpdate) return;
// Skip expensive API calls if tab is not visible
if (!isVisible.value) return;
shouldUpdateCost.value = false;
loadCost(profile);
},
Expand Down
10 changes: 8 additions & 2 deletions packages/playground/src/dashboard/components/node_details.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@

<script setup lang="ts">
import type { GridNode } from "@threefold/gridproxy_client";
import { onMounted, type PropType, ref } from "vue";
import { onMounted, onUnmounted, type PropType, ref } from "vue";

import { gridProxyClient } from "@/clients";
import type { NodeDetailsCard } from "@/types";
Expand Down Expand Up @@ -202,14 +202,20 @@ function loadingDots() {
dots.value += ".";
}
}

onUnmounted(() => {
if (interval.value !== null) {
window.clearInterval(interval.value);
interval.value = null;
}
});
</script>

<script lang="ts">
import CardDetails from "@/components/node_details_cards/card_details.vue";
import GPUDetailsCard from "@/components/node_details_cards/gpu_details_card.vue";

export default {

name: "NodeDetails",
components: {
CardDetails,
Expand Down
Loading