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

Configure Feed

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

Slowly figuring out how to improve drag & drop

+102 -25
+40 -13
src/Applications/UI/DnD.elm
··· 1 - module UI.DnD exposing (Environment, Model, Msg, environmentSubject, environmentTarget, hasDropped, initialModel, isBeingDraggedOver, listenToDrop, listenToEnterLeave, listenToStart, modelSubject, modelTarget, stoppedDragging, update) 1 + module UI.DnD exposing (Environment, Model, Msg, environmentSubject, environmentTarget, hasDropped, initialModel, isBeingDraggedOver, isDragging, listenToDrop, listenToEnterLeave, listenToStart, modelSubject, modelTarget, stoppedDragging, update) 2 2 3 3 import Html exposing (Attribute) 4 4 import Html.Attributes as Attributes ··· 55 55 Dragging { subject } -> 56 56 DraggingOver { subject = subject, target = context } 57 57 58 + DraggingOver { subject } -> 59 + DraggingOver { subject = subject, target = context } 60 + 58 61 _ -> 59 62 model 60 63 61 - Leave _ -> 64 + Leave context -> 62 65 case model of 63 - DraggingOver { subject } -> 64 - Dragging { subject = subject } 66 + DraggingOver { subject, target } -> 67 + if context == target then 68 + Dragging { subject = subject } 69 + 70 + else 71 + model 65 72 66 73 _ -> 67 74 model ··· 94 101 95 102 listenToStart : Environment context msg -> context -> Attribute msg 96 103 listenToStart { toMsg } context = 97 - Pointer.onDown 104 + Pointer.onWithOptions 105 + "pointerdown" 106 + { stopPropagation = True 107 + , preventDefault = True 108 + } 98 109 (\event -> 99 110 case event.pointer.button of 100 111 Mouse.MainButton -> ··· 125 136 ] 126 137 127 138 128 - listenToDrop : Environment context msg -> context -> List (Attribute msg) 129 - listenToDrop { model, toMsg } context = 130 - case model of 131 - NotDragging -> 132 - [] 133 - 134 - _ -> 135 - [ context 139 + listenToDrop : Environment context msg -> List (Attribute msg) 140 + listenToDrop { model, toMsg } = 141 + case modelTarget model of 142 + Just target -> 143 + [ target 136 144 |> Drop 137 145 |> toMsg 138 146 |> always 139 147 |> Pointer.onUp 140 148 ] 149 + 150 + Nothing -> 151 + [] 141 152 142 153 143 154 stoppedDragging : Msg context ··· 213 224 environmentTarget : Environment context msg -> Maybe context 214 225 environmentTarget = 215 226 .model >> modelTarget 227 + 228 + 229 + isDragging : Environment context msg -> Bool 230 + isDragging { model } = 231 + case model of 232 + NotDragging -> 233 + False 234 + 235 + Dragging _ -> 236 + True 237 + 238 + DraggingOver _ -> 239 + True 240 + 241 + Dropped _ -> 242 + True
+19 -6
src/Applications/UI/List.elm
··· 82 82 83 83 Draggable env -> 84 84 [ DnD.listenToEnterLeave env idx 85 - , DnD.listenToDrop env idx 85 + , DnD.listenToDrop env 86 86 ] 87 87 |> List.concat 88 88 |> List.map Attributes.fromUnstyled ··· 103 103 [ -- Label 104 104 -------- 105 105 chunk 106 - [ T.flex_grow_1 ] 106 + [ C.pointer_events_none, T.flex_grow_1 ] 107 107 [ label ] 108 108 109 109 -- Actions 110 110 ---------- 111 111 , chunk 112 - [ T.flex, T.items_center ] 112 + [ T.flex 113 + , T.items_center 114 + 115 + -- 116 + , case variant of 117 + Normal -> 118 + "" 119 + 120 + Draggable env -> 121 + if DnD.isDragging env then 122 + C.pointer_events_none 123 + 124 + else 125 + "" 126 + ] 113 127 (List.append 114 128 (List.map actionView actions) 115 129 (case variant of ··· 173 187 if dragTarget then 174 188 List.append 175 189 itemBaseStyles 176 - [ Css.borderTop3 (px 1) solid (Color.toElmCssColor UI.Kit.colorKit.accent) 177 - , Css.touchAction Css.none 178 - ] 190 + [ Css.borderTop3 (px 1) solid (Color.toElmCssColor UI.Kit.colorKit.accent) ] 179 191 180 192 else 181 193 itemBaseStyles ··· 186 198 [ Css.borderBottom3 (px 1) solid (Color.toElmCssColor UI.Kit.colors.verySubtleBorder) 187 199 , Css.borderTop3 (px 1) solid Css.transparent 188 200 , Css.marginTop (px -1) 201 + , Css.touchAction Css.none 189 202 ]
+12 -6
src/Applications/UI/Tracks/Scene/List.elm
··· 329 329 330 330 -- 331 331 , if isTouchDevice then 332 - [ touchContextMenuEvent identifiedTrack 332 + [ touchContextMenuEvent identifiedTrack Nothing 333 333 , touchPlayEvent identifiedTrack 334 334 ] 335 335 ··· 382 382 383 383 -- 384 384 , if isTouchDevice then 385 - [ touchContextMenuEvent identifiedTrack 385 + [ touchContextMenuEvent identifiedTrack (Just dragEnv) 386 386 , touchPlayEvent identifiedTrack 387 387 , DnD.listenToStart dragEnv listIdx 388 388 ] ··· 407 407 408 408 -- 409 409 , DnD.listenToEnterLeave dragEnv listIdx 410 - , DnD.listenToDrop dragEnv listIdx 410 + , DnD.listenToDrop dragEnv 411 411 412 412 -- 413 413 , if DnD.isBeingDraggedOver listIdx dnd then ··· 462 462 Mouse.onClick (MarkAsSelected i.indexInList) 463 463 464 464 465 - touchContextMenuEvent : IdentifiedTrack -> Html.Attribute Msg 466 - touchContextMenuEvent ( i, _ ) = 465 + touchContextMenuEvent : IdentifiedTrack -> Maybe (DnD.Environment Int Msg) -> Html.Attribute Msg 466 + touchContextMenuEvent ( i, _ ) maybeDragEnv = 467 467 Html.Events.custom 468 468 "longtap" 469 469 (Decode.map2 470 470 (\x y -> 471 - { message = ShowTrackMenu i.indexInList { x = x, y = y } 471 + { message = 472 + case Maybe.andThen (.model >> DnD.modelTarget) maybeDragEnv of 473 + Just _ -> 474 + Bypass 475 + 476 + Nothing -> 477 + ShowTrackMenu i.indexInList { x = x, y = y } 472 478 , stopPropagation = True 473 479 , preventDefault = True 474 480 }
+31
src/Javascript/index.js
··· 225 225 }) 226 226 227 227 228 + // Simulate `pointerenter` and `pointerleave` event for touch devices 229 + let enteredElement 230 + 231 + document.body.addEventListener("touchmove", event => { 232 + let touch = event.touches[0] 233 + let node 234 + 235 + if (touch) { 236 + node = document.elementFromPoint(touch.clientX, touch.clientY) 237 + } 238 + 239 + if (node && node != enteredElement) { 240 + const eventOpts = { 241 + clientX: touch.clientX, 242 + clientY: touch.clientY, 243 + isPrimary: true, 244 + pointerType: "touch" 245 + } 246 + 247 + const eventClass = 248 + PointerEvent || MouseEvent 249 + 250 + enteredElement && enteredElement.dispatchEvent(new eventClass("pointerleave", eventOpts)) 251 + node.dispatchEvent(new eventClass("pointerenter", eventOpts)) 252 + 253 + enteredElement = node 254 + } 255 + }) 256 + 257 + 258 + 228 259 229 260 // Vertical Height 230 261 // ---------------