Rewild Your Web
web browser dweb
16
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 508943f815334a02aefc47d9da365aba115ab0f5 172 lines 4.5 kB view raw
1// SPDX-License-Identifier: AGPL-3.0-or-later 2 3import { 4 LitElement, 5 html, 6 css, 7} from "//shared.localhost:8888/third_party/lit/lit-all.min.js"; 8 9export class MobileRadialMenu extends LitElement { 10 static properties = { 11 open: { type: Boolean, reflect: true }, 12 x: { type: Number }, 13 y: { type: Number }, 14 canGoBack: { type: Boolean }, 15 canGoForward: { type: Boolean }, 16 contextMenu: { type: Object }, 17 isHomescreen: { type: Boolean }, 18 }; 19 20 // 8 zones clockwise from top 21 static zones = [ 22 { id: 0, action: "home", icon: "house", angle: -90 }, 23 { id: 1, action: "overview", icon: "layout-grid", angle: -45 }, 24 { id: 2, action: "forward", icon: "arrow-right", angle: 0 }, 25 { id: 3, action: "context-menu", icon: "ellipsis-vertical", angle: 45 }, 26 { id: 4, action: "close-view", icon: "x", angle: 90 }, 27 { id: 5, action: "settings", icon: "settings", angle: 135 }, 28 { id: 6, action: "back", icon: "arrow-left", angle: 180 }, 29 { id: 7, action: "reload", icon: "rotate-ccw", angle: -135 }, 30 ]; 31 32 static styles = css` 33 @import url(//system.localhost:8888/mobile_radial_menu.css); 34 `; 35 36 constructor() { 37 super(); 38 this.open = false; 39 this.x = 0; 40 this.y = 0; 41 this.canGoBack = false; 42 this.canGoForward = false; 43 this.contextMenu = null; 44 this.isHomescreen = false; 45 } 46 47 show(x, y, contextMenu = null) { 48 // Adjust position to keep menu on screen 49 const menuRadius = 100; 50 const padding = 20; 51 52 this.x = Math.max( 53 menuRadius + padding, 54 Math.min(window.innerWidth - menuRadius - padding, x) 55 ); 56 this.y = Math.max( 57 menuRadius + padding, 58 Math.min(window.innerHeight - menuRadius - padding, y) 59 ); 60 this.contextMenu = contextMenu; 61 this.open = true; 62 } 63 64 hide() { 65 this.open = false; 66 // Dispatch dismiss event so pending context menu can be closed 67 this.dispatchEvent( 68 new CustomEvent("radial-dismiss", { 69 bubbles: true, 70 composed: true, 71 }) 72 ); 73 this.contextMenu = null; 74 } 75 76 handleOverlayTap(e) { 77 // Tapping on overlay (outside menu) closes the menu 78 e.preventDefault(); 79 this.hide(); 80 } 81 82 handleZoneTap(zone, e) { 83 console.log(`[RadialMenu] handleZoneTap ${zone.action}`); 84 e.preventDefault(); 85 e.stopPropagation(); 86 87 // Check if action is disabled 88 if (this.isZoneDisabled(zone)) { 89 return; 90 } 91 92 // For context-menu action, close without dispatching dismiss 93 // (the context menu will be shown instead) 94 if (zone.action === "context-menu") { 95 this.dispatchEvent( 96 new CustomEvent("radial-action", { 97 bubbles: true, 98 composed: true, 99 detail: { 100 action: zone.action, 101 contextMenu: this.contextMenu, 102 }, 103 }) 104 ); 105 this.open = false; 106 this.contextMenu = null; 107 return; 108 } 109 110 // Dispatch action 111 this.dispatchEvent( 112 new CustomEvent("radial-action", { 113 bubbles: true, 114 composed: true, 115 detail: { 116 action: zone.action, 117 originX: this.x, 118 originY: this.y, 119 }, 120 }) 121 ); 122 123 this.hide(); 124 } 125 126 isZoneDisabled(zone) { 127 if (zone.action === "back") { 128 return !this.canGoBack; 129 } 130 if (zone.action === "forward") { 131 return !this.canGoForward; 132 } 133 if (zone.action === "context-menu") { 134 return !this.contextMenu || this.contextMenu.items.length === 0; 135 } 136 // Disable close-view, reload and home actions when on homescreen 137 if ( 138 zone.action === "close-view" || 139 zone.action === "home" || 140 zone.action === "reload" 141 ) { 142 return this.isHomescreen; 143 } 144 return false; 145 } 146 147 render() { 148 const menuStyle = `left: ${this.x}px; top: ${this.y}px;`; 149 150 return html` 151 <div class="overlay" @click=${this.handleOverlayTap}></div> 152 <div class="menu" style=${menuStyle}> 153 <div class="center"> 154 <div class="center-dot"></div> 155 </div> 156 ${MobileRadialMenu.zones.map( 157 (zone) => html` 158 <div 159 class="zone ${this.isZoneDisabled(zone) ? "disabled" : ""}" 160 data-zone=${zone.id} 161 @click=${(e) => this.handleZoneTap(zone, e)} 162 > 163 <lucide-icon name=${zone.icon}></lucide-icon> 164 </div> 165 ` 166 )} 167 </div> 168 `; 169 } 170} 171 172customElements.define("mobile-radial-menu", MobileRadialMenu);