ng-app: feat: add connecting status to store and add pulsing logo

Laurin Weger 4 months ago
parent eb50e2c90f
commit 4672acff0c
No known key found for this signature in database
GPG Key ID: 9B372BB0B792770F
  1. 12
      ng-app/src/lib/FullLayout.svelte
  2. 10
      ng-app/src/lib/Home.svelte
  3. 64
      ng-app/src/lib/components/Logo.svelte
  4. 51
      ng-app/src/store.ts

@ -19,11 +19,7 @@
import { link, location } from "svelte-spa-router"; import { link, location } from "svelte-spa-router";
import MobileBottomBarItem from "./MobileBottomBarItem.svelte"; import MobileBottomBarItem from "./MobileBottomBarItem.svelte";
import MobileBottomBar from "./MobileBottomBar.svelte"; import MobileBottomBar from "./MobileBottomBar.svelte";
// @ts-ignore import Logo from "./components/Logo.svelte";
import Logo from "../assets/nextgraph.svg?component";
// @ts-ignore
import LogoGray from "../assets/nextgraph-gray.svg?component";
import { online } from "../store";
import { onMount, tick } from "svelte"; import { onMount, tick } from "svelte";
@ -96,11 +92,7 @@
<SidebarGroup ulClass="space-y-1 tall:space-y-2"> <SidebarGroup ulClass="space-y-1 tall:space-y-2">
<SidebarItem label="NextGraph" href="#/user" class="mt-1"> <SidebarItem label="NextGraph" href="#/user" class="mt-1">
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
{#if $online} <Logo className="w-7 h-7 tall:w-10 tall:h-10" />
<Logo class="w-7 h-7 tall:w-10 tall:h-10" />
{:else}
<LogoGray class="w-7 h-7 tall:w-10 tall:h-10" />
{/if}
</svelte:fragment> </svelte:fragment>
</SidebarItem> </SidebarItem>
<SidebarItem <SidebarItem

@ -10,7 +10,6 @@
--> -->
<script lang="ts"> <script lang="ts">
import { online } from "../store";
import FullLayout from "./FullLayout.svelte"; import FullLayout from "./FullLayout.svelte";
import Test from "./Test.svelte"; import Test from "./Test.svelte";
import { import {
@ -19,10 +18,7 @@
ArrowRightOnRectangle, ArrowRightOnRectangle,
Users, Users,
} from "svelte-heros-v2"; } from "svelte-heros-v2";
// @ts-ignore import Logo from "./components/Logo.svelte";
import Logo from "../assets/nextgraph.svg?component";
// @ts-ignore
import LogoGray from "../assets/nextgraph-gray.svg?component";
let width: number; let width: number;
let breakPoint: number = 662; let breakPoint: number = 662;
@ -43,11 +39,7 @@
class="mx-auto flex flex-wrap justify-between items-center w-full px-2 xxs:px-8 xs:px-10" class="mx-auto flex flex-wrap justify-between items-center w-full px-2 xxs:px-8 xs:px-10"
> >
<a href="#/user" class="flex items-center" on:click> <a href="#/user" class="flex items-center" on:click>
{#if $online}
<Logo class="w-7 h-7 tall:w-10 tall:h-10" /> <Logo class="w-7 h-7 tall:w-10 tall:h-10" />
{:else}
<LogoGray class="w-7 h-7 tall:w-10 tall:h-10" />
{/if}
<span <span
class="ml-4 self-center text-lg font-normal text-gray-900 rounded-lg dark:text-white whitespace-nowrap" class="ml-4 self-center text-lg font-normal text-gray-900 rounded-lg dark:text-white whitespace-nowrap"
>NextGraph</span >NextGraph</span

@ -0,0 +1,64 @@
<!--
// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
-->
<!--
@component Logo
The NextGraph Logo svg with color changing between blue and gray,
depending on connection status:
- connected: blue
- connecting: pulse between blue and gray
- disconnected: gray
Provide classes using the `className` prop.
-->
<script lang="ts">
import { connection_status } from "../../store";
// @ts-ignore
import Logo from "../../assets/nextgraph.svg?component";
export let className: string = "";
// Color is adjusted to connection status.
let connection_status_class = ""; // Default is blue.
if ($connection_status === "connecting") {
connection_status_class = "logo-pulse";
} else if ($connection_status === "disconnected") {
connection_status_class = "logo-gray";
}
</script>
<Logo class={`${className} ${connection_status_class}`} />
<!-- Sorry for the global but this way we can change the Logo's css from this component. -->
<style global>
@keyframes pulse-logo-color {
0%,
100% {
/* Default colors come from the svg. */
}
50% {
/* Mid-transition color */
stroke: #888;
fill: #888;
}
}
.logo-pulse path {
animation: pulse-logo-color 2s infinite;
animation-timing-function: cubic-bezier(0.65, 0.01, 0.59, 0.83);
}
.logo-gray path {
fill: #888;
stroke: #888;
}
</style>

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
import { writable, readable, readonly, derived, get } from "svelte/store"; import { writable, readable, readonly, derived, get, type Writable } from "svelte/store";
import ng from "./api"; import ng from "./api";
let all_branches = {}; let all_branches = {};
@ -19,31 +19,58 @@ export const active_wallet = writable(undefined);
export const wallets = writable({}); export const wallets = writable({});
export const connections = writable({}); export const connections: Writable<Record<string, any>> = writable({});
export const active_session = writable(undefined); export const active_session = writable(undefined);
let next_reconnect = null; export const connection_status: Writable<"disconnected" | "connected" | "connecting"> = writable("disconnected");
export const online = derived(connections,($connections) => { let next_reconnect: NodeJS.Timeout | null = null;
for (const cnx of Object.keys($connections)) {
if (!$connections[cnx].error) return true; const updateConnectionStatus = ($connections: Record<string, any> ) => {
else if ($connections[cnx].error=="PeerAlreadyConnected") { // Reset error state for PeerAlreadyConnected errors.
connections.update((c) => { Object.entries($connections).forEach(([cnx, connection]) => {
if (connection.error === "PeerAlreadyConnected") {
connections.update(c => {
c[cnx].error = undefined; c[cnx].error = undefined;
return c; return c;
}); });
return true; } }
else if ($connections[cnx].error=="ConnectionError" && !$connections[cnx].connecting && next_reconnect==null) { });
// Check if any connection is active.
const is_connected = Object.values($connections).some(connection => !connection.error);
// Check if any connection is connecting.
const is_connecting = Object.values($connections).some(connection => connection.connecting);
// Check, if reconnect is needed.
const should_reconnect = !is_connecting && (next_reconnect === null) && Object.values($connections).some(
connection => connection.error === "ConnectionError"
);
if (should_reconnect) {
console.log("will try reconnect in 20 sec"); console.log("will try reconnect in 20 sec");
next_reconnect = setTimeout(async () => { next_reconnect = setTimeout(async () => {
await reconnect(); await reconnect();
connection_status.set("connecting");
next_reconnect = null;
}, 20000); }, 20000);
} }
if (is_connected) {
connection_status.set("connected");
} else if (!is_connected && is_connecting) {
connection_status.set("connecting");
} else {
connection_status.set("disconnected");
} }
return false; };
connections.subscribe(($connections) => {
updateConnectionStatus($connections);
}); });
export const online = derived(connection_status,($connectionStatus) => $connectionStatus == "connected");
export const cannot_load_offline = writable(false); export const cannot_load_offline = writable(false);
if (!get(online) && !import.meta.env.TAURI_PLATFORM) { if (!get(online) && !import.meta.env.TAURI_PLATFORM) {
@ -123,8 +150,6 @@ export const reconnect = async function() {
get(active_session).user, get(active_session).user,
location.href location.href
)); ));
}catch (e) { }catch (e) {
console.error(e) console.error(e)
} }

Loading…
Cancel
Save