A music player that connects to your cloud/distributed storage.
5
fork

Configure Feed

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

Fix drag & drop

+105 -29
+6 -4
src/Applications/UI.elm
··· 9 9 import Browser.Events 10 10 import Browser.Navigation as Nav 11 11 import Chunky exposing (..) 12 + import Classes as C 12 13 import Color 13 14 import Color.Ext as Color 14 15 import Common exposing (Switch(..)) ··· 25 26 import Html.Events.Extra.Pointer as Pointer 26 27 import Html.Events.Extra.Touch as Touch 27 28 import Html.Styled as Html exposing (Html, section, toUnstyled) 28 - import Html.Styled.Attributes as Attributes exposing (css, id, style) 29 + import Html.Styled.Attributes as Attributes exposing (class, css, id, style) 29 30 import Html.Styled.Events exposing (on, onClick) 30 31 import Html.Styled.Lazy as Lazy 31 32 import Json.Decode ··· 1268 1269 ] 1269 1270 1270 1271 else if model.isDragging then 1271 - [ Attributes.class "dragging-something" 1272 + [ Attributes.class ("dragging-something " ++ C.disable_selection) 1272 1273 , Attributes.fromUnstyled (Pointer.onUp <| always StoppedDragging) 1273 1274 , Attributes.fromUnstyled (Pointer.onCancel <| always StoppedDragging) 1274 1275 ] ··· 1277 1278 [ Attributes.fromUnstyled (Touch.onStart <| always IndicateTouchDevice) ] 1278 1279 1279 1280 else 1280 - [] 1281 + [ class C.disable_selection ] 1281 1282 ) 1282 1283 [ Css.Global.global globalCss 1283 1284 ··· 1533 1534 1534 1535 -- 1535 1536 , Css.Global.selector ".disable-selection" 1536 - [ Css.property "-webkit-user-select" "none" 1537 + [ Css.property "-webkit-touch-callout" "none" 1538 + , Css.property "-webkit-user-select" "none" 1537 1539 , Css.property "-moz-user-select" "none" 1538 1540 , Css.property "-ms-user-select" "none" 1539 1541 , Css.property "user-select" "none"
+4 -3
src/Applications/UI/List.elm
··· 95 95 [ T.flex 96 96 , T.fw6 97 97 , T.items_center 98 - , T.pv3 99 98 100 99 -- 101 100 , ifThenElse (Maybe.isJust msg) T.pointer "" ··· 103 102 [ -- Label 104 103 -------- 105 104 chunk 106 - [ C.pointer_events_none, T.flex_grow_1 ] 105 + [ C.pointer_events_none, T.flex_grow_1, T.mv3 ] 107 106 [ label ] 108 107 109 108 -- Actions ··· 166 165 [ Attributes.title "Drag me" 167 166 , Attributes.fromUnstyled (DnD.listenToStart env context) 168 167 ] 169 - [ C.lh_0 168 + [ C.disable_selection 169 + , C.lh_0 170 170 , C.grab_cursor 171 171 , T.ml2 172 + , T.pv2 172 173 ] 173 174 [ fromUnstyled (Icons.drag_indicator 16 coloring) ] 174 175
+95 -18
src/Javascript/index.js
··· 249 249 250 250 251 251 252 - // Touch Events 253 - // ------------ 252 + // Pointer Events 253 + // -------------- 254 + // Thanks to https://github.com/mpizenberg/elm-pep/ 255 + 256 + let enteredElement 257 + 254 258 255 259 tocca({ 256 260 dbltapThreshold: 800 257 261 }) 258 262 259 263 260 - // Simulate `pointerenter` and `pointerleave` event for touch devices 261 - let enteredElement 264 + function mousePointerEvent(eventType, mouseEvent) { 265 + let pointerEvent = new MouseEvent(eventType, mouseEvent) 266 + pointerEvent.pointerId = 1 267 + pointerEvent.isPrimary = true 268 + pointerEvent.pointerType = "mouse" 269 + pointerEvent.width = 1 270 + pointerEvent.height = 1 271 + pointerEvent.tiltX = 0 272 + pointerEvent.tiltY = 0 273 + 274 + "buttons" in mouseEvent && mouseEvent.buttons !== 0 275 + ? (pointerEvent.pressure = 0.5) 276 + : (pointerEvent.pressure = 0) 277 + 278 + return pointerEvent 279 + } 280 + 281 + 282 + function touchPointerEvent(eventType, touchEvent, touch) { 283 + let pointerEvent = new CustomEvent(eventType, { 284 + bubbles: true, 285 + cancelable: true 286 + }) 287 + 288 + pointerEvent.ctrlKey = touchEvent.ctrlKey 289 + pointerEvent.shiftKey = touchEvent.shiftKey 290 + pointerEvent.altKey = touchEvent.altKey 291 + pointerEvent.metaKey = touchEvent.metaKey 292 + 293 + pointerEvent.clientX = touch.clientX 294 + pointerEvent.clientY = touch.clientY 295 + pointerEvent.screenX = touch.screenX 296 + pointerEvent.screenY = touch.screenY 297 + pointerEvent.pageX = touch.pageX 298 + pointerEvent.pageY = touch.pageY 299 + 300 + const rect = touch.target.getBoundingClientRect() 301 + pointerEvent.offsetX = touch.clientX - rect.left 302 + pointerEvent.offsetY = touch.clientY - rect.top 303 + pointerEvent.pointerId = 1 + touch.identifier 304 + 305 + pointerEvent.button = 0 306 + pointerEvent.buttons = 1 307 + pointerEvent.movementX = 0 308 + pointerEvent.movementY = 0 309 + pointerEvent.region = null 310 + pointerEvent.relatedTarget = null 311 + pointerEvent.x = pointerEvent.clientX 312 + pointerEvent.y = pointerEvent.clientY 313 + 314 + pointerEvent.pointerType = "touch" 315 + pointerEvent.width = 1 316 + pointerEvent.height = 1 317 + pointerEvent.tiltX = 0 318 + pointerEvent.tiltY = 0 319 + pointerEvent.pressure = 1 320 + pointerEvent.isPrimary = true 321 + 322 + return pointerEvent 323 + } 324 + 262 325 326 + // Simulate `pointerenter` and `pointerleave` event for non-touch devices 327 + if (!self.PointerEvent) { 328 + document.addEventListener("mouseover", event => { 329 + const section = document.body.querySelector("section") 330 + const isDragging = section && section.classList.contains("dragging-something") 331 + const node = isDragging && document.elementFromPoint(event.clientX, event.clientY) 332 + 333 + if (node && node != enteredElement) { 334 + enteredElement && enteredElement.dispatchEvent(mousePointerEvent("pointerleave", event)) 335 + node.dispatchEvent(mousePointerEvent("pointerenter", event)) 336 + enteredElement = node 337 + } 338 + }) 339 + } 340 + 341 + 342 + // Simulate `pointerenter` and `pointerleave` event for touch devices 263 343 document.body.addEventListener("touchmove", event => { 344 + const section = document.body.querySelector("section") 345 + const isDragging = section && section.classList.contains("dragging-something") 346 + 264 347 let touch = event.touches[0] 265 348 let node 266 349 267 - if (touch) { 350 + if (isDragging && touch) { 268 351 node = document.elementFromPoint(touch.clientX, touch.clientY) 269 352 } 270 353 271 354 if (node && node != enteredElement) { 272 - const eventOpts = { 273 - clientX: touch.clientX, 274 - clientY: touch.clientY, 275 - isPrimary: true, 276 - pointerType: "touch" 277 - } 278 - 279 - const eventClass = 280 - self.PointerEvent || self.MouseEvent 281 - 282 - enteredElement && enteredElement.dispatchEvent(new eventClass("pointerleave", eventOpts)) 283 - node.dispatchEvent(new eventClass("pointerenter", eventOpts)) 284 - 355 + enteredElement && enteredElement.dispatchEvent(touchPointerEvent("pointerleave", event, touch)) 356 + node.dispatchEvent(touchPointerEvent("pointerenter", event, touch)) 285 357 enteredElement = node 358 + } 359 + 360 + if (isDragging) { 361 + event.preventDefault() 362 + event.stopPropagation() 286 363 } 287 364 }) 288 365
-4
src/Static/Html/Application.html
··· 9 9 <meta name="media-controllable" /> 10 10 <meta name="apple-mobile-web-app-capable" content="yes" /> 11 11 12 - <!-- <base href="{{ getenv "BASE" "" }}" /> --> 13 - 14 12 <title>Diffuse</title> 15 13 16 14 <!-- Viewport --> ··· 91 89 92 90 93 91 <!-- Scripts --> 94 - <script>const BASE = new URL(document.baseURI).pathname</script> 95 - 96 92 <script src="vendor/pep.min.js"></script> 97 93 <script src="vendor/subworkers-polyfill.min.js"></script> 98 94 <script src="vendor/tocca.min.js"></script>