Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into feature/delete-m…
Browse files Browse the repository at this point in the history
…edia
  • Loading branch information
micahmo committed Jul 12, 2024
2 parents 41b3e30 + 108605b commit da9b900
Show file tree
Hide file tree
Showing 43 changed files with 3,981 additions and 2,600 deletions.
21 changes: 21 additions & 0 deletions lib/account/models/user_label.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,29 @@ class UserLabel {
}
}

static Future<List<UserLabel>> fetchAllUserLabels() async {
try {
final userLabelRows = await database.select(database.userLabels).get();
return userLabelRows
.map((userLabel) => UserLabel(
id: userLabel.id.toString(),
username: userLabel.username,
label: userLabel.label,
))
.toList();
} catch (e) {
debugPrint(e.toString());
return [];
}
}

/// Generates a username string that can be used to uniquely identify entries in the UserLabels table
static String usernameFromParts(String username, String actorId) {
return '$username@${fetchInstanceNameFromUrl(actorId)}';
}

/// Splits a username generated by [usernameFromParts] back into name and instance
static ({String username, String instance}) partsFromUsername(String username) {
return (username: username.split('@')[0], instance: username.split('@')[1]);
}
}
17 changes: 13 additions & 4 deletions lib/comment/cubit/create_comment_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,27 @@ class CreateCommentCubit extends Cubit<CreateCommentState> {
emit(state.copyWith(status: CreateCommentStatus.initial, message: null));
}

Future<void> uploadImage(String imageFile) async {
Future<void> uploadImages(List<String> imageFiles) async {
Account? account = await fetchActiveProfileAccount();
if (account == null) return;

PictrsApi pictrs = PictrsApi(account.instance!);
List<String> urls = [];

emit(state.copyWith(status: CreateCommentStatus.imageUploadInProgress));

try {
PictrsUpload result = await pictrs.upload(filePath: imageFile, auth: account.jwt);
String url = "https://${account.instance!}/pictrs/image/${result.files[0].file}";
for (String imageFile in imageFiles) {
PictrsUpload result = await pictrs.upload(filePath: imageFile, auth: account.jwt);
String url = "https://${account.instance!}/pictrs/image/${result.files[0].file}";

urls.add(url);

// Add a delay between each upload to avoid possible rate limiting
await Future.wait(urls.map((url) => Future.delayed(const Duration(milliseconds: 500))));
}

emit(state.copyWith(status: CreateCommentStatus.imageUploadSuccess, imageUrl: url));
emit(state.copyWith(status: CreateCommentStatus.imageUploadSuccess, imageUrls: urls));
} catch (e) {
emit(state.copyWith(status: CreateCommentStatus.imageUploadFailure, message: e.toString()));
}
Expand Down
12 changes: 6 additions & 6 deletions lib/comment/cubit/create_comment_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class CreateCommentState extends Equatable {
const CreateCommentState({
this.status = CreateCommentStatus.initial,
this.commentView,
this.imageUrl,
this.imageUrls,
this.message,
});

Expand All @@ -26,26 +26,26 @@ class CreateCommentState extends Equatable {
/// The result of the created or edited comment
final CommentView? commentView;

/// The url of the uploaded image
final String? imageUrl;
/// The urls of the uploaded images
final List<String>? imageUrls;

/// The info or error message to be displayed as a snackbar
final String? message;

CreateCommentState copyWith({
required CreateCommentStatus status,
CommentView? commentView,
String? imageUrl,
List<String>? imageUrls,
String? message,
}) {
return CreateCommentState(
status: status,
commentView: commentView ?? this.commentView,
imageUrl: imageUrl ?? this.imageUrl,
imageUrls: imageUrls ?? this.imageUrls,
message: message ?? this.message,
);
}

@override
List<dynamic> get props => [status, commentView, imageUrl, message];
List<dynamic> get props => [status, commentView, imageUrls, message];
}
1 change: 1 addition & 0 deletions lib/comment/enums/comment_action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ enum CommentAction {
save(permissionType: PermissionType.user),
delete(permissionType: PermissionType.user),
report(permissionType: PermissionType.user),
read(permissionType: PermissionType.user), // This is used for inbox items (replies/mentions)

/// Moderator level post actions
remove(permissionType: PermissionType.moderator),
Expand Down
15 changes: 11 additions & 4 deletions lib/comment/view/create_comment_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,12 @@ class _CreateCommentPageState extends State<CreateCommentPage> {
/// The ID of the post we're responding to
int? postId;

// The ID of the comment we're responding to
/// The ID of the comment we're responding to
int? parentCommentId;

/// Contains the text that is currently being selected in the post/comment that we are replying to
String? replyViewSelection;

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -256,7 +259,8 @@ class _CreateCommentPageState extends State<CreateCommentPage> {

switch (state.status) {
case CreateCommentStatus.imageUploadSuccess:
_bodyTextController.text = _bodyTextController.text.replaceRange(_bodyTextController.selection.end, _bodyTextController.selection.end, "![](${state.imageUrl})");
String markdownImages = state.imageUrls?.map((url) => '![]($url)').join('\n\n') ?? '';
_bodyTextController.text = _bodyTextController.text.replaceRange(_bodyTextController.selection.end, _bodyTextController.selection.end, markdownImages);
break;
case CreateCommentStatus.imageUploadFailure:
showSnackbar(l10n.postUploadImageError, leadingIcon: Icons.warning_rounded, leadingIconColor: theme.colorScheme.errorContainer);
Expand Down Expand Up @@ -328,6 +332,7 @@ class _CreateCommentPageState extends State<CreateCommentPage> {
showExpandableButton: false,
selectable: true,
showReplyEditorButtons: true,
onSelectionChanged: (selection) => replyViewSelection = selection,
),
),
),
Expand All @@ -354,6 +359,7 @@ class _CreateCommentPageState extends State<CreateCommentPage> {
disableActions: true,
selectable: true,
showReplyEditorButtons: true,
onSelectionChanged: (selection) => replyViewSelection = selection,
),
),
),
Expand Down Expand Up @@ -466,9 +472,10 @@ class _CreateCommentPageState extends State<CreateCommentPage> {
customImageButtonAction: () async {
if (state.status == CreateCommentStatus.imageUploadInProgress) return;

String imagePath = await selectImageToUpload();
if (context.mounted) context.read<CreateCommentCubit>().uploadImage(imagePath);
List<String> imagesPath = await selectImagesToUpload(allowMultiple: true);
if (context.mounted) context.read<CreateCommentCubit>().uploadImages(imagesPath);
},
getAlternativeSelection: () => replyViewSelection,
),
),
),
Expand Down
15 changes: 8 additions & 7 deletions lib/community/pages/create_post_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class _CreatePostPageState extends State<CreatePostPage> {

if (widget.image != null) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
if (context.mounted) context.read<CreatePostCubit>().uploadImage(widget.image!.path, isPostImage: true);
if (context.mounted) context.read<CreatePostCubit>().uploadImages([widget.image!.path], isPostImage: true);
});
}

Expand Down Expand Up @@ -331,10 +331,11 @@ class _CreatePostPageState extends State<CreatePostPage> {

switch (state.status) {
case CreatePostStatus.imageUploadSuccess:
_bodyTextController.text = _bodyTextController.text.replaceRange(_bodyTextController.selection.end, _bodyTextController.selection.end, "![](${state.imageUrl})");
String markdownImages = state.imageUrls?.map((url) => '![]($url)').join('\n\n') ?? '';
_bodyTextController.text = _bodyTextController.text.replaceRange(_bodyTextController.selection.end, _bodyTextController.selection.end, markdownImages);
break;
case CreatePostStatus.postImageUploadSuccess:
_urlTextController.text = state.imageUrl ?? '';
_urlTextController.text = state.imageUrls?.first ?? '';
break;
case CreatePostStatus.imageUploadFailure:
case CreatePostStatus.postImageUploadFailure:
Expand Down Expand Up @@ -460,8 +461,8 @@ class _CreatePostPageState extends State<CreatePostPage> {
onPressed: () async {
if (state.status == CreatePostStatus.postImageUploadInProgress) return;

String imagePath = await selectImageToUpload();
if (context.mounted) context.read<CreatePostCubit>().uploadImage(imagePath, isPostImage: true);
List<String> imagesPath = await selectImagesToUpload();
if (context.mounted) context.read<CreatePostCubit>().uploadImages(imagesPath, isPostImage: true);
},
icon: state.status == CreatePostStatus.postImageUploadInProgress
? const SizedBox(
Expand Down Expand Up @@ -604,8 +605,8 @@ class _CreatePostPageState extends State<CreatePostPage> {
customImageButtonAction: () async {
if (state.status == CreatePostStatus.imageUploadInProgress) return;

String imagePath = await selectImageToUpload();
if (context.mounted) context.read<CreatePostCubit>().uploadImage(imagePath, isPostImage: false);
List<String> imagesPath = await selectImagesToUpload(allowMultiple: true);
if (context.mounted) context.read<CreatePostCubit>().uploadImages(imagesPath, isPostImage: false);
},
),
),
Expand Down
11 changes: 10 additions & 1 deletion lib/community/widgets/community_header.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'package:flutter/material.dart';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lemmy_api_client/v3.dart';
import 'package:thunder/feed/bloc/feed_bloc.dart';
import 'package:thunder/feed/utils/utils.dart';

import 'package:thunder/shared/avatars/community_avatar.dart';
import 'package:thunder/shared/full_name_widgets.dart';
Expand Down Expand Up @@ -29,6 +32,7 @@ class _CommunityHeaderState extends State<CommunityHeader> {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final FeedBloc feedBloc = context.watch<FeedBloc>();

return Material(
elevation: widget.showCommunitySidebar ? 5.0 : 0,
Expand Down Expand Up @@ -115,7 +119,7 @@ class _CommunityHeaderState extends State<CommunityHeader> {
useDisplayName: false,
),
const SizedBox(height: 8.0),
Row(
Wrap(
children: [
IconText(
icon: const Icon(Icons.people_rounded),
Expand All @@ -126,6 +130,11 @@ class _CommunityHeaderState extends State<CommunityHeader> {
icon: const Icon(Icons.calendar_month_rounded),
text: formatNumberToK(widget.getCommunityResponse.communityView.counts.usersActiveMonth),
),
const SizedBox(width: 8.0),
IconText(
icon: Icon(getSortIcon(feedBloc.state)),
text: getSortName(feedBloc.state),
),
],
),
],
Expand Down
4 changes: 4 additions & 0 deletions lib/core/enums/full_name.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ Widget generateSampleUserFullNameWidget(
NameThickness? instanceNameThickness,
NameColor? instanceNameColor,
TextStyle? textStyle,
bool? useDisplayName,
}) =>
UserFullNameWidget(
null,
Expand All @@ -121,6 +122,7 @@ Widget generateSampleUserFullNameWidget(
instanceNameThickness: instanceNameThickness,
instanceNameColor: instanceNameColor,
textStyle: textStyle,
useDisplayName: useDisplayName,
);

String generateSampleCommunityFullName(FullNameSeparator separator, bool useDisplayName) => generateCommunityFullName(
Expand All @@ -139,6 +141,7 @@ Widget generateSampleCommunityFullNameWidget(
NameThickness? instanceNameThickness,
NameColor? instanceNameColor,
TextStyle? textStyle,
bool? useDisplayName,
}) =>
CommunityFullNameWidget(
null,
Expand All @@ -151,6 +154,7 @@ Widget generateSampleCommunityFullNameWidget(
instanceNameThickness: instanceNameThickness,
instanceNameColor: instanceNameColor,
textStyle: textStyle,
useDisplayName: useDisplayName,
);

/// --- USERS ---
Expand Down
4 changes: 4 additions & 0 deletions lib/core/enums/local_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ enum LocalSettingsCategories {
floatingActionButton('floatingActionButton'),
accessibility('Accessibility'),
account('Account'),
userLabels('User Labels'),
about('About'),
debug('Debug'),
theming('Theming'),
Expand Down Expand Up @@ -253,6 +254,8 @@ enum LocalSettings {
subCategory: LocalSettingsSubCategories.names,
searchable: false),

userLabels(name: 'setting_user_labels', key: 'userLabels', category: LocalSettingsCategories.userLabels),

/// -------------------------- Gesture Related Settings --------------------------
// Sidebar Gesture Settings
sidebarBottomNavBarSwipeGesture(
Expand Down Expand Up @@ -476,6 +479,7 @@ extension LocalizationExt on AppLocalizations {
'videoAutoLoop': videoAutoLoop,
'videoAutoPlay': videoAutoPlay,
'videoDefaultPlaybackSpeed': videoDefaultPlaybackSpeed,
'userLabels': userLabels,
};

if (localizationMap.containsKey(key)) {
Expand Down
2 changes: 1 addition & 1 deletion lib/globals.dart
Original file line number Diff line number Diff line change
@@ -1 +1 @@
const String currentVersion = '0.5.0-1+58';
const String currentVersion = '0.5.0-2+59';
Loading

0 comments on commit da9b900

Please sign in to comment.