following users page

This commit is contained in:
wgh19
2024-05-13 20:01:23 +08:00
parent 56917f22c1
commit 13ef786280
5 changed files with 121 additions and 5 deletions

View File

@@ -89,8 +89,18 @@ abstract class MultiPageLoadingState<T extends StatefulWidget, S extends Object>
}); });
} }
@override void reset() {
void initState() { setState(() {
_isFirstLoading = true;
_isLoading = false;
_data = null;
_error = null;
_page = 1;
});
firstLoad();
}
void firstLoad() {
loadData(_page).then((value) { loadData(_page).then((value) {
if(value.success) { if(value.success) {
_page++; _page++;
@@ -105,6 +115,11 @@ abstract class MultiPageLoadingState<T extends StatefulWidget, S extends Object>
}); });
} }
}); });
}
@override
void initState() {
firstLoad();
super.initState(); super.initState();
} }

View File

@@ -340,5 +340,5 @@ class UserPreview {
account = json['account'], account = json['account'],
avatar = json['profile_image_urls']['medium'], avatar = json['profile_image_urls']['medium'],
isFollowed = json['is_followed'], isFollowed = json['is_followed'],
isBlocking = json['is_access_blocking_user']; isBlocking = json['is_access_blocking_user'] ?? false;
} }

View File

@@ -324,4 +324,16 @@ class Network {
return Res.error(res.errorMessage); return Res.error(res.errorMessage);
} }
} }
Future<Res<List<UserPreview>>> getFollowing(String uid, String type, [String? nextUrl]) async {
var path = nextUrl ?? "/v1/user/following?filter=for_android&user_id=$uid&restrict=$type";
var res = await apiGet(path);
if (res.success) {
return Res(
(res.data["user_previews"] as List).map((e) => UserPreview.fromJson(e["user"])).toList(),
subData: res.data["next_url"]);
} else {
return Res.error(res.errorMessage);
}
}
} }

View File

@@ -0,0 +1,82 @@
import 'package:fluent_ui/fluent_ui.dart';
import 'package:pixes/appdata.dart';
import 'package:pixes/components/loading.dart';
import 'package:pixes/components/segmented_button.dart';
import 'package:pixes/foundation/app.dart';
import 'package:pixes/network/network.dart';
import 'package:pixes/utils/translation.dart';
import '../components/grid.dart';
import '../components/user_preview.dart';
class FollowingUsersPage extends StatefulWidget {
const FollowingUsersPage(this.uid, {super.key});
final String uid;
@override
State<FollowingUsersPage> createState() => _FollowingUsersPageState();
}
class _FollowingUsersPageState extends MultiPageLoadingState<FollowingUsersPage, UserPreview> {
String type = "public";
@override
Widget buildContent(BuildContext context, final List<UserPreview> data) {
return CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Row(
children: [
Text("Following".tl,
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),)
.paddingVertical(12).paddingLeft(16),
const Spacer(),
if(widget.uid == appdata.account?.user.id)
SegmentedButton(
value: type,
options: [
SegmentedButtonOption("public", "Public".tl),
SegmentedButtonOption("private", "Private".tl),
],
onPressed: (s) {
type = s;
reset();
},
),
const SizedBox(width: 16,)
],
),
),
SliverGridViewWithFixedItemHeight(
delegate: SliverChildBuilderDelegate(
(context, index) {
if(index == data.length - 1){
nextPage();
}
return UserPreviewWidget(data[index]);
},
childCount: data.length
),
maxCrossAxisExtent: 520,
itemHeight: 114,
).sliverPaddingHorizontal(8)
],
);
}
String? nextUrl;
@override
Future<Res<List<UserPreview>>> loadData(page) async{
if(nextUrl == "end") {
return Res.error("No more data");
}
var res = await Network().getFollowing(widget.uid, type, nextUrl);
if(!res.error) {
nextUrl = res.subData;
nextUrl ??= "end";
}
return res;
}
}

View File

@@ -1,10 +1,12 @@
import 'package:fluent_ui/fluent_ui.dart'; import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:pixes/components/loading.dart'; import 'package:pixes/components/loading.dart';
import 'package:pixes/components/md.dart'; import 'package:pixes/components/md.dart';
import 'package:pixes/foundation/app.dart'; import 'package:pixes/foundation/app.dart';
import 'package:pixes/foundation/image_provider.dart'; import 'package:pixes/foundation/image_provider.dart';
import 'package:pixes/network/network.dart'; import 'package:pixes/network/network.dart';
import 'package:pixes/pages/following_users_page.dart';
import 'package:pixes/utils/translation.dart'; import 'package:pixes/utils/translation.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
@@ -53,13 +55,18 @@ class _UserInfoPageState extends LoadingState<UserInfoPage, UserDetails> {
), ),
),), ),),
const SizedBox(height: 8), const SizedBox(height: 8),
Text(data!.name, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500)), Text(data!.name, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 4), const SizedBox(height: 4),
Text.rich( Text.rich(
TextSpan( TextSpan(
children: [ children: [
TextSpan(text: 'Follows: '.tl), TextSpan(text: 'Follows: '.tl),
TextSpan(text: '${data!.totalFollowUsers}', style: const TextStyle(fontWeight: FontWeight.w500)), TextSpan(
text: '${data!.totalFollowUsers}',
recognizer: TapGestureRecognizer()
..onTap = (() => context.to(() => FollowingUsersPage(widget.id))),
style: TextStyle(fontWeight: FontWeight.bold, color: FluentTheme.of(context).accentColor)
),
], ],
), ),
style: const TextStyle(fontSize: 14), style: const TextStyle(fontSize: 14),