@@ -19,9 +19,10 @@ import Code.DefinitionSummaryTooltip as DefinitionSummaryTooltip
19
19
import Code.FullyQualifiedName exposing (FQN )
20
20
import Code.Hash as Hash
21
21
import Code.HashQualified as HQ
22
- import Code.Workspace.WorkspaceItem as WorkspaceItem exposing (Item , WorkspaceItem , WorkspaceItemViewState )
22
+ import Code.Workspace.WorkspaceItem as WorkspaceItem exposing (ItemWithReferences , WorkspaceItem , WorkspaceItemViewState )
23
23
import Code.Workspace.WorkspaceItems as WorkspaceItems exposing (WorkspaceItems )
24
24
import Code.Workspace.WorkspaceMinimap as WorkspaceMinimap
25
+ import Dict exposing (Dict )
25
26
import Html exposing (Html , article , div , section )
26
27
import Html.Attributes exposing (class , id )
27
28
import Http
@@ -44,6 +45,7 @@ type alias Model =
44
45
, keyboardShortcut : KeyboardShortcut . Model
45
46
, workspaceItemViewState : WorkspaceItemViewState
46
47
, isMinimapToggled : Bool
48
+ , referenceMap : Dict String ( List Reference ) -- Map of refRequest to list refResponse, to handle multiple-responses case for one request
47
49
}
48
50
49
51
@@ -55,6 +57,7 @@ init config mRef =
55
57
, keyboardShortcut = KeyboardShortcut . init config. operatingSystem
56
58
, workspaceItemViewState = WorkspaceItem . viewState
57
59
, isMinimapToggled = False
60
+ , referenceMap = Dict . empty
58
61
}
59
62
in
60
63
case mRef of
@@ -71,7 +74,7 @@ init config mRef =
71
74
72
75
type Msg
73
76
= NoOp
74
- | FetchItemFinished Reference ( Result Http . Error Item )
77
+ | FetchItemFinished Reference ( Result Http . Error ( List ItemWithReferences ) )
75
78
| IsDocCropped Reference ( Result Dom . Error Bool )
76
79
| Keydown KeyboardEvent
77
80
| KeyboardShortcutMsg KeyboardShortcut . Msg
@@ -91,62 +94,103 @@ type OutMsg
91
94
| ChangePerspectiveToSubNamespace ( Maybe Reference ) FQN
92
95
93
96
97
+ updateOneItem :
98
+ Reference
99
+ -> ItemWithReferences
100
+ -> ( ( WorkspaceItems , Dict String ( List Reference ) ) , Cmd Msg )
101
+ -> ( ( WorkspaceItems , Dict String ( List Reference ) ) , Cmd Msg )
102
+ updateOneItem refRequest { item, refResponse } ( ( workspaceItems, referenceMap ) , aggCmd ) =
103
+ let
104
+ refReqeustKey =
105
+ Reference . toString refRequest
106
+
107
+ refResponseList =
108
+ referenceMap
109
+ |> Dict . get refReqeustKey
110
+ |> Maybe . withDefault []
111
+ |> ( \ list -> refResponse :: list)
112
+
113
+ updatedReferenceMap =
114
+ referenceMap
115
+ |> Dict . insert refReqeustKey refResponseList
116
+
117
+ cmd =
118
+ -- Docs items are always shown in full and never cropped
119
+ if WorkspaceItem . isDocItem item then
120
+ Cmd . none
121
+
122
+ else
123
+ isDocCropped refResponse
124
+
125
+ isDupe wi =
126
+ let
127
+ ref_ =
128
+ WorkspaceItem . reference wi
129
+
130
+ refEqs =
131
+ Reference . equals refResponse ref_
132
+
133
+ hashEqs =
134
+ wi
135
+ |> WorkspaceItem . hash
136
+ |> Maybe . map ( Hash . equals ( WorkspaceItem . itemHash item))
137
+ |> Maybe . withDefault False
138
+ in
139
+ ( Reference . same refResponse ref_ && not refEqs) || ( hashEqs && not refEqs)
140
+
141
+ -- In some cases (like using the back button between
142
+ -- perspectives) we try and fetch the same item twice, not
143
+ -- knowing we've fetched it before since one was by hash
144
+ -- and the other by name. If found to already be fetched,
145
+ -- we favor the newly fetched item and discard the old
146
+ deduped =
147
+ workspaceItems
148
+ |> WorkspaceItems . find isDupe
149
+ |> Maybe . map WorkspaceItem . reference
150
+ |> Maybe . map ( WorkspaceItems . remove workspaceItems)
151
+ |> Maybe . withDefault workspaceItems
152
+
153
+ newWorkspaceItem =
154
+ WorkspaceItem . fromItem refResponse item
155
+ in
156
+ ( ( WorkspaceItems . replaceOrPrependWithFocus deduped refResponse newWorkspaceItem
157
+ , updatedReferenceMap
158
+ )
159
+ , Cmd . batch [ aggCmd, cmd ]
160
+ )
161
+
162
+
94
163
update : Config -> ViewMode -> Msg -> Model -> ( Model , Cmd Msg , OutMsg )
95
- update config viewMode msg ( { workspaceItems } as model) =
164
+ update config viewMode msg ( { workspaceItems, referenceMap } as model) =
96
165
case msg of
97
166
NoOp ->
98
167
( model, Cmd . none, None )
99
168
100
- FetchItemFinished ref itemResult ->
169
+ FetchItemFinished refRequest itemResult ->
101
170
case itemResult of
102
171
Err e ->
103
- ( { model | workspaceItems = WorkspaceItems . replace workspaceItems ref ( WorkspaceItem . Failure ref e) }
172
+ ( { model | workspaceItems = WorkspaceItems . replace workspaceItems refRequest ( WorkspaceItem . Failure refRequest e) }
104
173
, Cmd . none
105
174
, None
106
175
)
107
176
108
- Ok i ->
177
+ Ok items ->
109
178
let
110
- cmd =
111
- -- Docs items are always shown in full and never cropped
112
- if WorkspaceItem . isDocItem i then
113
- Cmd . none
179
+ -- remove loading element (with `ref` used for request)
180
+ loadingRemoved =
181
+ WorkspaceItems . remove workspaceItems refRequest
114
182
115
- else
116
- isDocCropped ref
117
-
118
- isDupe wi =
119
- let
120
- ref_ =
121
- WorkspaceItem . reference wi
122
-
123
- refEqs =
124
- Reference . equals ref ref_
125
-
126
- hashEqs =
127
- wi
128
- |> WorkspaceItem . hash
129
- |> Maybe . map ( Hash . equals ( WorkspaceItem . itemHash i))
130
- |> Maybe . withDefault False
131
- in
132
- ( Reference . same ref ref_ && not refEqs) || ( hashEqs && not refEqs)
133
-
134
- -- In some cases (like using the back button between
135
- -- perspectives) we try and fetch the same item twice, not
136
- -- knowing we've fetched it before since one was by hash
137
- -- and the other by name. If found to already be fetched,
138
- -- we favor the newly fetched item and discard the old
139
- deduped =
140
- workspaceItems
141
- |> WorkspaceItems . find isDupe
142
- |> Maybe . map WorkspaceItem . reference
143
- |> Maybe . map ( WorkspaceItems . remove workspaceItems)
144
- |> Maybe . withDefault workspaceItems
145
-
146
- nextWorkspaceItems =
147
- WorkspaceItems . replace deduped ref ( WorkspaceItem . fromItem ref i)
183
+ -- update items with fetched result
184
+ ( ( nextWorkspaceItems, nextReferenceMap ) , cmd ) =
185
+ List . foldl ( updateOneItem refRequest) ( ( loadingRemoved, referenceMap ) , Cmd . none ) items
148
186
in
149
- ( { model | workspaceItems = nextWorkspaceItems }, cmd, None )
187
+ ( { model
188
+ | workspaceItems = nextWorkspaceItems
189
+ , referenceMap = nextReferenceMap
190
+ }
191
+ , cmd
192
+ , None
193
+ )
150
194
151
195
IsDocCropped ref res ->
152
196
let
@@ -346,7 +390,7 @@ update config viewMode msg ({ workspaceItems } as model) =
346
390
347
391
348
392
type alias WithWorkspaceItems m =
349
- { m | workspaceItems : WorkspaceItems }
393
+ { m | workspaceItems : WorkspaceItems , referenceMap : Dict String ( List Reference ) }
350
394
351
395
352
396
replaceWorkspaceItemReferencesWithHashOnly : Model -> Model
@@ -381,17 +425,24 @@ openReference config model relativeToRef ref =
381
425
382
426
383
427
openItem : Config -> WithWorkspaceItems m -> Maybe Reference -> Reference -> ( WithWorkspaceItems m , Cmd Msg )
384
- openItem config ( { workspaceItems } as model) relativeToRef ref =
428
+ openItem config ( { workspaceItems, referenceMap } as model) relativeToRef ref =
385
429
-- We don't want to refetch or replace any already open definitions, but we
386
430
-- do want to focus and scroll to it (unless its already currently focused)
387
- if WorkspaceItems . member workspaceItems ref then
388
- if not ( WorkspaceItems . isFocused workspaceItems ref) then
431
+ let
432
+ convertedRef =
433
+ referenceMap
434
+ |> Dict . get ( Reference . toString ref)
435
+ |> Maybe . andThen List . head
436
+ |> Maybe . withDefault ref
437
+ in
438
+ if WorkspaceItems . member workspaceItems convertedRef then
439
+ if not ( WorkspaceItems . isFocused workspaceItems convertedRef) then
389
440
let
390
441
nextWorkspaceItems =
391
- WorkspaceItems . focusOn workspaceItems ref
442
+ WorkspaceItems . focusOn workspaceItems convertedRef
392
443
in
393
444
( { model | workspaceItems = nextWorkspaceItems }
394
- , scrollToDefinition ref
445
+ , scrollToDefinition convertedRef
395
446
)
396
447
397
448
else
@@ -400,7 +451,7 @@ openItem config ({ workspaceItems } as model) relativeToRef ref =
400
451
else
401
452
let
402
453
toInsert =
403
- WorkspaceItem . Loading ref
454
+ WorkspaceItem . Loading convertedRef
404
455
405
456
nextWorkspaceItems =
406
457
case relativeToRef of
@@ -411,7 +462,10 @@ openItem config ({ workspaceItems } as model) relativeToRef ref =
411
462
WorkspaceItems . insertWithFocusBefore workspaceItems r toInsert
412
463
in
413
464
( { model | workspaceItems = nextWorkspaceItems }
414
- , Cmd . batch [ HttpApi . perform config. api ( fetchDefinition config ref) , scrollToDefinition ref ]
465
+ , Cmd . batch
466
+ [ HttpApi . perform config. api ( fetchDefinition config convertedRef)
467
+ , scrollToDefinition convertedRef
468
+ ]
415
469
)
416
470
417
471
@@ -531,7 +585,7 @@ handleKeyboardShortcut viewMode model shortcut =
531
585
-- EFFECTS
532
586
533
587
534
- fetchDefinition : Config -> Reference -> ApiRequest Item Msg
588
+ fetchDefinition : Config -> Reference -> ApiRequest ( List ItemWithReferences ) Msg
535
589
fetchDefinition config ref =
536
590
let
537
591
endpoint =
@@ -542,7 +596,7 @@ fetchDefinition config ref =
542
596
in
543
597
endpoint
544
598
|> config. toApiEndpoint
545
- |> HttpApi . toRequest ( WorkspaceItem . decodeItem ref) ( FetchItemFinished ref)
599
+ |> HttpApi . toRequest ( WorkspaceItem . decodeList ref) ( FetchItemFinished ref)
546
600
547
601
548
602
isDocCropped : Reference -> Cmd Msg
0 commit comments