@@ -27,6 +27,7 @@ struct InfiniteScrollSampleView: View {
2727 @StateObject private var viewModel : InfiniteScrollSampleViewModel
2828 @State private var showAlert = false
2929 @State private var alertInfo : AlertInfo ?
30+ @State private var scrollToTop = false
3031
3132 // MARK: - デバッグ用
3233 @State private var isDebugMenuExpanded = false
@@ -41,100 +42,106 @@ struct InfiniteScrollSampleView: View {
4142 VStack {
4243 debugView
4344
44- ZStack {
45- RagiSmoothList (
46- data: $employees,
47- listConfiguration: . init(
48- hasSeparator: true ,
49- separatorInsets: EdgeInsets ( ) ,
50- separatorColor: . red,
51- canRowDelete: true
52- ) ,
53- sectionContent: { section in
54- makeSection ( section: section)
55- } ,
56- cellContent: { employee in
57- makeEmployeeCell ( employee: employee)
58- } ,
59- onLoadMore: {
60- Task {
61- await viewModel. loadMore (
62- forceFirstLoadError: forceFirstLoadError,
63- forceMoreLoadError: forceMoreLoadError
64- )
65- }
66- } ,
67- onRefresh: {
68- Task {
69- await viewModel. refresh ( forceFirstLoadError: forceFirstLoadError)
70- }
71- } ,
72- onDeleting: { employee in
73- } ,
74- onDeleted: { employee in
75- viewModel. delete ( target: employee)
76- alertInfo = . init( message: " [removed] id: \( employee. id) " )
77- showAlert = true
78- }
79- )
80- . alert ( isPresented: $showAlert) {
81- if let alertInfo {
82- return Alert ( title: Text ( alertInfo. message) )
45+ Button {
46+ scrollToTop = true
47+ } label: {
48+ Text ( " \( Image ( systemName: " arrow.up.circle " ) ) scroll to top " )
49+ }
50+
51+
52+ RagiSmoothList (
53+ data: $employees,
54+ listConfiguration: . init(
55+ hasSeparator: true ,
56+ separatorInsets: EdgeInsets ( ) ,
57+ separatorColor: . red,
58+ canRowDelete: true
59+ ) ,
60+ sectionContent: { section in
61+ makeSection ( section: section)
62+ } ,
63+ cellContent: { employee in
64+ makeEmployeeCell ( employee: employee)
65+ } ,
66+ onLoadMore: {
67+ Task {
68+ await viewModel. loadMore (
69+ forceFirstLoadError: forceFirstLoadError,
70+ forceMoreLoadError: forceMoreLoadError
71+ )
8372 }
84- assertionFailure ( )
85- return Alert ( title: Text ( " " ) )
86- }
87- . overlay (
88- moreLoadingState
89- . opacity ( isLoading ? 1.0 : 0.0 ) ,
90- alignment: . bottom
91- )
92- . overlay (
93- // MEMO: タップを貫通させたい
94- firstLoadErrorState
95- . opacity ( isFirstLoadFailed ? 1.0 : 0.0 ) ,
96- alignment: . center
97- )
98- . overlay (
99- moreLoadErrorState
100- . opacity ( isMoreLoadFailed ? 1.0 : 0.0 )
101- . padding ( ) ,
102- alignment: . bottom
103- )
104- . onAppear {
73+ } ,
74+ onRefresh: {
10575 Task {
106- await viewModel. loadMore ( )
76+ await viewModel. refresh ( forceFirstLoadError : forceFirstLoadError )
10777 }
78+ } ,
79+ onDeleting: { employee in
80+ } ,
81+ onDeleted: { employee in
82+ viewModel. delete ( target: employee)
83+ alertInfo = . init( message: " [removed] id: \( employee. id) " )
84+ showAlert = true
10885 }
109- . onChange ( of: viewModel. state) { state in
110- switch state {
111- case . initial:
112- isLoading = false
113- isFirstLoadFailed = false
114- isMoreLoadFailed = false
115- case . loading:
116- isLoading = true
117- isFirstLoadFailed = false
118- isMoreLoadFailed = false
119- case . loaded( let employees) :
120- isLoading = false
121- isFirstLoadFailed = false
122- isMoreLoadFailed = false
123- self . employees = employees
124- case . unchanged:
125- isLoading = false
126- isFirstLoadFailed = false
127- isMoreLoadFailed = false
128- case . firstLoadFailed:
129- isLoading = false
130- isFirstLoadFailed = true
131- isMoreLoadFailed = false
132- self . employees = [ ]
133- case . moreLoadFailed:
134- isLoading = false
135- isFirstLoadFailed = false
136- isMoreLoadFailed = true
137- }
86+ )
87+ . scrollToTop ( $scrollToTop)
88+ . alert ( isPresented: $showAlert) {
89+ if let alertInfo {
90+ return Alert ( title: Text ( alertInfo. message) )
91+ }
92+ assertionFailure ( )
93+ return Alert ( title: Text ( " " ) )
94+ }
95+ . overlay (
96+ moreLoadingState
97+ . opacity ( isLoading ? 1.0 : 0.0 ) ,
98+ alignment: . bottom
99+ )
100+ . overlay (
101+ // MEMO: タップを貫通させたい
102+ firstLoadErrorState
103+ . opacity ( isFirstLoadFailed ? 1.0 : 0.0 ) ,
104+ alignment: . center
105+ )
106+ . overlay (
107+ moreLoadErrorState
108+ . opacity ( isMoreLoadFailed ? 1.0 : 0.0 )
109+ . padding ( ) ,
110+ alignment: . bottom
111+ )
112+ . onAppear {
113+ Task {
114+ await viewModel. loadMore ( )
115+ }
116+ }
117+ . onChange ( of: viewModel. state) { state in
118+ switch state {
119+ case . initial:
120+ isLoading = false
121+ isFirstLoadFailed = false
122+ isMoreLoadFailed = false
123+ case . loading:
124+ isLoading = true
125+ isFirstLoadFailed = false
126+ isMoreLoadFailed = false
127+ case . loaded( let employees) :
128+ isLoading = false
129+ isFirstLoadFailed = false
130+ isMoreLoadFailed = false
131+ self . employees = employees
132+ case . unchanged:
133+ isLoading = false
134+ isFirstLoadFailed = false
135+ isMoreLoadFailed = false
136+ case . firstLoadFailed:
137+ isLoading = false
138+ isFirstLoadFailed = true
139+ isMoreLoadFailed = false
140+ self . employees = [ ]
141+ case . moreLoadFailed:
142+ isLoading = false
143+ isFirstLoadFailed = false
144+ isMoreLoadFailed = true
138145 }
139146 }
140147 }
0 commit comments