Skip to content

Commit 624a21a

Browse files
committed
Untest Android ListView implementation.
1 parent e93420f commit 624a21a

File tree

3 files changed

+67
-52
lines changed

3 files changed

+67
-52
lines changed

ReactFSharp.Android/Views/View.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ module private ViewProps =
203203
Func<unit, bool>(fun _ -> false)
204204

205205
let private defaultOnSystemUiVisibilityChange =
206-
Func<StatusBarVisibility, unit>(fun _ -> ())
206+
Func<StatusBarVisibility, unit>(ignore)
207207

208208
let private defaultOnTouch =
209209
Func<MotionEvent, bool>(fun _ -> false)
@@ -467,7 +467,7 @@ module View =
467467
|> Observable.observeOn Scheduler.mainLoopScheduler
468468
|> Observable.iter (view.RequestFocus >> ignore)
469469
|> Observable.subscribeWithError
470-
(fun _ -> ())
470+
ignore
471471
onError
472472
else Disposable.Empty
473473

ReactFSharp.Android/Widget/ListView.fs

Lines changed: 63 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ open Android.Widget
88
open FSharp.Control.Reactive
99
open ImmutableCollections
1010
open React
11+
open React.Android
1112
open React.Android.Views
1213
open System
1314
open System.Reactive.Disposables
@@ -17,7 +18,7 @@ open System.Runtime.CompilerServices
1718
type IListViewProps =
1819
inherit IViewGroupProps
1920

20-
type ListViewProps =
21+
type ListViewProps =
2122
{
2223
// View Props
2324
accessibilityLiveRegion: int
@@ -164,93 +165,107 @@ type ListViewComponentProps = {
164165
props: IListViewProps
165166
children: IImmutableMap<int, ReactElement>
166167
}
167-
(*
168+
168169
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
169170
module ListView =
170171
[<Sealed>]
171-
type ReactListAdapter (createNativeView: string (* view name *) -> obj (* initialProps *) -> IReactNativeView<View>,
172-
emptyViewProvider: unit -> View) =
172+
type ReactListAdapter (children: IObservable<IImmutableMap<int, ReactDOMNode>>,
173+
createNativeView: string (* view name *) -> obj (* initialProps *) -> IReactView<View>,
174+
onError: Exception -> unit) as this =
173175
inherit BaseAdapter()
174176

175177
let updateNativeView = ReactView.updateNativeView createNativeView
176178

177-
let reactViewCache = new ConditionalWeakTable<View, ReactView<View>>()
179+
let childrenSubject =
180+
new BehaviorSubject<IImmutableVector<int * ReactNativeDOMNode>>(ImmutableVector.empty ())
178181

179-
let onSetDomChildren = new Subject<seq<ReactDOMNode>>()
180-
let state = new BehaviorSubject<IImmutableVector<Option<ReactNativeDOMNode>>>(ImmutableVector.empty ())
182+
let childrenSubscription =
183+
childrenSubject
184+
|> Observable.iter (ignore >> this.NotifyDataSetChanged)
185+
|> Observable.subscribeWithError ignore onError
181186

182-
let stateSubscription =
183-
onSetDomChildren
184-
|> Observable.map (
185-
Seq.map (fun dom -> ReactDom.observe dom)
186-
>> Observable.combineLatestSeq
187-
>> Observable.map ImmutableVector.create
187+
let children =
188+
children
189+
|> Observable.flatmap (
190+
Seq.map (
191+
fun (key, dom) ->
192+
ReactDom.observe dom |> Observable.map (fun nativeDomNode -> (key, nativeDomNode))
188193
)
189-
|> Observable.flatmap (fun obs -> obs)
190-
|> Observable.subscribeObserver state
194+
>> Observable.combineLatestSeq
195+
>> Observable.map (
196+
Seq.filter (fun (key, node) -> node |> Option.isSome)
197+
>> Seq.map (fun (key, node) -> (key, node |> Option.get))
198+
>> ImmutableVector.create
199+
)
200+
)
201+
|> Observable.observeOn Scheduler.mainLoopScheduler
202+
|> Observable.subscribeObserver childrenSubject
203+
204+
let reactViewCache = new ConditionalWeakTable<View, IReactView<View>>()
205+
206+
override this.Count = childrenSubject.Value.Count
191207

192-
override this.Count = state.Value.Count
208+
override this.GetItem position = null
193209

194210
override this.GetItemId position =
195-
state.Value.Item position |> hash |> int64
211+
childrenSubject.Value.Item position |> (fun (key, _) -> key) |> int64
196212

197213
override this.GetView (position: int, convertView: View, parent: ViewGroup) =
198-
let nativeDomNode = state.Value.Item position
199-
200-
let reactView =
201-
match (reactViewCache.TryGetValue(convertView), nativeDomNode) with
202-
| ((true, reactView), Some domNode) -> reactView |> updateNativeView domNode |> Some
203-
| (_ , Some domNode) -> ReactViewNone |> updateNativeView domNode |> Some
204-
| _ -> None
205-
214+
let (key, nativeDomNode) = childrenSubject.Value.Item position
215+
216+
let reactView =
217+
match reactViewCache.TryGetValue(convertView) with
218+
| (true, reactView) -> updateNativeView (Some reactView) (Some nativeDomNode)
219+
| _ -> updateNativeView None (Some nativeDomNode)
220+
206221
match reactView with
207222
| Some reactView ->
208223
reactViewCache.Remove reactView.View |> ignore
209-
reactViewCache.Add (reactView.View, ReactNativeView reactView)
224+
reactViewCache.Add (reactView.View, reactView)
210225
reactView.View
211-
| _ when convertView.Id = -8 -> convertView
212-
| _ ->
213-
let emptyView = emptyViewProvider ()
214-
emptyView.Id <- -8
215-
emptyView
226+
| _ -> failwith "Something went wrong"
216227

217228
override this.HasStableIds = true
218229

219-
member this.SetDomChildren children =
220-
children
221-
|> ImmutableMap.values
222-
|> onSetDomChildren.OnNext
223-
224230
interface IListAdapter with
225231
member this.AreAllItemsEnabled () = true
226232
member this.IsEnabled index = true
227233

234+
interface IDisposable with
235+
member this.Dispose () =
236+
childrenSubscription.Dispose ()
237+
228238
let private name = typeof<ListView>.FullName
229239

230240
let private listViewAdapterCache =
231-
new ConditionalWeakTable<ListView, IImmutableMap<string, ReactView<View>>>()
241+
new ConditionalWeakTable<ListView, IImmutableMap<string, IReactView<View>>>()
232242

233243
let setProps (onError: Exception -> unit) (view: View) (props: IListViewProps) =
234244
let view = (view :?> ListView)
235245
ViewGroup.setProps onError view props
236246

237247
let private createView (context: Context): AndroidViewCreator =
238-
let viewGroupProvider () = new ListView (context) :> View
248+
let createView
249+
(onError: Exception -> unit)
250+
(createView: string (* view name *) -> obj (* initialProps *) -> IReactView<View>) =
251+
252+
let view = new ListView (context)
253+
let setChildrenSubject = new Subject<IImmutableMap<int, ReactDOMNode>>()
254+
255+
let adapter = new ReactListAdapter (setChildrenSubject, createView, onError)
256+
view.Adapter <- adapter
239257

240-
let createView onError updateWith initialProps =
241-
let onDispose () = ()
242-
let setChildren view children =
243-
Disposable.Empty
244-
245-
ReactView.createView name viewGroupProvider (setProps onError) setChildren onDispose initialProps
258+
let onDispose () =
259+
setChildrenSubject.OnCompleted()
260+
()
261+
262+
ReactView.createView name (view :> View) (setProps onError view) setChildrenSubject.OnNext onDispose
246263

247264
createView
248265

249266
let viewProvider = (name, createView)
250-
251-
let internal reactComponent = ReactComponent.makeLazy (fun (props: ListViewComponentProps) -> ReactNativeElement {
267+
let internal reactComponent (props: ListViewComponentProps) = ReactNativeElement {
252268
Name = name
253269
Props = props.props
254270
Children = props.children
255-
})
256-
*)
271+
}

ReactFSharp/ReactView.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ module ReactView =
134134
(setProps: 'view -> 'props -> IDisposable)
135135
(initialProps: obj) =
136136
let view = viewProvider ()
137-
createView name view (setProps view) (fun _ -> ()) (fun () -> ()) initialProps
137+
createView name view (setProps view) ignore ignore initialProps
138138

139139
let createViewImmediatelyRenderingAllChildren<'view, 'props when 'view :> IDisposable>
140140
(scheduler: IScheduler)
@@ -204,7 +204,7 @@ module ReactView =
204204
removeAllViews view
205205
addViews view childViews
206206
)
207-
|> Observable.subscribeWithError (fun _ -> ()) onError
207+
|> Observable.subscribeWithError ignore onError
208208

209209
let onDispose () =
210210
setChildrenSubject.OnCompleted ()

0 commit comments

Comments
 (0)