Skip to content

Commit

Permalink
🔀 Merge pull request #29 from Fedodo/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
LNA-DEV authored Jul 2, 2023
2 parents b0ed8cf + d4310df commit b7f32a9
Show file tree
Hide file tree
Showing 7 changed files with 377 additions and 1 deletion.
49 changes: 49 additions & 0 deletions lib/widgets/profile/components/profile_description.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:url_launcher/url_launcher.dart';

class ProfileDescription extends StatelessWidget {
const ProfileDescription({
Key? key,
this.htmlData,
}) : super(key: key);

final String? htmlData;

@override
Widget build(BuildContext context) {
return Html(
data: htmlData ?? "",
style: {
"p": Style(fontSize: FontSize(16)),
"a": Style(
fontSize: FontSize(16),
textDecoration: TextDecoration.none,
),
},
extensions: [
TagExtension(
tagsToExtend: {"a"},
builder: (extensionContext) {
return InkWell(
onTap: () => {
launchUrl(
Uri.parse(
extensionContext.element!.attributes["href"]!,
),
),
},
child: Text(
extensionContext.node.text!,
style: const TextStyle(
color: Colors.blue,
fontSize: 16,
),
),
);
},
),
],
);
}
}
120 changes: 120 additions & 0 deletions lib/widgets/profile/components/profile_name_row.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import 'package:activitypub/activitypub.dart';
import 'package:fedodo_general/widgets/profile/enums/profile_button_state.dart';
import 'package:flutter/material.dart';

class ProfileNameRow extends StatefulWidget {
const ProfileNameRow({
Key? key,
required this.preferredUsername,
required this.userId,
required this.name,
required this.profileButtonInitialState,
}) : super(key: key);

final String preferredUsername;
final String userId;
final String? name;
final Future<ProfileButtonState> profileButtonInitialState;

@override
State<ProfileNameRow> createState() => _ProfileNameRowState();
}

class _ProfileNameRowState extends State<ProfileNameRow> {
late Future<ProfileButtonState> profileButtonState;

@override
Widget build(BuildContext context) {

profileButtonState = widget.profileButtonInitialState;

String fullUserName =
"@${widget.preferredUsername}@${Uri.parse(widget.userId).authority}";

return Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.name ?? "",
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
Text(
fullUserName,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.white54,
),
),
],
),
Column(
children: [
FutureBuilder<ProfileButtonState>(
future: profileButtonState,
builder: (BuildContext context,
AsyncSnapshot<ProfileButtonState> snapshot) {
Widget child;
if (snapshot.hasData) {
switch (snapshot.data!) {
case ProfileButtonState.ownProfile:
{
child = ElevatedButton(
onPressed: () {},
child: const Text("Edit Profile"),
);
}
break;
case ProfileButtonState.subscribed:
{
child = ElevatedButton(
onPressed: () {},
child: const Text("Unfollow"),
);
}
break;
case ProfileButtonState.notSubscribed:
child = ElevatedButton(
onPressed: () async {
ActivityAPI activityApi = ActivityAPI();
activityApi.follow(Uri.parse(widget.userId));

setState(() {
profileButtonState = Future.sync(
() => ProfileButtonState.subscribed);
});
},
child: const Text("Follow"),
);
break;
}
} else if (snapshot.hasError) {
child = const Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
);
} else {
child = ElevatedButton(
onPressed: () {},
child: const Text("Loading"),
);
}
return child;
},
),
],
),
],
),
);
}
}
91 changes: 91 additions & 0 deletions lib/widgets/profile/components/profile_picture_detail.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import 'package:fedodo_general/Extensions/string_extensions.dart';
import 'package:flutter/material.dart';

class ProfilePictureDetail extends StatefulWidget {
const ProfilePictureDetail({
Key? key,
required this.followersCount,
required this.followingCount,
required this.postsCount,
this.iconUrl,
}) : super(key: key);

final int followersCount;
final int followingCount;
final int postsCount;
final String? iconUrl;

@override
State<ProfilePictureDetail> createState() => _ProfilePictureDetailState();
}

class _ProfilePictureDetailState extends State<ProfilePictureDetail> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.network(
width: 80,
height: 80,
widget.iconUrl != null
? widget.iconUrl!.asFedodoProxyString()
: "https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png?20170328184010"
.asFedodoProxyString(),
),
),
],
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text(
widget.postsCount.toString(),
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const Text("Posts"),
],
),
Column(
children: [
Text(
widget.followingCount.toString(),
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const Text("Following"),
],
),
Column(
children: [
Text(
widget.followersCount.toString(),
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const Text("Followers"),
],
),
],
),
),
],
),
);
}
}
5 changes: 5 additions & 0 deletions lib/widgets/profile/enums/profile_button_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum ProfileButtonState {
ownProfile,
subscribed,
notSubscribed
}
110 changes: 110 additions & 0 deletions lib/widgets/profile/profile_head.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import 'package:activitypub/APIs/followers_api.dart';
import 'package:activitypub/APIs/followings_api.dart';
import 'package:activitypub/APIs/outbox_api.dart';
import 'package:activitypub/Models/actor.dart';
import 'package:activitypub/Models/ordered_paged_collection.dart';
import 'package:fedodo_general/Globals/general.dart';
import 'package:flutter/material.dart';
import 'components/profile_description.dart';
import 'components/profile_name_row.dart';
import 'components/profile_picture_detail.dart';
import 'enums/profile_button_state.dart';

class ProfileHead extends StatefulWidget {
const ProfileHead({
super.key,
required this.actor,
});

final Actor actor;

@override
State<ProfileHead> createState() => _ProfileHeadState();
}

class _ProfileHeadState extends State<ProfileHead> {
int? postCount;
int? followingCount;
int? followersCount;

@override
Widget build(BuildContext context) {
if (followersCount == null && widget.actor.followers != null) {
setFollowers(widget.actor.followers!);
}
if (followingCount == null && widget.actor.following != null) {
setFollowings(widget.actor.following!);
}
if (postCount == null) {
setPosts(widget.actor.outbox!);
}

return Column(
children: [
ProfilePictureDetail(
followersCount: followersCount ?? 0,
followingCount: followingCount ?? 0,
iconUrl: widget.actor.icon?.url,
postsCount: postCount ?? 0,
),
ProfileNameRow(
profileButtonInitialState: getProfileButtonState(widget.actor),
preferredUsername: widget.actor.preferredUsername!,
userId: widget.actor.id!,
name: widget.actor.name,
),
ProfileDescription(
htmlData: widget.actor.summary ?? "",
),
],
);
}

Future<ProfileButtonState> getProfileButtonState(Actor actor) async {
if (actor.id == null) General.logger.w("ActorId was null!");

if (actor.id == General.fullActorId) {
return ProfileButtonState.ownProfile;
} else {
FollowingsAPI followingsAPI = FollowingsAPI();
var isFollowed =
await followingsAPI.isFollowed(actor.id!, General.fullActorId);
if (isFollowed) {
return ProfileButtonState.subscribed;
} else {
return ProfileButtonState.notSubscribed;
}
}
}

void setFollowers(String followersString) async {
FollowersAPI followersApi = FollowersAPI();
OrderedPagedCollection followersCollection =
await followersApi.getFollowers(followersString);

setState(() {
followersCount = followersCollection.totalItems;
});
}

void setFollowings(String followingsString) async {
FollowingsAPI followersProvider = FollowingsAPI();
OrderedPagedCollection followingCollection =
await followersProvider.getFollowings(followingsString);

setState(() {
followingCount = followingCollection.totalItems;
});
}

void setPosts(String outboxUrl) async {
OutboxAPI outboxProvider = OutboxAPI();

OrderedPagedCollection orderedPagedCollection =
await outboxProvider.getFirstPage(outboxUrl);

setState(() {
postCount = orderedPagedCollection.totalItems;
});
}
}
File renamed without changes.
3 changes: 2 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: fedodo_general
description: A flutter package which contains general components of the Fedodo-UIs.
version: 1.6.5
version: 1.7.0
homepage: https://fedodo.org

environment:
Expand All @@ -20,6 +20,7 @@ dependencies:
jwt_decoder: ^2.0.1
easy_sidemenu: ^0.4.1+1
logger: ^1.4.0
flutter_html: ^3.0.0-beta.1

dev_dependencies:
flutter_test:
Expand Down

0 comments on commit b7f32a9

Please sign in to comment.