Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Fix mobile context menu
Rūdolfs Ošiņš committed 3 years ago
commit 251f9681bcc93036839ea09a35f9c9b5058402f1
parent 604d8f4f35c576b6657a7443a16420d773c15e54
9 files changed +92 -150
modified src/Floating.svelte
@@ -9,6 +9,7 @@

<script lang="ts">
  export let disabled = false;
+
  export let overlay = false;

  let expanded = false;
  let thisComponent: HTMLDivElement;
@@ -33,14 +34,35 @@
  $: expanded = $focused === thisComponent;
</script>

+
<style>
+
  .overlay {
+
    background-color: #00000075;
+
    position: fixed;
+
    top: 0;
+
    left: 0;
+
    width: 100%;
+
    height: 100%;
+
  }
+

+
  .toggle {
+
    user-select: none;
+
  }
+
</style>
+

<svelte:window on:click={clickOutside} />

<div bind:this={thisComponent}>
-
  <div on:click={toggle}>
+
  <div
+
    on:click={toggle}
+
    class="toggle"
+
    style:cursor={disabled ? "not-allowed" : "pointer"}>
    <slot name="toggle" />
  </div>

  {#if expanded}
+
    {#if overlay}
+
      <div class="overlay" on:click={toggle} />
+
    {/if}
    <slot name="modal" />
  {/if}
</div>
modified src/Header.svelte
@@ -1,24 +1,27 @@
<script lang="ts">
-
  import { link } from "svelte-routing";
-
  import { formatAddress, formatBalance } from "@app/utils";
-
  import { error, Failure } from "@app/error";
-
  import { disconnectWallet } from "@app/session";
+
  import type { Config } from "@app/config";
+
  import type { ResolvedSearch } from "@app/resolver";
  import type { Session } from "@app/session";
+

+
  import { link } from "svelte-routing";
+

+
  import Avatar from "@app/Avatar.svelte";
+
  import Button from "@app/Button.svelte";
+
  import Connect from "@app/Connect.svelte";
+
  import Floating from "@app/Floating.svelte";
+
  import Icon from "@app/Icon.svelte";
  import Loading from "@app/Loading.svelte";
  import Logo from "@app/Logo.svelte";
-
  import Connect from "@app/Connect.svelte";
-
  import type { Config } from "@app/config";
-
  import { Profile, ProfileType } from "@app/profile";
-
  import Avatar from "@app/Avatar.svelte";
  import Search from "@app/Search.svelte";
-
  import Floating from "@app/Floating.svelte";
-
  import Icon from "./Icon.svelte";
-
  import MobileNavbar from "./MobileNavbar.svelte";
-
  import SeedDropdown from "./SeedDropdown.svelte";
-
  import ThemeToggle from "./ThemeToggle.svelte";
-
  import Button from "@app/Button.svelte";
  import SearchResults from "@app/components/Modal/SearchResults.svelte";
-
  import type { ResolvedSearch } from "@app/resolver";
+
  import SeedDropdown from "@app/SeedDropdown.svelte";
+
  import ThemeToggle from "@app/ThemeToggle.svelte";
+

+
  import { Profile, ProfileType } from "@app/profile";
+
  import { closeFocused } from "@app/Floating.svelte";
+
  import { disconnectWallet } from "@app/session";
+
  import { error, Failure } from "@app/error";
+
  import { formatAddress, formatBalance } from "@app/utils";

  export let session: Session | null;
  export let config: Config;
@@ -27,12 +30,8 @@
  let results: ResolvedSearch;

  let sessionButtonHover = false;
-
  let mobileNavbarDisplayed = false;
  let searchResultsDisplayed = false;

-
  function toggleNavbar() {
-
    mobileNavbarDisplayed = !mobileNavbarDisplayed;
-
  }
  function toggleSearchResults() {
    searchResultsDisplayed = !searchResultsDisplayed;
  }
@@ -123,9 +122,6 @@
    white-space: nowrap;
  }

-
  div.toggle {
-
    display: none;
-
  }
  @media (max-width: 720px) {
    header .right {
      gap: 1rem;
@@ -137,15 +133,23 @@
    .balance {
      display: none;
    }
-
    div.toggle {
-
      display: flex;
-
      justify-content: center;
-
      align-items: center;
-
      height: 42px;
-
      width: 42px;
-
      z-index: 2;
-
      cursor: pointer;
-
    }
+
  }
+
  .modal {
+
    background: var(--color-background);
+
    border-radius: var(--border-radius);
+
    max-width: 22.5rem;
+
    min-width: 18rem;
+
    padding: 1.5rem;
+
    position: absolute;
+
    right: 1.5rem;
+
    top: 5rem;
+
  }
+
  .modal a {
+
    color: var(--color-foreground-6);
+
    padding-left: 0.5rem;
+
  }
+
  .modal a:hover {
+
    color: var(--color-foreground);
  }
</style>

@@ -180,7 +184,7 @@
      {#if session && Object.keys(session.siwe).length > 0}
        <span class="seeds-container">
          <Floating>
-
            <span slot="toggle" class="nav-link">Seeds</span>
+
            <span slot="toggle">Seeds</span>
            <svelte:fragment slot="modal">
              <SeedDropdown seeds={session.siwe} {config} />
            </svelte:fragment>
@@ -237,22 +241,41 @@
      </span>
    {/if}
    <ThemeToggle />
-
    <div class="toggle" on:click={toggleNavbar}>
-
      <span style="transform: scale(1.2);">
-
        <Icon name="ellipsis" />
-
      </span>
+
    <div class="mobile">
+
      <Floating overlay>
+
        <div slot="toggle">
+
          <span style="transform: scale(1.2);">
+
            <Icon name="ellipsis" />
+
          </span>
+
        </div>
+

+
        <svelte:fragment slot="modal">
+
          <div class="modal">
+
            <div style="padding-bottom: 1rem;">
+
              <Search
+
                {config}
+
                on:finished={() => {
+
                  closeFocused();
+
                }}
+
                on:search={e => {
+
                  ({ query, results } = e.detail);
+
                  toggleSearchResults();
+
                }} />
+
            </div>
+
            <a
+
              use:link
+
              on:click={() => {
+
                closeFocused();
+
              }}
+
              href="/registrations">
+
              Register
+
            </a>
+
          </div>
+
        </svelte:fragment>
+
      </Floating>
    </div>
  </div>

-
  {#if mobileNavbarDisplayed}
-
    <MobileNavbar
-
      {config}
-
      on:search={e => {
-
        ({ query, results } = e.detail);
-
        toggleSearchResults();
-
        toggleNavbar();
-
      }} />
-
  {/if}
  {#if searchResultsDisplayed}
    <SearchResults {config} {results} {query} on:close={toggleSearchResults} />
  {/if}
deleted src/MobileNavbar.svelte
@@ -1,78 +0,0 @@
-
<script lang="ts">
-
  import { link } from "svelte-routing";
-
  import { createEventDispatcher } from "svelte";
-
  import Search from "./Search.svelte";
-
  import { clickOutside } from "@app/utils";
-
  import type { Config } from "@app/config";
-

-
  const dispatch = createEventDispatcher();
-

-
  export let config: Config;
-

-
  function handleClickOutside() {
-
    dispatch("select");
-
  }
-
</script>
-

-
<style>
-
  .modal-floating {
-
    position: absolute;
-
    top: 0;
-
    left: 0;
-
    width: 100%;
-
    height: 100%;
-
    overflow: hidden;
-
  }
-
  .modal-floating {
-
    z-index: 300;
-
    display: flex;
-
    align-items: center;
-
    justify-content: center;
-
    background-color: #000000bf;
-
  }
-
  .modal {
-
    position: absolute;
-
    top: 90px;
-
    right: 1.5rem;
-
    padding: 1.5rem;
-
    font-family: var(--font-family-sans-serif);
-
    background: var(--color-background);
-
    min-width: 240px;
-
    max-width: 360px;
-
    border-radius: var(--border-radius);
-
    text-align: center;
-
  }
-
  .modal-title {
-
    color: var(--color-foreground);
-
    font-size: var(--font-size-regular);
-
    line-height: 2rem;
-
    text-align: left;
-
    text-overflow: ellipsis;
-
    overflow: hidden;
-
  }
-
  .modal-title a {
-
    color: var(--color-foreground-6);
-
    padding-left: 1.5rem;
-
  }
-
  .modal-title a:hover {
-
    color: var(--color-foreground);
-
  }
-
  .modal-title a:first-child {
-
    padding-left: 0.5rem;
-
  }
-
</style>
-

-
<div class="modal-floating">
-
  <div use:clickOutside={handleClickOutside} class="modal">
-
    <div class="modal-title">
-
      <div style="padding-bottom: 1rem;">
-
        <Search {config} on:search />
-
      </div>
-
      <div>
-
        <a use:link on:click={() => dispatch("select")} href="/registrations">
-
          Register
-
        </a>
-
      </div>
-
    </div>
-
  </div>
-
</div>
modified src/Search.svelte
@@ -21,6 +21,7 @@
      }
      input = "";
      searching = false;
+
      dispatch("finished");
    }
  };
</script>
modified src/base/projects/BranchSelector.svelte
@@ -39,12 +39,10 @@
    font-family: var(--font-family-monospace);
  }
  .commit .branch {
-
    cursor: pointer;
    padding: 0.5rem 0.75rem;
    color: var(--color-secondary);
    background-color: var(--color-secondary-2);
    border-radius: var(--border-radius-small) 0 0 var(--border-radius-small);
-
    user-select: none;
  }
  .commit .branch.not-allowed {
    cursor: not-allowed;
modified src/base/projects/CloneButton.svelte
@@ -16,11 +16,9 @@
    background-color: var(--color-caution-2);
    border-radius: var(--border-radius-small);
    color: var(--color-caution-6);
-
    cursor: pointer;
    font-family: var(--font-family-monospace);
    min-width: max-content;
    padding: 0.5rem 0.75rem;
-
    user-select: none;
  }
  .clone-button:hover {
    background-color: var(--color-caution-3);
modified src/base/projects/Patch/PatchTabBar.svelte
@@ -65,7 +65,6 @@
  .revision-toggle:hover {
    background-color: var(--color-foreground-1);
    color: var(--color-foreground);
-
    cursor: pointer;
  }
  .revision-toggle:disabled {
    color: var(--color-foreground-5);
modified src/base/projects/PeerSelector.svelte
@@ -59,12 +59,10 @@
    font-family: var(--font-family-monospace);
  }
  .selector .peer {
-
    cursor: pointer;
    padding: 0.5rem;
    color: var(--color-secondary);
    background-color: var(--color-secondary-2);
    border-radius: var(--border-radius-small);
-
    user-select: none;
  }
  .selector .peer.not-allowed {
    cursor: not-allowed;
modified src/utils.ts
@@ -209,25 +209,6 @@ export function parseEnsLabel(name: string, config: Config): string {
  return label;
}

-
export function clickOutside(
-
  node: HTMLElement,
-
  onEventFunction: () => void,
-
): any {
-
  const handleClick = (event: any) => {
-
    const path = event.composedPath();
-
    if (!path.includes(node)) {
-
      onEventFunction();
-
    }
-
  };
-
  document.addEventListener("click", handleClick, true);
-

-
  return {
-
    destroy() {
-
      document.removeEventListener("click", handleClick, true);
-
    },
-
  };
-
}
-

// Get the mime type of an image, given a file path.
// Returns `null` if unknown.
export function getImageMime(path: string): string | null {